From ed52be4cdee20729337e86c1021f5ee69f61eedc Mon Sep 17 00:00:00 2001 From: Broc Going Date: Thu, 2 Jul 2026 12:08:17 -0700 Subject: [PATCH 1/5] tests: Add is_windows check and skip unsupported tests on Windows Adds an is_windows check to nvme tests, and skips tests on Windows for commands that aren't supported by the Windows driver. Signed-off-by: Broc Going --- tests/nvme_compare_test.py | 2 ++ tests/nvme_dsm_test.py | 2 ++ tests/nvme_test.py | 19 ++++++++++++++++--- tests/nvme_verify_test.py | 2 ++ tests/nvme_writeuncor_test.py | 2 ++ tests/nvme_writezeros_test.py | 2 ++ 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/tests/nvme_compare_test.py b/tests/nvme_compare_test.py index 4c323e4a96..83d03ad442 100644 --- a/tests/nvme_compare_test.py +++ b/tests/nvme_compare_test.py @@ -58,6 +58,8 @@ def compare_cmd_supported(self): def setUp(self): """ Pre Section for TestNVMeCompareCmd """ super().setUp() + if self.is_windows(): + self.skipTest("Compare command not supported by Windows") if not self.compare_cmd_supported(): self.skipTest("because: Optional NVM Command 'Compare' (NVMCMPS) not supported") self.start_block = 1023 diff --git a/tests/nvme_dsm_test.py b/tests/nvme_dsm_test.py index 4ad3e05ed5..bbc3642441 100644 --- a/tests/nvme_dsm_test.py +++ b/tests/nvme_dsm_test.py @@ -29,6 +29,8 @@ class TestNVMeDsm(TestNVMe): def setUp(self): """ Pre Section for TestNVMeDsm """ super().setUp() + if self.is_windows(): + self.skipTest("Dataset Management command not supported by Windows") self.start_block = 0 self.range = 0 self.namespace = 1 diff --git a/tests/nvme_test.py b/tests/nvme_test.py index f48493943b..623c6bf355 100644 --- a/tests/nvme_test.py +++ b/tests/nvme_test.py @@ -26,6 +26,7 @@ import logging import mmap import os +import platform import re import shutil import stat @@ -70,6 +71,9 @@ class or appropriate subclass which is a child of this class. - clear_log_dir : default log directory. """ + def is_windows(self): + return platform.system() == 'Windows' + def setUp(self): """ Pre Section for TestNVMe. """ # common code used in various testcases. @@ -119,6 +123,7 @@ def create_and_attach_default_ns(self): """ self.dps = 0 self.flbas = 0 + (ds, ms) = self.get_lba_format_size() ncap = int(self.get_ncap() / (ds+ms)) self.nsze = ncap @@ -140,6 +145,9 @@ def validate_pci_device(self): - Returns: - None """ + if self.is_windows(): + return + x1, x2, dev = self.ctrl.split('/') cmd = "find /sys/devices -name \\*" + dev + " | grep -i pci" err = self.run_cmd(cmd).returncode @@ -250,9 +258,11 @@ def nvme_reset_ctrl(self): nvme_reset_cmd = f"{self.nvme_bin} reset {self.ctrl}" err = self.run_cmd(nvme_reset_cmd).returncode self.assertEqual(err, 0, "ERROR : nvme reset failed") - rescan_cmd = "echo 1 > /sys/bus/pci/rescan" - result = self.run_cmd(rescan_cmd) - self.assertEqual(result.returncode, 0, "ERROR : pci rescan failed") + + if not self.is_windows(): # Rescan occurs during reset on Windows + rescan_cmd = "echo 1 > /sys/bus/pci/rescan" + result = self.run_cmd(rescan_cmd) + self.assertEqual(result.returncode, 0, "ERROR : pci rescan failed") def get_ctrl_id(self): """ Wrapper for extracting the first controller id. @@ -295,6 +305,9 @@ def get_ns_mgmt_support(self): bool: True if both Namespace Management and Namespace Attachment are supported, False otherwise. """ + if self.is_windows(): + return False # Namespace management not supported on Windows + oacs = to_decimal(self.get_id_ctrl_field_value("oacs")) ns_mgmt_supported = bool(oacs & (1 << 3)) diff --git a/tests/nvme_verify_test.py b/tests/nvme_verify_test.py index 90e149dc78..0cdbb5de26 100644 --- a/tests/nvme_verify_test.py +++ b/tests/nvme_verify_test.py @@ -37,6 +37,8 @@ def verify_cmd_supported(self): def setUp(self): """ Pre Section for TestNVMeVerify """ super().setUp() + if self.is_windows(): + self.skipTest("Verify command not supported by Windows") if not self.verify_cmd_supported(): self.skipTest( "because: Optional NVM Command 'Verify' (NVMVFYS) not supported") diff --git a/tests/nvme_writeuncor_test.py b/tests/nvme_writeuncor_test.py index 0fbeaec14f..f8a2cd211b 100644 --- a/tests/nvme_writeuncor_test.py +++ b/tests/nvme_writeuncor_test.py @@ -46,6 +46,8 @@ class TestNVMeUncor(TestNVMeIO): def setUp(self): """ Constructor TestNVMeUncor """ super().setUp() + if self.is_windows(): + self.skipTest("Write Uncorrectable command not supported by Windows") self.start_block = 1023 self.setup_log_dir(self.__class__.__name__) self.write_file = self.test_log_dir + "/" + self.write_file diff --git a/tests/nvme_writezeros_test.py b/tests/nvme_writezeros_test.py index 381672034a..1c3ebe5eb9 100644 --- a/tests/nvme_writezeros_test.py +++ b/tests/nvme_writezeros_test.py @@ -50,6 +50,8 @@ class TestNVMeWriteZeros(TestNVMeIO): def setUp(self): """ Pre Section for TestNVMeWriteZeros """ super().setUp() + if self.is_windows(): + self.skipTest("Write Zeroes command not supported by Windows") self.start_block = 1023 self.block_count = 0 self.setup_log_dir(self.__class__.__name__) From 6d4dd8b3229d1779a9d49b1731799248d9b5ad56 Mon Sep 17 00:00:00 2001 From: Broc Going Date: Thu, 2 Jul 2026 12:13:42 -0700 Subject: [PATCH 2/5] tests: Configure PATH for tests in a platform-agnostic way. Updates the meson configuration for tests to add the project build root and other required directories to the path in a project-agnostic way. Also ensures that the environment variable needed for running tests within the Windows msys2 environment get copied into the test environment. Signed-off-by: Broc Going --- tests/meson.build | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/meson.build b/tests/meson.build index 900a5d54b8..e27064602a 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -42,6 +42,9 @@ python_module = import('python') python = python_module.find_installation('python3') +test_env = environment() +test_env.prepend('PATH', meson.project_build_root()) + foreach t : tests t_name = t.split('.')[0] test( @@ -52,7 +55,7 @@ foreach t : tests '--start-dir', meson.current_source_dir(), t_name, ], - env: ['PATH=' + meson.project_build_root() + ':/usr/bin:/usr/sbin'], + env: test_env, timeout: 500, protocol: 'tap', is_parallel: false, From 5c4c616e6a42497e3e8403acdc20fee20c06a9a0 Mon Sep 17 00:00:00 2001 From: Broc Going Date: Thu, 2 Jul 2026 12:17:57 -0700 Subject: [PATCH 3/5] tests: Update get features test base on Windows capabilities On Windows, reading some of the features used in the get features test is not supported. Updates the get features test to work on Windows. Signed-off-by: Broc Going --- tests/nvme_get_features_test.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/nvme_get_features_test.py b/tests/nvme_get_features_test.py index 898e100dde..52dbca5548 100644 --- a/tests/nvme_get_features_test.py +++ b/tests/nvme_get_features_test.py @@ -52,13 +52,21 @@ def setUp(self): """ Pre Section for TestNVMeGetMandatoryFeatures """ super().setUp() self.setup_log_dir(self.__class__.__name__) - self.feature_id_list = ["0x01", "0x02", "0x04", "0x05", "0x07", - "0x08", "0x09", "0x0A", "0x0B"] - device = self.ctrl.split('/')[-1] - get_vector_list_cmd = "grep " + device + "q /proc/interrupts |" \ - " cut -d : -f 1 | tr -d ' ' | tr '\n' ' '" - result = self.run_cmd(get_vector_list_cmd) - self.vector_list_len = len(result.stdout.strip().split(" ")) + + if self.is_windows(): + # FIDs 5 and 7 are not supported by Windows. + self.feature_id_list = ["0x01", "0x02", "0x04", + "0x08", "0x09", "0x0A", "0x0B"] + # Interrupt vector discovery not available on Windows. + self.vector_list_len = 1 + else: + self.feature_id_list = ["0x01", "0x02", "0x04", "0x05", "0x07", + "0x08", "0x09", "0x0A", "0x0B"] + device = self.ctrl.split('/')[-1] + get_vector_list_cmd = "grep " + device + "q /proc/interrupts |" \ + " cut -d : -f 1 | tr -d ' ' | tr '\n' ' '" + result = self.run_cmd(get_vector_list_cmd) + self.vector_list_len = len(result.stdout.strip().split(" ")) def tearDown(self): """ Post Section for TestNVMeGetMandatoryFeatures From c31a9fbf4f971ab60e444351e3ee798817577743 Mon Sep 17 00:00:00 2001 From: Broc Going Date: Thu, 2 Jul 2026 12:24:11 -0700 Subject: [PATCH 4/5] test-uint128: Update tostr_test locale handling to be Windows compatible The \u202f code does not work for matching the separator used on Windows. Previously the test was ignoring the actual thousands_sep value for the locale and assuming it would match \u202f. Update the test to use the thousands_sep value from the locale to build the comparison string. Signed-off-by: Broc Going --- unit/test-uint128.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/unit/test-uint128.c b/unit/test-uint128.c index 0a1f7d3259..9186c6215d 100644 --- a/unit/test-uint128.c +++ b/unit/test-uint128.c @@ -43,13 +43,14 @@ static struct tostr_test tostr_tests[] = { U128(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), "340282366920938463463374607431768211455" }, - { "fr_FR.utf-8", U128(0, 0, 0, 1000), "1\u202f000" }, + { "fr_FR.utf-8", U128(0, 0, 0, 1000), "1%s000" }, }; void tostr_test(struct tostr_test *test) { char *str; const char *exp = test->exp; + char exp_buf[64]; if (!setlocale(LC_NUMERIC, test->locale)) return; @@ -67,6 +68,11 @@ void tostr_test(struct tostr_test *test) test->locale); return; } + + if (strstr(test->exp, "%s")) { + snprintf(exp_buf, sizeof(exp_buf), test->exp, sep); + exp = exp_buf; + } str = uint128_t_to_l10n_string(test->val); } else { str = uint128_t_to_string(test->val); From 7bdc01bb17df187e32496aae3eb66bb38f11360a Mon Sep 17 00:00:00 2001 From: Broc Going Date: Thu, 2 Jul 2026 12:32:52 -0700 Subject: [PATCH 5/5] test: Update build configuration to support testing on Windows Updates build configuration to allow testing to be enabled on Windows and to exclude Linux-specific test on Windows. Signed-off-by: Broc Going --- libnvme/test/meson.build | 68 +++++++++++++++++++++------------------- meson.build | 2 +- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/libnvme/test/meson.build b/libnvme/test/meson.build index 844eaaad6a..34e1ad1a7e 100644 --- a/libnvme/test/meson.build +++ b/libnvme/test/meson.build @@ -70,25 +70,27 @@ if cxx_available endif -register = executable( - 'test-register', - ['register.c'], - dependencies: [ - config_dep, - ccan_dep, - libnvme_dep, - ], -) +if host_system != 'windows' + register = executable( + 'test-register', + ['register.c'], + dependencies: [ + config_dep, + ccan_dep, + libnvme_dep, + ], + ) -zns = executable( - 'test-zns', - ['zns.c'], - dependencies: [ - config_dep, - ccan_dep, - libnvme_test_dep, - ], -) + zns = executable( + 'test-zns', + ['zns.c'], + dependencies: [ + config_dep, + ccan_dep, + libnvme_test_dep, + ], + ) +endif # host_system != 'windows' if want_mi mi = executable( @@ -259,22 +261,24 @@ if conf.get('NVME_HAVE_NETDB') test('libnvme - util', test_util) endif -subdir('ioctl') -if want_fabrics - subdir('nbft') -endif +if host_system != 'windows' + subdir('ioctl') + if want_fabrics + subdir('nbft') + endif -if json_c_dep.found() - subdir('sysfs') - subdir('config') -endif + if json_c_dep.found() + subdir('sysfs') + subdir('config') + endif -if openssl_dep.found() - hkdf_add1 = executable( - 'hkdf_add1', - ['hkdf_add1.c'], - dependencies: openssl_dep, - ) + if openssl_dep.found() + hkdf_add1 = executable( + 'hkdf_add1', + ['hkdf_add1.c'], + dependencies: openssl_dep, + ) + endif endif foreach hdr : [ diff --git a/meson.build b/meson.build index e03c7c91b8..7defce0c97 100644 --- a/meson.build +++ b/meson.build @@ -56,7 +56,7 @@ want_mi = get_option('mi').disabled() == false and host_system != 'windows' want_top = get_option('top').disabled() == false and host_system != 'windows' want_json_c = get_option('json-c').disabled() == false want_libkmod = get_option('libkmod').disabled() == false and host_system != 'windows' -want_tests = get_option('tests') and host_system != 'windows' +want_tests = get_option('tests') want_examples = get_option('examples') and host_system != 'windows' want_docs = get_option('docs') want_docs_build = get_option('docs-build')