Commit 0bf38fb8 authored by Julius Athenstaedt's avatar Julius Athenstaedt
Browse files

test python bindings with example program

parent 1779c028
Loading
Loading
Loading
Loading
Loading
+113 −0
Original line number Diff line number Diff line
import gkfs_python as gk
import os
import stat as st

def main():
    gk.init()

    path = "/testfile"
    path_create_delete = "/testfile2"
    symlink_path = "/test_symlink"
    renamed_path = "/testfile_renamed"

    fd = gk.create(path_create_delete, 0o644)
    print(f"Created file: {path_create_delete}, fd={fd}")
    gk.remove(path_create_delete)
    print(f"Deleted file: {path_create_delete}, fd={fd}")

    fd = gk.create(path, 0o644)
    fd = gk.open(path, os.O_CREAT | os.O_RDWR, st.S_IRUSR | st.S_IWUSR)
    print(f"Open file: {path}, fd={fd}")

    print(gk.get_file_list("/"))

    gk.write(fd, b"Test GekkoFS!")
    print(f"write success")

    gk.lseek(fd, 0, os.SEEK_SET)
    print(f"lseek success")

    data = gk.read(fd, 16)
    print(f"Read data: {data}")

    gk.pwrite(fd, b"Hello", 0)
    print(f"pwrite success")

    gk.lseek(fd, 0, os.SEEK_SET)
    data = gk.read(fd, 16)
    print(f"Read data: {data}")

    read_data = gk.pread(fd, 5, 5)
    print(f"Pread data: {read_data}")

    gk.lseek(fd, 0, os.SEEK_SET)
    # TODO
    #gk.writev(fd, [b"ABC", b"DEF"])

    data_readv = gk.readv(fd, 2)
    print(f"Readv data: {data_readv}")

    # TODO
    #gk.pwritev(fd, [b"ghi", b"jkl"], 3)

    data_preadv = gk.preadv(fd, 2, 0)
    print(f"Preadv data: {data_preadv}")

    dup_fd = gk.dup(fd)
    dup2_fd = gk.dup2(fd, dup_fd + 1)
    print(f"Duplicated fds: {dup_fd}, {dup2_fd}")

    gk.fsync(fd)

    res, stat = gk.stat(path, True, False)
    print(f"Stat result: {stat}")

    res, statx = gk.statx(-1, path, 0, 0xFFF, True)
    print(f"Statx result: {statx}")

    accessible = gk.access(path, os.R_OK | os.W_OK)
    print(f"Access check (R_OK|W_OK): {accessible}")

    file_list = gk.get_file_list("/")
    print(f"File list: {file_list}")

    gk.close(fd)
    gk.close(dup_fd)
    gk.close(dup2_fd)

    gk.truncate(path, 5)

    addr = gk.mmap(0, 4096, 1 | 2, 2, gk.open(path, os.O_RDWR, 0), 0)
    gk.msync(addr, 4096, 0)
    gk.munmap(addr, 4096)
    print("mmap/msync/munmap done")

    # Symlink if available
    try:
        gk.mk_symlink(path, symlink_path)
        target = gk.readlink(symlink_path, 1024)
        print(f"Symlink points to: {target}")
    except Exception:
        print("Symlink not supported or failed.")

    # Rename if available
    try:
        gk.rename(path, renamed_path)
        print(f"Renamed {path} to {renamed_path}")
    except Exception:
        print("Rename not supported or failed.")

    file_list = gk.get_file_list("/")
    print(f"File list: {file_list}")

    gk.remove(renamed_path)
    print(f"Removed {renamed_path}")

    file_list = gk.get_file_list("/")
    print(f"File list: {file_list}")

    gk.end()

if __name__ == "__main__":
    main()
