ovirt-imageio/test/stats_test.py
Albert Esteve fc6e58d9e6 reuse: addheader test/*.py
Add SPDX header to python files with
the 'py' extension in the test directory.

Signed-off-by: Albert Esteve <aesteve@redhat.com>
2022-10-18 13:04:20 +02:00

265 lines
6.0 KiB
Python

# SPDX-FileCopyrightText: Red Hat, Inc.
# SPDX-License-Identifier: GPL-2.0-or-later
import pytest
from ovirt_imageio._internal import stats
class FakeTime:
def __init__(self):
self.value = 0
def __call__(self):
return self.value
# Ccorrect usage
def test_empty():
c = stats.Clock()
assert str(c) == ""
def test_stop_returns_elapsed_time():
fake_time = FakeTime()
c = stats.Clock(fake_time)
c.start("read")
fake_time.value += 1
assert c.stop("read") == 1
c.start("read")
fake_time.value += 2
assert c.stop("read") == 2
def test_measure():
fake_time = FakeTime()
c = stats.Clock(fake_time)
c.start("total")
c.start("read")
fake_time.value += 1
c.stop("read")
c.start("write")
fake_time.value += 1
c.stop("write")
c.start("sync")
fake_time.value += 1
c.stop("sync")
c.stop("total")
assert str(c) == (
"[total 1 ops, 3.000000 s] "
"[read 1 ops, 1.000000 s] "
"[write 1 ops, 1.000000 s] "
"[sync 1 ops, 1.000000 s]"
)
def test_measure_multiple():
fake_time = FakeTime()
c = stats.Clock(fake_time)
c.start("total")
c.start("read")
fake_time.value += 1
c.stop("read")
c.start("write")
fake_time.value += 1
c.stop("write")
c.start("read")
fake_time.value += 1
c.stop("read")
c.start("write")
fake_time.value += 1
c.stop("write")
c.start("sync")
fake_time.value += 1
c.stop("sync")
c.stop("total")
assert str(c) == (
"[total 1 ops, 5.000000 s] "
"[read 2 ops, 2.000000 s] "
"[write 2 ops, 2.000000 s] "
"[sync 1 ops, 1.000000 s]"
)
def test_running():
fake_time = FakeTime()
c = stats.Clock(fake_time)
c.start("total")
fake_time.value += 3
c.start("read")
fake_time.value += 4
c.stop("read")
# Since total was not stopped, the operation is not counted.
assert str(c) == "[total 0 ops, 7.000000 s] [read 1 ops, 4.000000 s]"
def test_bytes():
fake_time = FakeTime()
c = stats.Clock(fake_time)
c.start("total")
# Using start()/stop().
s = c.start("read")
s.bytes += 512 * 1024**2
fake_time.value += 1
c.stop("read")
s = c.start("write")
s.bytes += 200 * 1024**2
fake_time.value += 1
c.stop("write")
# Using run().
with c.run("read") as s:
s.bytes += 512 * 1024**2
fake_time.value += 1
with c.run("write") as s:
s.bytes += 200 * 1024**2
fake_time.value += 1
with c.run("sync"):
fake_time.value += 1
c.stop("total")
assert str(c) == (
"[total 1 ops, 5.000000 s] "
"[read 2 ops, 2.000000 s, 1.00 GiB, 512.00 MiB/s] "
"[write 2 ops, 2.000000 s, 400.00 MiB, 200.00 MiB/s] "
"[sync 1 ops, 1.000000 s]"
)
def test_null_clock():
c = stats.NullClock()
# This clock records nothing...
with c.run("total"):
with c.run("read") as s:
s.bytes += 4096
# bytes value is dropped...
assert s.bytes == 0
with c.run("sync"):
pass
# And always return empty string.
assert str(c) == ""
def test_error_before_stop():
fake_time = FakeTime()
c = stats.Clock(fake_time)
c.start("read")
fake_time.value += 1
# User code fails here, before we increase bytes and call stop().
# Since read was not stopped the operation is not counted...
assert str(c) == "[read 0 ops, 1.000000 s]"
# And we cannot start this operation again.
with pytest.raises(RuntimeError):
c.start("read")
# We can abort the operation to continue to use this clock.
fake_time.value += 1
c.abort("read")
assert str(c) == "[read 0 ops, 2.000000 s]"
def test_error_in_run():
fake_time = FakeTime()
c = stats.Clock(fake_time)
with pytest.raises(RuntimeError):
with c.run("read") as s:
fake_time.value += 1
raise RuntimeError("fake error")
s.bytes += 512 * 1024**2
# First read failed, so bytes is not set and the operation is not counted.
assert str(c) == "[read 0 ops, 1.000000 s]"
# However clock was stopped, so next read can succeed.
with c.run("read") as s:
fake_time.value += 1
s.bytes += 512 * 1024**2
# Bytes value is set now so we report total and rate values.
assert str(c) == "[read 1 ops, 2.000000 s, 512.00 MiB, 256.00 MiB/s]"
# Inccorrect usage
def test_start_twice():
c = stats.Clock()
c.start("started")
with pytest.raises(RuntimeError):
c.start("started")
def test_stop_twice():
c = stats.Clock()
c.start("stopped")
c.stop("stopped")
with pytest.raises(RuntimeError):
c.stop("stopped")
def test_stop_missing():
c = stats.Clock()
with pytest.raises(RuntimeError):
c.stop("missing")
def test_run():
fake_time = FakeTime()
c = stats.Clock(fake_time)
with c.run("total"):
with c.run("a"):
fake_time.value += 4
with c.run("b"):
fake_time.value += 3
assert str(c) == (
"[total 1 ops, 7.000000 s] "
"[a 1 ops, 4.000000 s] "
"[b 1 ops, 3.000000 s]"
)
def test_run_recursive():
c = stats.Clock()
with c.run("started"):
with pytest.raises(RuntimeError):
with c.run("started"):
pass
@pytest.mark.benchmark
@pytest.mark.parametrize("clock", [
pytest.param(stats.Clock(), id="clock"),
pytest.param(stats.NullClock(), id="null-clock"),
])
def test_benchmark(clock):
test = stats.Clock()
with test.run("total"):
clock.start("connection")
# We have seen 66,000 requests per single upload with virt-v2v.
for i in range(50000):
clock.start("request")
with clock.run("read") as s:
s.bytes += 2 * 1024**2
with clock.run("write") as s:
s.bytes += 2 * 1024**2
clock.stop("request")
clock.stop("connection")
print("{} {}".format(test, clock))