pyocf: Update tests after the API changes
Signed-off-by: Robert Baldyga <robert.baldyga@huawei.com> Signed-off-by: Michal Mielewczyk <michal.mielewczyk@huawei.com>
This commit is contained in:
parent
c5741df0ed
commit
be0ad8fe20
@ -88,19 +88,13 @@ class VolumeOps(Structure):
|
||||
class VolumeProperties(Structure):
|
||||
_fields_ = [
|
||||
("_name", c_char_p),
|
||||
("_io_priv_size", c_uint32),
|
||||
("_volume_priv_size", c_uint32),
|
||||
("_caps", VolumeCaps),
|
||||
("_io_ops", IoOps),
|
||||
("_deinit", c_char_p),
|
||||
("_ops_", VolumeOps),
|
||||
]
|
||||
|
||||
|
||||
class VolumeIoPriv(Structure):
|
||||
_fields_ = [("_data", c_void_p), ("_offset", c_uint64)]
|
||||
|
||||
|
||||
VOLUME_POISON = 0x13
|
||||
|
||||
|
||||
@ -243,11 +237,9 @@ class Volume:
|
||||
|
||||
Volume._props_[cls] = VolumeProperties(
|
||||
_name=str(cls.__name__).encode("ascii"),
|
||||
_io_priv_size=sizeof(VolumeIoPriv),
|
||||
_volume_priv_size=0,
|
||||
_caps=VolumeCaps(_atomic_writes=0),
|
||||
_ops_=cls.get_ops(),
|
||||
_io_ops=cls.get_io_ops(),
|
||||
_deinit=0,
|
||||
)
|
||||
return Volume._props_[cls]
|
||||
@ -267,22 +259,6 @@ class Volume:
|
||||
def get_by_uuid(cls, uuid):
|
||||
return cls._uuid_[uuid]
|
||||
|
||||
@staticmethod
|
||||
@IoOps.SET_DATA
|
||||
def _io_set_data(io, data, offset):
|
||||
io_priv = cast(OcfLib.getInstance().ocf_io_get_priv(io), POINTER(VolumeIoPriv))
|
||||
data = Data.get_instance(data)
|
||||
io_priv.contents._offset = offset
|
||||
io_priv.contents._data = data.handle
|
||||
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
@IoOps.GET_DATA
|
||||
def _io_get_data(io):
|
||||
io_priv = cast(OcfLib.getInstance().ocf_io_get_priv(io), POINTER(VolumeIoPriv))
|
||||
return io_priv.contents._data
|
||||
|
||||
def __init__(self, uuid=None):
|
||||
if uuid:
|
||||
if uuid in type(self)._uuid_:
|
||||
@ -499,8 +475,7 @@ class RamVolume(Volume):
|
||||
return
|
||||
|
||||
try:
|
||||
io_priv = cast(OcfLib.getInstance().ocf_io_get_priv(io), POINTER(VolumeIoPriv))
|
||||
offset = io_priv.contents._offset
|
||||
offset = OcfLib.getInstance().ocf_io_get_offset(io)
|
||||
|
||||
if io.contents._dir == IoDir.WRITE:
|
||||
src_ptr = cast(OcfLib.getInstance().ocf_io_get_data(io), c_void_p)
|
||||
@ -512,7 +487,6 @@ class RamVolume(Volume):
|
||||
src = self.data_ptr + io.contents._addr
|
||||
|
||||
memmove(dst, src, io.contents._bytes)
|
||||
io_priv.contents._offset += io.contents._bytes
|
||||
|
||||
io.contents._end(io, 0)
|
||||
except: # noqa E722
|
||||
@ -597,7 +571,6 @@ class ErrorDevice(Volume):
|
||||
def should_forward_io(self, rw, addr):
|
||||
if not self.armed:
|
||||
return True
|
||||
|
||||
direction = IoDir(rw)
|
||||
seq_no_match = (
|
||||
self.error_seq_no[direction] >= 0
|
||||
@ -633,7 +606,7 @@ class ErrorDevice(Volume):
|
||||
else:
|
||||
self.complete_submit_with_error(io)
|
||||
|
||||
def complete_forward_with_error(self, token, rw):
|
||||
def complete_forward_with_error(self, token, rw=IoDir.WRITE):
|
||||
self.error = True
|
||||
direction = IoDir(rw)
|
||||
self.stats["errors"][direction] += 1
|
||||
@ -646,16 +619,16 @@ class ErrorDevice(Volume):
|
||||
self.complete_forward_with_error(token, rw)
|
||||
|
||||
def do_forward_flush(self, token):
|
||||
if self.data_only or self.should_forward_io(0, 0):
|
||||
if self.data_only or self.should_forward_io(IoDir.WRITE, 0):
|
||||
self.vol.do_forward_flush(token)
|
||||
else:
|
||||
self.complete_forward_with_error(token, rw)
|
||||
self.complete_forward_with_error(token)
|
||||
|
||||
def do_forward_discard(self, token, addr, nbytes):
|
||||
if self.data_only or self.should_forward_io(0, addr):
|
||||
if self.data_only or self.should_forward_io(IoDir.WRITE, addr):
|
||||
self.vol.do_forward_discard(token, addr, nbytes)
|
||||
else:
|
||||
self.complete_forward_with_error(token, rw)
|
||||
self.complete_forward_with_error(token)
|
||||
|
||||
def arm(self):
|
||||
self.armed = True
|
||||
@ -812,7 +785,7 @@ class TraceDevice(Volume):
|
||||
|
||||
|
||||
lib = OcfLib.getInstance()
|
||||
lib.ocf_io_get_priv.restype = POINTER(VolumeIoPriv)
|
||||
lib.ocf_io_get_offset.restype = c_uint32
|
||||
lib.ocf_io_get_volume.argtypes = [c_void_p]
|
||||
lib.ocf_io_get_volume.restype = c_void_p
|
||||
lib.ocf_io_get_data.argtypes = [c_void_p]
|
||||
|
@ -4,10 +4,7 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
from ctypes import c_int, memmove, cast, c_void_p
|
||||
from enum import IntEnum
|
||||
from itertools import product
|
||||
import random
|
||||
from ctypes import memmove, cast, c_void_p, c_uint64
|
||||
|
||||
import pytest
|
||||
|
||||
@ -18,6 +15,7 @@ from pyocf.types.volume_core import CoreVolume
|
||||
from pyocf.types.data import Data
|
||||
from pyocf.types.io import IoDir, Sync
|
||||
from pyocf.utils import Size
|
||||
from pyocf.ocf import OcfLib
|
||||
|
||||
|
||||
def __io(io, data):
|
||||
@ -48,19 +46,19 @@ class FlagsValVolume(RamVolume):
|
||||
self.fail = False
|
||||
super().__init__(size)
|
||||
|
||||
def set_check(self, check):
|
||||
self.check = check
|
||||
def set_check(self):
|
||||
self.check = True
|
||||
self.fail = True
|
||||
|
||||
def submit_io(self, io):
|
||||
def do_forward_io(self, token, rw, addr, nbytes, offset):
|
||||
if self.check:
|
||||
flags = io.contents._flags
|
||||
if flags != self.flags:
|
||||
self.fail = True
|
||||
super().submit_io(io)
|
||||
flags = lib.ocf_forward_get_flags(token)
|
||||
if flags == self.flags:
|
||||
self.fail = False
|
||||
super().do_forward_io(token, rw, addr, nbytes, offset)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cache_mode", CacheMode)
|
||||
def test_io_flags(pyocf_ctx, cache_mode):
|
||||
def test_io_flags(pyocf_ctx):
|
||||
"""
|
||||
Verify that I/O flags provided at the top volume interface
|
||||
are propagated down to bottom volumes for all associated
|
||||
@ -74,44 +72,54 @@ def test_io_flags(pyocf_ctx, cache_mode):
|
||||
|
||||
pyocf_ctx.register_volume_type(FlagsValVolume)
|
||||
|
||||
cache_device = FlagsValVolume(Size.from_MiB(50), flags)
|
||||
cache_device = FlagsValVolume(Size.from_MiB(50), 0)
|
||||
core_device = FlagsValVolume(Size.from_MiB(50), flags)
|
||||
|
||||
cache = Cache.start_on_device(cache_device, cache_mode=cache_mode)
|
||||
cache = Cache.start_on_device(cache_device, cache_mode=CacheMode.WB)
|
||||
core = Core.using_device(core_device)
|
||||
|
||||
cache.add_core(core)
|
||||
vol = CoreVolume(core)
|
||||
|
||||
cache_device.set_check(True)
|
||||
core_device.set_check(True)
|
||||
def set_check():
|
||||
cache_device.set_check()
|
||||
core_device.set_check()
|
||||
|
||||
# write miss
|
||||
set_check()
|
||||
io_to_exp_obj(vol, block_size * 0, block_size, data, 0, IoDir.WRITE, flags)
|
||||
assert not cache_device.fail
|
||||
assert not core_device.fail
|
||||
|
||||
# read miss
|
||||
set_check()
|
||||
io_to_exp_obj(vol, block_size * 1, block_size, data, 0, IoDir.READ, flags)
|
||||
assert not cache_device.fail
|
||||
assert not core_device.fail
|
||||
|
||||
# "dirty" read hit
|
||||
set_check()
|
||||
io_to_exp_obj(vol, block_size * 0, block_size, data, 0, IoDir.READ, flags)
|
||||
assert not cache_device.fail
|
||||
assert not core_device.fail
|
||||
|
||||
# "clean" read hit
|
||||
set_check()
|
||||
io_to_exp_obj(vol, block_size * 1, block_size, data, 0, IoDir.READ, flags)
|
||||
assert not cache_device.fail
|
||||
assert not core_device.fail
|
||||
|
||||
cache.change_cache_mode(CacheMode.WT)
|
||||
|
||||
# "dirty" write hit
|
||||
set_check()
|
||||
io_to_exp_obj(vol, block_size * 0, block_size, data, 0, IoDir.WRITE, flags)
|
||||
assert not cache_device.fail
|
||||
assert not core_device.fail
|
||||
|
||||
# "clean" write hit
|
||||
set_check()
|
||||
io_to_exp_obj(vol, block_size * 1, block_size, data, 0, IoDir.WRITE, flags)
|
||||
assert not cache_device.fail
|
||||
assert not core_device.fail
|
||||
|
||||
|
||||
lib = OcfLib.getInstance()
|
||||
lib.ocf_forward_get_flags.argtypes = [c_uint64]
|
||||
lib.ocf_forward_get_flags.restype = c_uint64
|
||||
|
@ -12,7 +12,7 @@ from threading import Event
|
||||
from collections import namedtuple
|
||||
|
||||
from pyocf.ocf import OcfLib
|
||||
from pyocf.types.volume import RamVolume, ErrorDevice, TraceDevice, IoFlags, VolumeIoPriv
|
||||
from pyocf.types.volume import RamVolume, ErrorDevice, TraceDevice, IoFlags
|
||||
from pyocf.types.cvolume import CVolume
|
||||
from pyocf.types.data import Data
|
||||
from pyocf.types.io import IoDir
|
||||
@ -287,19 +287,25 @@ def test_io_propagation_basic(pyocf_ctx):
|
||||
ret = cvol_submit_data_io(cvol, addr, io_size)
|
||||
assert ret == 0
|
||||
|
||||
ret = cvol_submit_flush_io(cvol, addr, io_size, IoFlags.FLUSH)
|
||||
ret = cvol_submit_flush_io(cvol, addr, io_size)
|
||||
assert ret == 0
|
||||
|
||||
ret = cvol_submit_discard_io(cvol, addr, io_size)
|
||||
assert ret == 0
|
||||
|
||||
for io_type in TraceDevice.IoType:
|
||||
ios = io_trace[vol][io_type]
|
||||
assert len(ios) == 1
|
||||
io = ios[0]
|
||||
assert io.dir == IoDir.WRITE
|
||||
assert io.addr == addr.B - int(vol_begin[i])
|
||||
assert io.bytes == io_size.B
|
||||
ios = io_trace[vol][TraceDevice.IoType.Data]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].dir == IoDir.WRITE
|
||||
assert ios[0].addr == addr.B - int(vol_begin[i])
|
||||
assert ios[0].bytes == io_size.B
|
||||
|
||||
ios = io_trace[vol][TraceDevice.IoType.Flush]
|
||||
assert len(ios) == i + 1
|
||||
|
||||
ios = io_trace[vol][TraceDevice.IoType.Discard]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].addr == addr.B - int(vol_begin[i])
|
||||
assert ios[0].bytes == io_size.B
|
||||
|
||||
cvol.close()
|
||||
cvol.destroy()
|
||||
@ -355,27 +361,36 @@ def test_io_propagation_cross_boundary(pyocf_ctx):
|
||||
ret = cvol_submit_data_io(cvol, addr, io_size)
|
||||
assert ret == 0
|
||||
|
||||
ret = cvol_submit_flush_io(cvol, addr, io_size, IoFlags.FLUSH)
|
||||
ret = cvol_submit_flush_io(cvol, addr, io_size)
|
||||
assert ret == 0
|
||||
|
||||
ret = cvol_submit_discard_io(cvol, addr, io_size)
|
||||
assert ret == 0
|
||||
|
||||
for io_type in TraceDevice.IoType:
|
||||
ios1 = io_trace[vols[i]][io_type]
|
||||
ios2 = io_trace[vols[i + 1]][io_type]
|
||||
ios1 = io_trace[vols[i]][TraceDevice.IoType.Data]
|
||||
ios2 = io_trace[vols[i + 1]][TraceDevice.IoType.Data]
|
||||
assert len(ios1) == 1
|
||||
assert ios1[0].dir == IoDir.WRITE
|
||||
assert ios1[0].addr == int(vols[i].vol.size - (io_size / 2))
|
||||
assert ios1[0].bytes == io_size.B / 2
|
||||
assert len(ios2) == 1
|
||||
assert ios2[0].dir == IoDir.WRITE
|
||||
assert ios2[0].addr == 0
|
||||
assert ios2[0].bytes == io_size.B / 2
|
||||
|
||||
assert len(ios1) == 1
|
||||
io = ios1[0]
|
||||
assert io.dir == IoDir.WRITE
|
||||
assert io.addr == int(vols[i].vol.size - (io_size / 2))
|
||||
assert io.bytes == io_size.B / 2
|
||||
ios1 = io_trace[vols[i]][TraceDevice.IoType.Flush]
|
||||
ios2 = io_trace[vols[i + 1]][TraceDevice.IoType.Flush]
|
||||
assert len(ios1) == 1
|
||||
assert len(ios2) == 1
|
||||
|
||||
assert len(ios2) == 1
|
||||
io = ios2[0]
|
||||
assert io.dir == IoDir.WRITE
|
||||
assert io.addr == 0
|
||||
assert io.bytes == io_size.B / 2
|
||||
ios1 = io_trace[vols[i]][TraceDevice.IoType.Discard]
|
||||
ios2 = io_trace[vols[i + 1]][TraceDevice.IoType.Discard]
|
||||
assert len(ios1) == 1
|
||||
assert ios1[0].addr == int(vols[i].vol.size - (io_size / 2))
|
||||
assert ios1[0].bytes == io_size.B / 2
|
||||
assert len(ios2) == 1
|
||||
assert ios2[0].addr == 0
|
||||
assert ios2[0].bytes == io_size.B / 2
|
||||
|
||||
cvol.close()
|
||||
cvol.destroy()
|
||||
@ -483,25 +498,51 @@ def test_io_propagation_multiple_subvolumes(pyocf_ctx, rand_seed):
|
||||
ret = cvol_submit_data_io(cvol, addr, size)
|
||||
assert ret == 0
|
||||
|
||||
ret = cvol_submit_flush_io(cvol, addr, size, IoFlags.FLUSH)
|
||||
ret = cvol_submit_flush_io(cvol, addr, size)
|
||||
assert ret == 0
|
||||
|
||||
ret = cvol_submit_discard_io(cvol, addr, size)
|
||||
assert ret == 0
|
||||
|
||||
for vol in middle:
|
||||
for io in io_trace[vol].values():
|
||||
assert len(io) == 1
|
||||
assert io[0].addr == 0
|
||||
assert io[0].bytes == int(vol.vol.size)
|
||||
ios = io_trace[vol][TraceDevice.IoType.Data]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].addr == 0
|
||||
assert ios[0].bytes == int(vol.vol.size)
|
||||
|
||||
for io in io_trace[first].values():
|
||||
assert io[0].addr == int(start_offset)
|
||||
assert io[0].bytes == int(vol_size - start_offset)
|
||||
ios = io_trace[first][TraceDevice.IoType.Data]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].addr == int(start_offset)
|
||||
assert ios[0].bytes == int(vol_size - start_offset)
|
||||
|
||||
for io in io_trace[last].values():
|
||||
assert io[0].addr == 0
|
||||
assert io[0].bytes == int(end_offset)
|
||||
ios = io_trace[last][TraceDevice.IoType.Data]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].addr == 0
|
||||
assert ios[0].bytes == int(end_offset)
|
||||
|
||||
ios = io_trace[vol][TraceDevice.IoType.Flush]
|
||||
assert len(ios) == 1
|
||||
|
||||
ios = io_trace[first][TraceDevice.IoType.Flush]
|
||||
assert len(ios) == 1
|
||||
|
||||
ios = io_trace[last][TraceDevice.IoType.Flush]
|
||||
assert len(ios) == 1
|
||||
|
||||
ios = io_trace[vol][TraceDevice.IoType.Discard]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].addr == 0
|
||||
assert ios[0].bytes == int(vol.vol.size)
|
||||
|
||||
ios = io_trace[first][TraceDevice.IoType.Discard]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].addr == int(start_offset)
|
||||
assert ios[0].bytes == int(vol_size - start_offset)
|
||||
|
||||
ios = io_trace[last][TraceDevice.IoType.Discard]
|
||||
assert len(ios) == 1
|
||||
assert ios[0].addr == 0
|
||||
assert ios[0].bytes == int(end_offset)
|
||||
|
||||
cvol.close()
|
||||
cvol.destroy()
|
||||
@ -538,16 +579,16 @@ def test_io_completion(pyocf_ctx, rand_seed):
|
||||
self.pending_ios = []
|
||||
self.io_submitted = Event()
|
||||
|
||||
def do_submit_io(self, io):
|
||||
self.pending_ios.append(("io", io))
|
||||
def do_forward_io(self, token, rw, addr, nbytes, offset):
|
||||
self.pending_ios.append(("io", token, rw, addr, nbytes, offset))
|
||||
self.io_submitted.set()
|
||||
|
||||
def do_submit_flush(self, flush):
|
||||
self.pending_ios.append(("flush", flush))
|
||||
def do_forward_flush(self, token):
|
||||
self.pending_ios.append(("flush", token))
|
||||
self.io_submitted.set()
|
||||
|
||||
def do_submit_discard(self, discard):
|
||||
self.pending_ios.append(("discard", discard))
|
||||
def do_forward_discard(self, token, addr, nbytes):
|
||||
self.pending_ios.append(("discard", token, addr, nbytes))
|
||||
self.io_submitted.set()
|
||||
|
||||
def wait_submitted(self):
|
||||
@ -558,13 +599,13 @@ def test_io_completion(pyocf_ctx, rand_seed):
|
||||
if not self.pending_ios:
|
||||
return False
|
||||
|
||||
io_type, io = self.pending_ios.pop()
|
||||
io_type, token, *params = self.pending_ios.pop()
|
||||
if io_type == "io":
|
||||
super().do_submit_io(io)
|
||||
super().do_forward_io(token, *params)
|
||||
elif io_type == "flush":
|
||||
super().do_submit_flush(io)
|
||||
super().do_forward_flush(token)
|
||||
elif io_type == "discard":
|
||||
super().do_submit_discard(io)
|
||||
super().do_forward_discard(token, *params)
|
||||
else:
|
||||
assert False
|
||||
|
||||
@ -586,14 +627,18 @@ def test_io_completion(pyocf_ctx, rand_seed):
|
||||
addr = vol_size / 2
|
||||
size = (subvol_count - 1) * vol_size
|
||||
|
||||
for op, flags in [("submit", 0), ("submit_flush", IoFlags.FLUSH), ("submit_discard", 0)]:
|
||||
for op, cnt in [
|
||||
("submit", subvol_count),
|
||||
("submit_flush", len(vols)),
|
||||
("submit_discard", subvol_count)
|
||||
]:
|
||||
io = cvol.new_io(
|
||||
queue=None,
|
||||
addr=addr,
|
||||
length=size,
|
||||
direction=IoDir.WRITE,
|
||||
io_class=0,
|
||||
flags=flags,
|
||||
flags=0,
|
||||
)
|
||||
completion = OcfCompletion([("err", c_int)])
|
||||
io.callback = completion.callback
|
||||
@ -604,7 +649,7 @@ def test_io_completion(pyocf_ctx, rand_seed):
|
||||
submit_fn = getattr(io, op)
|
||||
submit_fn()
|
||||
|
||||
pending_vols = vols[:subvol_count]
|
||||
pending_vols = vols[:cnt]
|
||||
for v in pending_vols:
|
||||
v.wait_submitted()
|
||||
|
||||
@ -674,7 +719,7 @@ def test_io_error(pyocf_ctx, rand_seed):
|
||||
assert ret == -OcfErrorCode.OCF_ERR_IO
|
||||
|
||||
# verify flush properly propagated
|
||||
ret = cvol_submit_flush_io(cvol, addr, size, IoFlags.FLUSH)
|
||||
ret = cvol_submit_flush_io(cvol, addr, size)
|
||||
assert ret == -OcfErrorCode.OCF_ERR_IO
|
||||
|
||||
# verdiscard discard properly propagated
|
||||
|
Loading…
Reference in New Issue
Block a user