+10 −10
Original line number Diff line number Diff line
@@ -35,14 +35,10 @@ PYBIND11_MODULE(gkfs_python, m) {

    m.def("close", &gkfs::syscall::gkfs_close);

    m.def("lseek", &gkfs::syscall::gkfs_lseek, py::arg("fd"), py::arg("offset"),
          py::arg("whence"));

    m.def(
            "lseek",
            [](unsigned int fd, int64_t offset, unsigned int whence) {
                return gkfs::syscall::gkfs_lseek(fd, offset, whence);
            },
            py::arg("fd"), py::arg("offset"), py::arg("whence"));

    // TODO check behaviour
    m.def(
            "pwrite",
            [](int fd, py::bytes data, int64_t offset) {
@@ -65,6 +61,7 @@ PYBIND11_MODULE(gkfs_python, m) {
            },
            py::arg("fd"), py::arg("count"), py::arg("offset"));

    // TODO check behaviour and buffer strategy
    m.def(
            "readv",
            [](int fd, size_t iovcnt) {
@@ -86,6 +83,7 @@ PYBIND11_MODULE(gkfs_python, m) {
            },
            py::arg("fd"), py::arg("iovcnt"));

    // TODO check behaviour and buffer strategy
    m.def(
            "writev",
            [](int fd, const std::vector<py::bytes>& bufs) {
@@ -104,6 +102,7 @@ PYBIND11_MODULE(gkfs_python, m) {
            },
            py::arg("fd"), py::arg("buffers"));

    // TODO check behaviour and buffer strategy
    m.def(
            "preadv",
            [](int fd, size_t iovcnt, int64_t offset) {
@@ -124,6 +123,7 @@ PYBIND11_MODULE(gkfs_python, m) {
            },
            py::arg("fd"), py::arg("iovcnt"), py::arg("offset"));

    // TODO check behaviour
    m.def(
            "pwritev",
            [](int fd, const std::vector<py::bytes>& bufs, int64_t offset) {
@@ -242,8 +242,8 @@ PYBIND11_MODULE(gkfs_python, m) {

    m.def("fsync", &gkfs::syscall::gkfs_fsync);

    m.def("mmap", [](uintptr_t addr, size_t length, int prot, int flags,
                          int fd, off_t offset) {
    m.def("mmap", [](uintptr_t addr, size_t length, int prot, int flags, int fd,
                     off_t offset) {
        void* result = gkfs::syscall::gkfs_mmap(
                reinterpret_cast<void*>(addr), length, prot, flags, fd, offset);
        // if(result == MAP_FAILED) // TODO
+1 −0
Original line number Diff line number Diff line
@@ -753,6 +753,7 @@ class ShellClient:

        self._patched_env = {
            'LD_LIBRARY_PATH'      : libdirs,
            'PYTHONPATH'           : libdirs,
            'LD_PRELOAD'           : str(self._preload_library),
            'LIBGKFS_HOSTS_FILE'   : str(self.cwd / gkfs_hosts_file),
            'LIBGKFS_LOG'          : gkfs_client_log_level,
+52 −60
Original line number Diff line number Diff line
@@ -32,76 +32,68 @@ import errno
import stat
import os
import ctypes
import sh
import fnmatch
import sys
import pytest
import gkfs_python
from harness.logger import logger



nonexisting = "nonexisting"
gkfs_hosts_file = 'gkfs_hosts.txt'


def test_pybindings(gkfs_daemon, gkfs_client):

    file = gkfs_daemon.mountdir / "file"
    file2 = gkfs_daemon.mountdir / "file2"
expected_output = """Created file: /testfile2, fd=0
Deleted file: /testfile2, fd=0
Open file: /testfile, fd=46
['.', '..', 'testfile']
write success
lseek success
Read data: b'Test GekkoFS!'
pwrite success
Read data: b'HelloGekkoFS!'
Pread data: b'Gekko'
Readv data: b'HelloGekkoFS!'
Preadv data: b'HelloGekkoFS!'
Duplicated fds: 47, 48
Stat result: {'st_dev': 0, 'st_ino': 6604349686198632337, 'st_mode': 33188, 'st_nlink': 1, 'st_uid': 1000, 'st_gid': 1000, 'st_rdev': 0, 'st_size': 13, 'st_blksize': 524288, 'st_blocks': 0, 'st_atime': 0, 'st_mtime': 0, 'st_ctime': 0}
Statx result: {'size': 13, 'mode': 33188, 'uid': 1000, 'gid': 1000, 'mtime': 0, 'atime': 0, 'ctime': 0, 'ino': 6604349686198632337, 'nlink': 1, 'dev_major': 0, 'dev_minor': 0}
Access check (R_OK|W_OK): 0
File list: ['.', '..', 'testfile']
mmap/msync/munmap done
Symlink not supported or failed.
Renamed /testfile to /testfile_renamed
File list: ['.', '..', 'testfile_renamed']
Removed /testfile_renamed
File list: ['.', '..']
"""

    os.environ["GKFS_HOSTS_FILE"] = str(gkfs_daemon.cwd / gkfs_hosts_file)
def find_up_and_down(pattern, start_path=None):
    if start_path is None:
        start_path = os.getcwd()

    # create a file in gekkofs
    ret = gkfs_python.init()
    assert ret == 0
    ret = gkfs_python.get_file_list("/")
    assert ret == ['.', '..']
    # ret = gkfs_python.open(str(file),
    #                        os.O_CREAT | os.O_WRONLY,
    #                        stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
    #
    # assert ret != -1
    #
    # ret = gkfs_python.access(file, os.R_OK)
    # assert ret == 0
    #
    # # write a buffer we know
    # buf = b'42'
    # ret = gkfs_python.write(file, buf, len(buf))
    #
    # assert ret == len(buf) # Return the number of written bytes
    #
    # ret, st = gkfs_python.stat(file)
    # assert ret != 1
    #
    # ret, st = gkfs_python.stat(file2)
    # assert ret == -1
    #
    # ret = gkfs_python.rename(file, file2)
    # assert ret == 0
    #
    # ret = gkfs_python.access(file,  os.R_OK)
    # assert ret == -1
    #
    # ret = gkfs_python.access(file2, os.R_OK)
    # assert ret == 0
    #
    # ret, st = gkfs_python.stat(file)
    # assert ret == -1
    #
    # ret, st = gkfs_python.stat(file2)
    # assert ret != 1
    current_dir = os.path.abspath(start_path)

    # File is renamed, and innacesible
    while True:
        for root, dirs, files in os.walk(current_dir):
            for name in files:
                if fnmatch.fnmatch(name, pattern):
                    return os.path.join(root, name)

    # Read contents of file2
    # ret = gkfs_python.open(file2, os.O_RDONLY)
    # assert ret != -1
    #
    # ret = gkfs_python.read(file2, len(buf))
    # assert ret.retval == len(buf)
    # assert ret.buf == buf
        parent_dir = os.path.dirname(current_dir)
        if parent_dir == current_dir:
            # Reached filesystem root
            break
        current_dir = parent_dir

    ret = gkfs_python.end()
    assert ret == 0
    return None

def test_pybindings(gkfs_daemon, gkfs_shell):
    # Example usage:
    found_file = find_up_and_down("gkfs_python_lib_example.py")
    assert found_file != None
    print("Found:", found_file)
    cmd = gkfs_shell.python(found_file)
    print("stdout", cmd.stdout.decode())
    print("stderr", cmd.stderr.decode())
    assert cmd.exit_code == 0
    assert cmd.stdout.decode() == expected_output
    assert cmd.stderr.decode() == ''