181 lines
6.5 KiB
Python
181 lines
6.5 KiB
Python
# Copyright 2026 Cloudbase Solutions Srl
|
|
# All Rights Reserved.
|
|
|
|
"""Compare writes and reads from VDDK with openvixdisklib."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from openvixdisklib import openvixdisklib as open_vix
|
|
from tests.integration import vixdisklib
|
|
from tests.integration.base import (
|
|
SECTOR_AT_1GB,
|
|
SECTOR_AT_5GB,
|
|
SECTOR_SIZE,
|
|
LabEnv,
|
|
pattern_bytes,
|
|
)
|
|
|
|
_64MIB = 64 * 1024 * 1024
|
|
_5GIB = SECTOR_AT_5GB * SECTOR_SIZE
|
|
|
|
|
|
def _connect_extra(lab: LabEnv, module: Any) -> dict[str, Any] | None:
|
|
"""Return extra ``connect`` kwargs needed by ``module``."""
|
|
if module is open_vix:
|
|
return {"allow_untrusted": lab.allow_untrusted}
|
|
return None
|
|
|
|
|
|
def _write_sectors(
|
|
lab: LabEnv, module: Any, payloads: dict[int, bytes], flags: int = 0
|
|
) -> None:
|
|
"""Write one sector at each index using a vixdisklib-compatible module."""
|
|
handle = module.VixDiskLibHandle(
|
|
vixdisklib_compatibility_version="8.0", config_path=None
|
|
)
|
|
buf = module.get_buffer(SECTOR_SIZE)
|
|
kwargs = lab.vixdisklib_connect_kwargs(_connect_extra(lab, module))
|
|
with (
|
|
handle.connect(**kwargs) as conn,
|
|
handle.open(conn, lab.disk_path, flags=flags) as disk,
|
|
):
|
|
for start, data in payloads.items():
|
|
buf[:SECTOR_SIZE] = data
|
|
handle.write(disk, start, 1, buf)
|
|
|
|
|
|
def _read_sectors(
|
|
lab: LabEnv, module: Any, sectors: tuple[int, ...], flags: int = 0
|
|
) -> dict[int, bytes]:
|
|
"""Read one sector at each index using a vixdisklib-compatible module."""
|
|
handle = module.VixDiskLibHandle(
|
|
vixdisklib_compatibility_version="8.0", config_path=None
|
|
)
|
|
buf = module.get_buffer(SECTOR_SIZE)
|
|
result: dict[int, bytes] = {}
|
|
kwargs = lab.vixdisklib_connect_kwargs(_connect_extra(lab, module))
|
|
with (
|
|
handle.connect(**kwargs) as conn,
|
|
handle.open(conn, lab.disk_path, flags=flags) as disk,
|
|
):
|
|
for start in sectors:
|
|
buf[:SECTOR_SIZE] = b"\xa5" * SECTOR_SIZE
|
|
handle.read(disk, start, 1, buf)
|
|
result[start] = buf.raw[:SECTOR_SIZE]
|
|
return result
|
|
|
|
|
|
def _assert_both_read(
|
|
lab: LabEnv, sectors: tuple[int, ...], expected: dict[int, bytes], flags: int = 0
|
|
) -> None:
|
|
vddk_data = _read_sectors(lab, vixdisklib, sectors, flags=flags)
|
|
replacement = _read_sectors(lab, open_vix, sectors, flags=flags)
|
|
for start in sectors:
|
|
assert vddk_data[start] == expected[start], f"VDDK mismatch at sector {start}"
|
|
assert replacement[start] == expected[start], (
|
|
f"openvixdisklib mismatch at sector {start}"
|
|
)
|
|
|
|
|
|
def _write_bytes(
|
|
lab: LabEnv, module: Any, start_byte: int, data: bytes, flags: int = 0
|
|
) -> None:
|
|
"""Write ``data`` starting at ``start_byte`` using ``module``."""
|
|
handle = module.VixDiskLibHandle(
|
|
vixdisklib_compatibility_version="8.0", config_path=None
|
|
)
|
|
buf = module.get_buffer(len(data))
|
|
buf[: len(data)] = data
|
|
kwargs = lab.vixdisklib_connect_kwargs(_connect_extra(lab, module))
|
|
with (
|
|
handle.connect(**kwargs) as conn,
|
|
handle.open(conn, lab.disk_path, flags=flags) as disk,
|
|
):
|
|
handle.write(disk, start_byte // SECTOR_SIZE, len(data) // SECTOR_SIZE, buf)
|
|
|
|
|
|
def _read_bytes(
|
|
lab: LabEnv, module: Any, start_byte: int, nbytes: int, flags: int = 0
|
|
) -> bytes:
|
|
"""Read ``nbytes`` starting at ``start_byte`` using ``module``."""
|
|
handle = module.VixDiskLibHandle(
|
|
vixdisklib_compatibility_version="8.0", config_path=None
|
|
)
|
|
buf = module.get_buffer(nbytes)
|
|
buf[:nbytes] = b"\xa5" * nbytes
|
|
kwargs = lab.vixdisklib_connect_kwargs(_connect_extra(lab, module))
|
|
with (
|
|
handle.connect(**kwargs) as conn,
|
|
handle.open(conn, lab.disk_path, flags=flags) as disk,
|
|
):
|
|
handle.read(disk, start_byte // SECTOR_SIZE, nbytes // SECTOR_SIZE, buf)
|
|
return buf.raw[:nbytes]
|
|
|
|
|
|
def _assert_both_read_bytes(
|
|
lab: LabEnv, start_byte: int, expected: bytes, flags: int = 0
|
|
) -> None:
|
|
vddk_data = _read_bytes(lab, vixdisklib, start_byte, len(expected), flags=flags)
|
|
replacement = _read_bytes(lab, open_vix, start_byte, len(expected), flags=flags)
|
|
assert vddk_data == expected, f"VDDK mismatch at byte offset {start_byte}"
|
|
assert replacement == expected, (
|
|
f"openvixdisklib mismatch at byte offset {start_byte}"
|
|
)
|
|
|
|
|
|
class TestCrosscheck:
|
|
@pytest.mark.parametrize(
|
|
"open_flags",
|
|
[0, vixdisklib.VIXDISKLIB_FLAG_OPEN_COMPRESSION_FASTLZ],
|
|
ids=["plain", "fastlz"],
|
|
)
|
|
def test_openvixdisklib_matches_vddk_sectors(
|
|
self, lab: LabEnv, vddk: None, open_flags: int
|
|
) -> None:
|
|
"""Writes from either library must be visible to both readers."""
|
|
sectors = (0, 1, SECTOR_AT_1GB, SECTOR_AT_5GB)
|
|
vddk_payloads = {
|
|
0: pattern_bytes(SECTOR_SIZE, b"XCHK-VDDK-S0"),
|
|
1: pattern_bytes(SECTOR_SIZE, b"XCHK-VDDK-S1"),
|
|
SECTOR_AT_1GB: pattern_bytes(SECTOR_SIZE, b"XCHK-VDDK-1G"),
|
|
SECTOR_AT_5GB: pattern_bytes(SECTOR_SIZE, b"XCHK-VDDK-5G"),
|
|
}
|
|
_write_sectors(lab, vixdisklib, vddk_payloads, flags=open_flags)
|
|
_assert_both_read(lab, sectors, vddk_payloads, flags=open_flags)
|
|
|
|
ovdl_payloads = {
|
|
0: pattern_bytes(SECTOR_SIZE, b"XCHK-OVDL-S0"),
|
|
1: pattern_bytes(SECTOR_SIZE, b"XCHK-OVDL-S1"),
|
|
SECTOR_AT_1GB: pattern_bytes(SECTOR_SIZE, b"XCHK-OVDL-1G"),
|
|
SECTOR_AT_5GB: pattern_bytes(SECTOR_SIZE, b"XCHK-OVDL-5G"),
|
|
}
|
|
_write_sectors(lab, open_vix, ovdl_payloads, flags=open_flags)
|
|
_assert_both_read(lab, sectors, ovdl_payloads, flags=open_flags)
|
|
|
|
@pytest.mark.slow
|
|
@pytest.mark.parametrize(
|
|
"open_flags",
|
|
[0, vixdisklib.VIXDISKLIB_FLAG_OPEN_COMPRESSION_FASTLZ],
|
|
ids=["plain", "fastlz"],
|
|
)
|
|
def test_openvixdisklib_matches_vddk_64mib_at_5gib(
|
|
self, lab: LabEnv, vddk: None, open_flags: int
|
|
) -> None:
|
|
"""Write 64 MiB of random data at a 5 GiB offset and compare both libraries.
|
|
|
|
The 5 GiB start is past the 4 GiB (2**32) byte boundary, so a
|
|
32-bit disk offset would wrap and fail the comparison.
|
|
"""
|
|
vddk_payload = os.urandom(_64MIB)
|
|
_write_bytes(lab, vixdisklib, _5GIB, vddk_payload, flags=open_flags)
|
|
_assert_both_read_bytes(lab, _5GIB, vddk_payload, flags=open_flags)
|
|
|
|
ovdl_payload = os.urandom(_64MIB)
|
|
_write_bytes(lab, open_vix, _5GIB, ovdl_payload, flags=open_flags)
|
|
_assert_both_read_bytes(lab, _5GIB, ovdl_payload, flags=open_flags)
|