diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 2ab6b76..d824689 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -23,7 +23,7 @@ jobs: run: python -c "import sys; print(sys.version)" - name: Install Python build dependencies - run: python -m pip install --upgrade pip setuptools wheel + run: python -m pip install --upgrade pip setuptools wheel pytest - name: Install libfuse-dev and pkg-config run: sudo apt install -y libfuse-dev pkg-config @@ -34,5 +34,4 @@ jobs: - name: Test run: | sudo modprobe fuse - mkdir /tmp/foo && python example/hello.py /tmp/foo && [ "$(cat /tmp/foo/hello)" = "Hello World!" ] - mkdir /tmp/bar && python example/fioc.py /tmp/bar && [ -f /tmp/bar/fioc ] + python -m pytest diff --git a/example/fioc.py b/example/fioc.py index e4b81bb..485a8b0 100644 --- a/example/fioc.py +++ b/example/fioc.py @@ -71,6 +71,7 @@ def _IOWR(cls,t,nr,size): FIOC_GET_SIZE = IOCTL._IOR(ord('E'),0, struct.calcsize("L")); FIOC_SET_SIZE = IOCTL._IOW(ord('E'),1, struct.calcsize("L")); +print(f"{FIOC_GET_SIZE:x} {FIOC_SET_SIZE:x}") # object type FIOC_NONE = 0 FIOC_ROOT = 1 diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..90dddf3 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +markers = + fstype: Type of filesystem to mount diff --git a/tests/test_basic.py b/tests/test_basic.py new file mode 100644 index 0000000..380ce30 --- /dev/null +++ b/tests/test_basic.py @@ -0,0 +1,63 @@ +import os +import time +import sys +import struct +import subprocess +import pathlib +import tempfile +import pytest +import fcntl + +topdir = pathlib.Path(__file__).parent.parent + +@pytest.fixture +def filesystem(request): + fstype = request.node.get_closest_marker("fstype").args[0] + + with tempfile.TemporaryDirectory() as tmpdir: + st_dev = os.stat(tmpdir).st_dev + proc = subprocess.Popen([sys.executable, "-d", topdir / "example" / f"{fstype}.py", tmpdir], stdin=subprocess.DEVNULL) + + deadline = time.time() + 1 + while time.time() < deadline: + new_st_dev = os.stat(tmpdir).st_dev + if new_st_dev != st_dev: + break + time.sleep(.01) + if new_st_dev == st_dev: + proc.terminate() + raise RuntimeError("Filesystem did not mount within 1s") + + + yield pathlib.Path(tmpdir) + + subprocess.call(["fusermount", "-u", "-q", "-z", tmpdir]) + + deadline = time.time() + 1 + while time.time() < deadline: + result = proc.poll() + if result is not None: + if result != 0: + raise RuntimeError("Filesystem exited with an error: {result}") + return + time.sleep(.01) + + proc.terminate() + raise RuntimeError("Filesystem failed to exit within 1s after unmount") + +@pytest.mark.fstype("hello") +def test_hello(filesystem): + content = (filesystem / "hello").read_text(encoding="utf-8") + assert content == "Hello World!\n" + +@pytest.mark.fstype("fioc") +def test_fioc(filesystem): + FIOC_GET_SIZE, FIOC_SET_SIZE = 0x80084500, 0x40084501 + with (filesystem / "fioc").open("rb") as f: + b = struct.pack("L", 42) + fcntl.ioctl(f.fileno(), FIOC_SET_SIZE, b) + + b = bytearray(struct.calcsize('l')) + fcntl.ioctl(f.fileno(), FIOC_GET_SIZE, b) + assert struct.unpack("L", b)[0] == 42 +