Add SPDX header to python files with the 'py' extension in the test directory. Signed-off-by: Albert Esteve <aesteve@redhat.com>
265 lines
6.0 KiB
Python
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))
|