diff --git a/scripts/collect-sysfs.sh b/scripts/collect-sysfs.sh new file mode 100755 index 00000000..b7ce0179 --- /dev/null +++ b/scripts/collect-sysfs.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later + +filename=nvme-sysfs-$(hostname)-$(uname -r).tar.xz + +declare -a dirs=( + "/sys/class/nvme" + "/sys/class/nvme-fabrics" + "/sys/class/nvme-generic" + "/sys/class/nvme-subsystem" + "/sys/bus/pci/slots" +) + +files="" +for d in "${dirs[@]}"; do + files+="${d} " + for l in "${d}"/*; do + files+="$(readlink -f $l) " + done +done + +tar -c -J -p -f "${filename}" ${files} 2> /dev/null diff --git a/test/meson.build b/test/meson.build index 2b4c6d80..93e69991 100644 --- a/test/meson.build +++ b/test/meson.build @@ -97,3 +97,7 @@ endif subdir('ioctl') subdir('nbft') + +if json_c_dep.found() + subdir('sysfs') +endif diff --git a/test/sysfs/data/nvme-sysfs-tw-carbon-6.8.0-rc1+.out b/test/sysfs/data/nvme-sysfs-tw-carbon-6.8.0-rc1+.out new file mode 100644 index 00000000..1cb6de4d --- /dev/null +++ b/test/sysfs/data/nvme-sysfs-tw-carbon-6.8.0-rc1+.out @@ -0,0 +1,32 @@ +{ + "hosts":[ + { + "hostnqn":"nqn.2014-08.org.nvmexpress:uuid:ce4fee3e-c02c-11ee-8442-830d068a36c6", + "hostid":"ce4fee3e-c02c-11ee-8442-830d068a36c6", + "subsystems":[ + { + "name":"nvme-subsys1", + "nqn":"nqn.2019-08.org.qemu:nvme-0", + "controllers":[ + { + "name":"nvme1", + "transport":"pcie", + "traddr":"0000:00:05.0" + } + ] + }, + { + "name":"nvme-subsys0", + "nqn":"nqn.2019-08.org.qemu:subsys1", + "controllers":[ + { + "name":"nvme0", + "transport":"pcie", + "traddr":"0000:0f:00.0" + } + ] + } + ] + } + ] +} diff --git a/test/sysfs/data/nvme-sysfs-tw-carbon-6.8.0-rc1+.tar.xz b/test/sysfs/data/nvme-sysfs-tw-carbon-6.8.0-rc1+.tar.xz new file mode 100644 index 00000000..ee11fdeb Binary files /dev/null and b/test/sysfs/data/nvme-sysfs-tw-carbon-6.8.0-rc1+.tar.xz differ diff --git a/test/sysfs/meson.build b/test/sysfs/meson.build new file mode 100644 index 00000000..c004fc05 --- /dev/null +++ b/test/sysfs/meson.build @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# This file is part of libnvme. +# Copyright (c) 2024 SUSE LLC. +# +# Authors: Daniel Wagner + + +sysfs = executable( + 'test-sysfs', + ['sysfs.c'], + dependencies: libnvme_dep, + include_directories: [incdir, internal_incdir] +) + +sysfs_files= [ + 'nvme-sysfs-tw-carbon-6.8.0-rc1+' +] + +setup = find_program('setup.sh') + +foreach t_file : sysfs_files + r = run_command(setup, files('data'/t_file + '.tar.xz'), meson.current_build_dir(), check: true) + i = r.stdout().strip() + e0 = 'LIBNVME_SYSFS_PATH=' + i + e1 = 'LIBNVME_HOSTNQN=nqn.2014-08.org.nvmexpress:uuid:ce4fee3e-c02c-11ee-8442-830d068a36c6' + e2 = 'LIBNVME_HOSTID=ce4fee3e-c02c-11ee-8442-830d068a36c6' + test('sysfs', sysfs, args : [ i, t_file + '.out', files('data'/t_file + '.out') ], env : [ e0, e1, e2 ]) +endforeach diff --git a/test/sysfs/setup.sh b/test/sysfs/setup.sh new file mode 100755 index 00000000..3437d4ee --- /dev/null +++ b/test/sysfs/setup.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later + +TARFILE=$1 +BASEDIR=$2 +TESTDIR="$BASEDIR/$(basename -s .tar.xz ${TARFILE})" + +mkdir -p "${TESTDIR}" +tar -x -f "${TARFILE}" -C "${TESTDIR}" || exit 1 + +echo "${TESTDIR}" diff --git a/test/sysfs/sysfs.c b/test/sysfs/sysfs.c new file mode 100644 index 00000000..c2df1789 --- /dev/null +++ b/test/sysfs/sysfs.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/** + * This file is part of libnvme. + * Copyright (c) 2024 Daniel Wagner, SUSE LLC + */ + +#include "nvme/tree.h" +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +static bool test_sysfs(const char *path, const char *filename) +{ + FILE *f; + nvme_root_t r; + int err; + + f = fopen(filename, "w"); + if (!f) + return false; + + r = nvme_create_root(f, LOG_ERR); + assert(r); + + err = nvme_scan_topology(r, NULL, NULL); + if (!err) + nvme_dump_tree(r); + fprintf(f, "\n"); + + nvme_free_tree(r); + fclose(f); + + return err == 0; +} + +static bool compare_content(const char *filename1, const char *filename2) +{ + FILE *f1, *f2; + char c1, c2; + bool pass = false; + + f1 = fopen(filename1, "r"); + if (!f1) + return false; + + f2 = fopen(filename2, "r"); + if (!f2) { + fclose(f1); + return false; + } + + do { + c1 = getc(f1); + c2 = getc(f2); + if (c1 != c2) + goto out; + } while (c1 != EOF || c2 != EOF); + + if (c1 == c2) + pass = true; +out: + fclose(f1); + fclose(f2); + + return pass; +} + +int main(int argc, char *argv[]) +{ + bool pass = true; + + if (argc < 4) { + fprintf(stderr, "usage: test-sysfs SYSFS_DIR OUTPUT_FILE COMPARE_FILE\n"); + return EXIT_FAILURE; + } + + pass &= test_sysfs(argv[1], argv[2]); + pass &= compare_content(argv[2], argv[3]); + + exit(pass ? EXIT_SUCCESS : EXIT_FAILURE); +}