diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfc0a93b..4d3c8973 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,8 +30,14 @@ jobs: - os: macos-latest config: '--enable-wolfclu' sanitize: '' + # Keeps the no-filesystem build (and the tests that skip on it) + # from rotting; cheap enough to run without ASAN. + - os: ubuntu-latest + config: '--enable-wolfclu' + sanitize: '' + clu_config: '--disable-filesystem' - name: ${{ matrix.os }} ${{ matrix.sanitize && 'ASAN' || '' }} (${{ matrix.config }}) + name: ${{ matrix.os }} ${{ matrix.sanitize && 'ASAN' || '' }} (${{ matrix.config }}${{ matrix.clu_config && format(' / wolfclu {0}', matrix.clu_config) || '' }}) runs-on: ${{ matrix.os }} timeout-minutes: 10 @@ -73,7 +79,8 @@ jobs: working-directory: ./wolfclu run: | ./autogen.sh - ./configure ${{ matrix.sanitize }} --with-wolfssl=$GITHUB_WORKSPACE/build-dir + ./configure ${{ matrix.sanitize }} ${{ matrix.clu_config }} \ + --with-wolfssl=$GITHUB_WORKSPACE/build-dir make -j - name: Run tests diff --git a/src/server/clu_server_setup.c b/src/server/clu_server_setup.c index 467ceb23..d387e60e 100644 --- a/src/server/clu_server_setup.c +++ b/src/server/clu_server_setup.c @@ -23,9 +23,9 @@ #include #include #include -#include #ifndef WOLFCLU_NO_FILESYSTEM +#include static const struct option server_options[] = { {"-port", required_argument, 0, WOLFCLU_PORT }, @@ -98,6 +98,7 @@ static int _addServerArg(const char** args, const char* in, int* idx) int wolfCLU_Server(int argc, char** argv) { +#ifndef WOLFCLU_NO_FILESYSTEM func_args args; int ret = WOLFCLU_SUCCESS; int longIndex = 1; @@ -206,4 +207,10 @@ int wolfCLU_Server(int argc, char** argv) FreeTcpReady(&ready); return ret; +#else + (void)argc; + (void)argv; + WOLFCLU_LOG(WOLFCLU_E0, "No filesystem support"); + return WOLFCLU_FATAL_ERROR; +#endif } diff --git a/src/server/server.c b/src/server/server.c index 5b9c70dd..2cba8ba8 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -23,6 +23,9 @@ * https://github.com/wolfSSL/wolfssl-examples/tree/master/tls */ +/* Only compile when filesystem is enabled, like src/client/client.c. */ +#ifndef WOLFCLU_NO_FILESYSTEM + #ifdef HAVE_CONFIG_H #include #endif @@ -3927,3 +3930,5 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) char* myoptarg = NULL; #endif /* NO_MAIN_DRIVER */ + +#endif /* !WOLFCLU_NO_FILESYSTEM */ diff --git a/src/sign-verify/clu_x509_verify.c b/src/sign-verify/clu_x509_verify.c index 98367096..81c1f8b1 100644 --- a/src/sign-verify/clu_x509_verify.c +++ b/src/sign-verify/clu_x509_verify.c @@ -51,7 +51,6 @@ static void wolfCLU_x509VerifyHelp(void) "1 cert as -untrusted"); } -#endif static X509* load_cert_from_file(const char* filename) { WOLFSSL_BIO* bio = NULL; @@ -75,6 +74,7 @@ static X509* load_cert_from_file(const char* filename) { return cert; } +#endif /* !WOLFCLU_NO_FILESYSTEM */ int wolfCLU_x509Verify(int argc, char** argv) { diff --git a/src/tools/clu_base64.c b/src/tools/clu_base64.c index 20a9d8b3..e5eda590 100644 --- a/src/tools/clu_base64.c +++ b/src/tools/clu_base64.c @@ -24,6 +24,11 @@ #include #include +#if !defined(WOLFCLU_NO_FILESYSTEM) && !defined(NO_CODING) + #define WOLFCLU_BASE64_ENABLED +#endif + +#ifdef WOLFCLU_BASE64_ENABLED static const struct option base64_options[] = { {"-in", required_argument, 0, WOLFCLU_INFILE }, {"-out", required_argument, 0, WOLFCLU_OUTFILE }, @@ -44,11 +49,12 @@ static void wolfCLU_Base64Help(void) WOLFCLU_LOG(WOLFCLU_L0, "\t-d Decode data"); WOLFCLU_LOG(WOLFCLU_L0, "\t-help Display this message"); } +#endif /* WOLFCLU_BASE64_ENABLED */ /* base64 setup function */ int wolfCLU_Base64Setup(int argc, char** argv) { -#if !defined(WOLFCLU_NO_FILESYSTEM) && !defined(NO_CODING) +#ifdef WOLFCLU_BASE64_ENABLED WOLFSSL_BIO *bioIn = NULL; WOLFSSL_BIO *bioOut = NULL; byte* input = NULL; @@ -330,5 +336,5 @@ int wolfCLU_Base64Setup(int argc, char** argv) wolfCLU_LogError("No filesystem support"); #endif return WOLFCLU_FATAL_ERROR; -#endif /* !WOLFCLU_NO_FILESYSTEM */ +#endif /* WOLFCLU_BASE64_ENABLED */ } diff --git a/tests/base64/base64-test.py b/tests/base64/base64-test.py index c955ac71..2baed320 100644 --- a/tests/base64/base64-test.py +++ b/tests/base64/base64-test.py @@ -9,9 +9,11 @@ # Allow importing the shared helper when run standalone or via the test runner sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, no_filesystem, run_wolfssl, + test_main) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class Base64Test(unittest.TestCase): @classmethod @@ -19,13 +21,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - # Skip if filesystem support is disabled (Linux autotools build) - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - # Skip if base64 coding support is not compiled in result = run_wolfssl("base64", "-in", os.path.join(CERTS_DIR, "server-key.der")) diff --git a/tests/client/client-test.py b/tests/client/client-test.py index 4fbca71d..3479bba7 100644 --- a/tests/client/client-test.py +++ b/tests/client/client-test.py @@ -7,9 +7,11 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, no_filesystem, run_wolfssl, + test_main) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class ClientTest(unittest.TestCase): @classmethod @@ -17,12 +19,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def test_s_client_x509(self): """Connect to a TLS server, extract cert, and verify PEM output.""" tmp_crt = "tmp.crt" diff --git a/tests/dgst/dgst-test.py b/tests/dgst/dgst-test.py index b412c6fb..4c91b08c 100644 --- a/tests/dgst/dgst-test.py +++ b/tests/dgst/dgst-test.py @@ -9,12 +9,13 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import (CERTS_DIR, is_fips, not_compiled_in, run_wolfssl, - test_main, truncate_sparse) +from wolfclu_test import (CERTS_DIR, is_fips, no_filesystem, not_compiled_in, + run_wolfssl, test_main, truncate_sparse) DGST_DIR = os.path.dirname(os.path.abspath(__file__)) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class DgstVerifyTest(unittest.TestCase): @classmethod @@ -22,12 +23,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def test_verify_sha256_rsa(self): r = run_wolfssl("dgst", "-sha256", "-verify", os.path.join(CERTS_DIR, "server-keyPub.pem"), @@ -162,6 +157,7 @@ def test_complete_args_not_misflagged(self): self.assertEqual(r.returncode, 0, r.stderr) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class DgstLargeFileTest(unittest.TestCase): LARGE_FILE = "large-test.txt" @@ -171,12 +167,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - # Create large file: 5000 copies of server-key.der der_path = os.path.join(CERTS_DIR, "server-key.der") with open(der_path, "rb") as src: @@ -354,6 +344,7 @@ def test_tampered_last_byte_fails_verify(self): self.assertNotEqual(r.returncode, 0) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class DgstSignVerifyRoundtripTest(unittest.TestCase): @classmethod @@ -397,6 +388,7 @@ def test_ecc_sign_verify_roundtrip(self): self.assertEqual(r.returncode, 0, r.stderr) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class DgstHmacTest(unittest.TestCase): """HMAC test vectors for `dgst -mac HMAC`. @@ -445,12 +437,6 @@ class DgstHmacTest(unittest.TestCase): @classmethod def setUpClass(cls): - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - cls._tmpdir = tempfile.mkdtemp(prefix="wolfclu-hmac-") cls.data_file = os.path.join(cls._tmpdir, "data.bin") with open(cls.data_file, "wb") as f: diff --git a/tests/dh/dh-test.py b/tests/dh/dh-test.py index 71cb6575..0e52c804 100644 --- a/tests/dh/dh-test.py +++ b/tests/dh/dh-test.py @@ -6,9 +6,10 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import CERTS_DIR, no_filesystem, run_wolfssl, test_main +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class DhParamTest(unittest.TestCase): @classmethod @@ -16,12 +17,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - # Skip if DH not compiled in r = run_wolfssl("dhparam", "1024") combined = r.stdout + r.stderr diff --git a/tests/dsa/dsa-test.py b/tests/dsa/dsa-test.py index 2f4b9c8d..4ad4e8ae 100644 --- a/tests/dsa/dsa-test.py +++ b/tests/dsa/dsa-test.py @@ -6,7 +6,13 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import CERTS_DIR, no_filesystem, run_wolfssl, test_main + + +# `dsaparam` generates to stdout without a filesystem, so only the tests that +# pass a file path are skipped on a --disable-filesystem build. +needs_filesystem = unittest.skipIf(no_filesystem(), + "filesystem support disabled") class DsaParamTest(unittest.TestCase): @@ -16,12 +22,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - # Skip if DSA not compiled in r = run_wolfssl("dsaparam", "1024") combined = r.stdout + r.stderr @@ -37,6 +37,7 @@ def test_dsaparam_zero_fails(self): r = run_wolfssl("dsaparam", "0") self.assertNotEqual(r.returncode, 0) + @needs_filesystem def test_dsaparam_out_and_in(self): params_file = "dsa.params" self.addCleanup(lambda: os.remove(params_file) @@ -49,6 +50,7 @@ def test_dsaparam_out_and_in(self): self.assertEqual(r.returncode, 0, r.stderr) self.assertIn("-----BEGIN DSA PARAMETERS-----", r.stdout) + @needs_filesystem def test_dsaparam_noout(self): params_file = "dsa.params" self.addCleanup(lambda: os.remove(params_file) @@ -61,6 +63,7 @@ def test_dsaparam_noout(self): self.assertEqual(r.returncode, 0, r.stderr) self.assertNotIn("-----BEGIN DSA PARAMETERS-----", r.stdout) + @needs_filesystem def test_dsaparam_genkey(self): params_file = "dsa.params" self.addCleanup(lambda: os.remove(params_file) @@ -74,6 +77,7 @@ def test_dsaparam_genkey(self): self.assertIn("-----BEGIN DSA PARAMETERS-----", r.stdout) self.assertIn("-----BEGIN DSA PRIVATE KEY-----", r.stdout) + @needs_filesystem def test_dsaparam_genkey_noout(self): params_file = "dsa.params" self.addCleanup(lambda: os.remove(params_file) @@ -87,6 +91,7 @@ def test_dsaparam_genkey_noout(self): self.assertNotIn("-----BEGIN DSA PARAMETERS-----", r.stdout) self.assertIn("-----BEGIN DSA PRIVATE KEY-----", r.stdout) + @needs_filesystem def test_bad_input_fails(self): r = run_wolfssl("dsaparam", "-in", os.path.join(CERTS_DIR, "server-cert.pem"), diff --git a/tests/encrypt/enc-test.py b/tests/encrypt/enc-test.py index 5fa48c7f..c68bf251 100644 --- a/tests/encrypt/enc-test.py +++ b/tests/encrypt/enc-test.py @@ -11,7 +11,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, WOLFSSL_BIN, run_wolfssl, test_main +from wolfclu_test import (CERTS_DIR, WOLFSSL_BIN, no_filesystem, run_wolfssl, + test_main) # The interactive password prompt only reads from stdin when stdin is a real # terminal (wolfCLU_GetStdinPassword -> tcgetattr fails on a pipe), so driving @@ -30,6 +31,7 @@ def run_enc(*args, password=""): stdin=subprocess.DEVNULL, timeout=60) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EncDecryptTest(unittest.TestCase): @classmethod @@ -37,12 +39,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def _cleanup(self, *files): for f in files: self.addCleanup(lambda p=f: os.remove(p) @@ -180,6 +176,7 @@ def test_explicit_hex_key_iv(self): "{}".format(r.stderr)) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EncInteropTest(unittest.TestCase): """Test interoperability with OpenSSL (skipped if openssl not available).""" @@ -336,6 +333,7 @@ def test_pbkdf2_wolfssl_pass_flag(self): self.assertTrue(filecmp.cmp(orig, dec, shallow=False)) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EncPassSourceTest(unittest.TestCase): """Regression tests for issue 6133. @@ -351,12 +349,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def _cleanup(self, *files): for f in files: self.addCleanup(lambda p=f: os.remove(p) @@ -420,6 +412,7 @@ def test_supported_pass_source_still_works(self): self.assertTrue(filecmp.cmp(orig, dec, shallow=False)) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EncLegacyNamesTest(unittest.TestCase): @classmethod @@ -479,6 +472,7 @@ def _camellia_available(): os.remove(probe) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EncStdinInputTest(unittest.TestCase): """Regression tests for stack buffer overflow fix (scanf -> fgets). @@ -492,12 +486,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - cls.has_camellia = _camellia_available() def _cleanup(self, *files): @@ -640,6 +628,7 @@ def test_camellia_outname_too_long_reprompt(self): "Camellia roundtrip mismatch after too-long reprompt") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EncKeyInputTest(unittest.TestCase): """Tests for the -key (hex on CLI) and -inkey (key from file) flags.""" @@ -653,12 +642,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def _cleanup(self, *files): for f in files: self.addCleanup(lambda p=f: os.remove(p) @@ -914,6 +897,7 @@ def test_rand_hex_to_inkey_workflow(self): @unittest.skipUnless(HAVE_PTY, "pty not available (non-POSIX)") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EncStdinPasswordTest(unittest.TestCase): """Interactive stdin-password path of `encrypt` (F-5970). @@ -933,14 +917,6 @@ class EncStdinPasswordTest(unittest.TestCase): # AES-256 key length in bytes. FULL_KEY_BYTES = 32 - @classmethod - def setUpClass(cls): - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log) as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def _cleanup(self, *files): for f in files: self.addCleanup(lambda p=f: os.remove(p) diff --git a/tests/genkey_sign_ver/genkey-sign-ver-test.py b/tests/genkey_sign_ver/genkey-sign-ver-test.py index 14a777df..61540e59 100644 --- a/tests/genkey_sign_ver/genkey-sign-ver-test.py +++ b/tests/genkey_sign_ver/genkey-sign-ver-test.py @@ -6,8 +6,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, not_compiled_in, - run_wolfssl, test_main) +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, no_filesystem, + not_compiled_in, run_wolfssl, test_main) # Files that tests may create; cleaned up by tearDownClass _TEMP_FILES = [] @@ -27,6 +27,7 @@ def _has_algorithm(algo): return algo in combined +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class _GenkeySignVerifyBase(unittest.TestCase): """Base class with the gen-key / sign / verify workflow.""" @@ -34,12 +35,6 @@ class _GenkeySignVerifyBase(unittest.TestCase): @classmethod def setUpClass(cls): - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - with open(cls.SIGN_FILE, "w") as f: f.write("Sign this test data\n") @@ -532,6 +527,7 @@ def test_xmssmt_missing_height_arg(self): "crash)") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class SignVerifySetupArgsTest(unittest.TestCase): """Argument-parsing branches in clu_sign_verify_setup.c. @@ -546,11 +542,6 @@ class SignVerifySetupArgsTest(unittest.TestCase): @classmethod def setUpClass(cls): - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") with open(cls.SIGN_FILE, "w") as f: f.write("Sign this test data\n") diff --git a/tests/hash/hash-test.py b/tests/hash/hash-test.py index a51d6286..241719c6 100644 --- a/tests/hash/hash-test.py +++ b/tests/hash/hash-test.py @@ -8,8 +8,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import (CERTS_DIR, not_compiled_in, run_wolfssl, test_main, - truncate_sparse) +from wolfclu_test import (CERTS_DIR, no_filesystem, not_compiled_in, + run_wolfssl, test_main, truncate_sparse) HASH_DIR = os.path.dirname(os.path.abspath(__file__)) CERT_FILE = os.path.join(CERTS_DIR, "ca-cert.pem") @@ -21,6 +21,7 @@ def _read_expected(name): return f.read().strip() +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class HashCommandTest(unittest.TestCase): """Tests using the -hash subcommand.""" @@ -29,12 +30,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def test_md5(self): r = run_wolfssl("-hash", "-md5", "-in", CERT_FILE) if not_compiled_in(r): @@ -82,6 +77,7 @@ def test_blake2b(self): self.assertEqual(r.stdout.strip(), _read_expected("blake2b-expect.hex")) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class HashShortcutTest(unittest.TestCase): """Tests using the shortcut subcommands (md5, sha256, etc.).""" @@ -90,12 +86,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def test_md5(self): r = run_wolfssl("md5", CERT_FILE) if not_compiled_in(r): diff --git a/tests/ocsp/ocsp-test.py b/tests/ocsp/ocsp-test.py index 077be417..2c78c800 100644 --- a/tests/ocsp/ocsp-test.py +++ b/tests/ocsp/ocsp-test.py @@ -15,7 +15,9 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, test_main, find_free_port +from wolfclu_test import ( + WOLFSSL_BIN, CERTS_DIR, find_free_port, test_main +) HAS_OPENSSL = shutil.which("openssl") is not None @@ -107,6 +109,9 @@ def _run_client(binary, port, extra_args=None): return r.returncode, r.stdout + r.stderr +# No no_filesystem() skip: wolfCLU_OcspSetup, client and responder paths +# alike, is gated only on HAVE_OCSP / HAVE_OCSP_RESPONDER, already covered by +# the _ocsp_supported() check in setUpClass. class _OCSPInteropBase(unittest.TestCase): """Base class for a single client/responder combination. @@ -368,6 +373,11 @@ def test_01_client_start_up(self): self.assertEqual(rc, 0, out) self.assertIn("good", out.lower(), out) + +# The -port/-nrequest range checks below live in wolfCLU_OcspSetup's argument +# parser, which is not gated on WOLFCLU_NO_FILESYSTEM -- only on HAVE_OCSP / +# HAVE_OCSP_RESPONDER, already covered by the _ocsp_supported() check in each +# setUpClass. So these classes need no no_filesystem() skip. class TestPortValidation(unittest.TestCase): """Boundary tests for the -port range check in wolfCLU_OcspSetup. diff --git a/tests/pkcs/pkcs12-test.py b/tests/pkcs/pkcs12-test.py index 7d067f1c..f57a9b9a 100644 --- a/tests/pkcs/pkcs12-test.py +++ b/tests/pkcs/pkcs12-test.py @@ -7,11 +7,13 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, is_fips, run_wolfssl, test_main +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, is_fips, no_filesystem, + run_wolfssl, test_main) P12_FILE = os.path.join(CERTS_DIR, "test-servercert.p12") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class Pkcs12Test(unittest.TestCase): @classmethod @@ -19,12 +21,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - if is_fips(): raise unittest.SkipTest("FIPS build") diff --git a/tests/pkcs/pkcs7-test.py b/tests/pkcs/pkcs7-test.py index b6baa472..c4609574 100644 --- a/tests/pkcs/pkcs7-test.py +++ b/tests/pkcs/pkcs7-test.py @@ -7,9 +7,11 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, no_filesystem, run_wolfssl, + test_main) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class Pkcs7Test(unittest.TestCase): @classmethod @@ -17,12 +19,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - r = run_wolfssl("pkcs7", "-inform", "DER", "-in", os.path.join(CERTS_DIR, "signed.p7b")) combined = r.stdout + r.stderr diff --git a/tests/pkcs/pkcs8-test.py b/tests/pkcs/pkcs8-test.py index 2a23aa3d..90497f7f 100644 --- a/tests/pkcs/pkcs8-test.py +++ b/tests/pkcs/pkcs8-test.py @@ -8,9 +8,11 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, is_fips, run_wolfssl, test_main +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, is_fips, no_filesystem, + run_wolfssl, test_main) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class Pkcs8Test(unittest.TestCase): @classmethod @@ -18,12 +20,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - r = run_wolfssl("pkcs8", "-in", os.path.join(CERTS_DIR, "server-keyEnc.pem"), "-passin", "pass:yassl123") diff --git a/tests/pkey/ecparam-test.py b/tests/pkey/ecparam-test.py index 0579df35..377c78b2 100644 --- a/tests/pkey/ecparam-test.py +++ b/tests/pkey/ecparam-test.py @@ -6,7 +6,7 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import CERTS_DIR, no_filesystem, run_wolfssl, test_main def _get_curve_names(): @@ -26,6 +26,7 @@ def _get_curve_names(): return names +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class EcparamTest(unittest.TestCase): @classmethod @@ -33,12 +34,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def _cleanup(self, *files): for f in files: self.addCleanup(lambda p=f: os.remove(p) diff --git a/tests/pkey/pkey-test.py b/tests/pkey/pkey-test.py index 91b528d1..bbdc2f7f 100644 --- a/tests/pkey/pkey-test.py +++ b/tests/pkey/pkey-test.py @@ -6,7 +6,7 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import CERTS_DIR, no_filesystem, run_wolfssl, test_main ECC_PUBKEY_PEM = """\ -----BEGIN PUBLIC KEY----- @@ -22,6 +22,7 @@ -----END EC PRIVATE KEY-----""" +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class PkeyTest(unittest.TestCase): @classmethod @@ -29,12 +30,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def _cleanup(self, *files): for f in files: self.addCleanup(lambda p=f: os.remove(p) diff --git a/tests/pkey/rsa-test.py b/tests/pkey/rsa-test.py index 3e58b275..de1c76ea 100644 --- a/tests/pkey/rsa-test.py +++ b/tests/pkey/rsa-test.py @@ -8,7 +8,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, WOLFSSL_BIN, is_fips, run_wolfssl, test_main +from wolfclu_test import (CERTS_DIR, WOLFSSL_BIN, is_fips, no_filesystem, + run_wolfssl, test_main) RSA_PUBKEY_PEM = """\ -----BEGIN PUBLIC KEY----- @@ -22,6 +23,7 @@ -----END PUBLIC KEY-----""" +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class RsaTest(unittest.TestCase): @classmethod @@ -29,12 +31,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - cls.is_fips = is_fips() def _cleanup(self, *files): diff --git a/tests/rand/rand-test.py b/tests/rand/rand-test.py index 214b52b5..f360390d 100644 --- a/tests/rand/rand-test.py +++ b/tests/rand/rand-test.py @@ -8,18 +8,16 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, run_wolfssl, test_main +from wolfclu_test import WOLFSSL_BIN, no_filesystem, run_wolfssl, test_main -class RandTest(unittest.TestCase): +# `rand` writes to stdout without a filesystem, so only the tests that pass a +# file path are skipped on a --disable-filesystem build. +needs_filesystem = unittest.skipIf(no_filesystem(), + "filesystem support disabled") + - @classmethod - def setUpClass(cls): - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") +class RandTest(unittest.TestCase): def test_base64_random(self): r = run_wolfssl("rand", "-base64", "10") @@ -35,6 +33,7 @@ def test_base64_not_repeated(self): self.assertNotEqual(r1.stdout, r2.stdout, "back-to-back random calls should differ") + @needs_filesystem def test_output_file(self): out = "entropy.txt" self.addCleanup(lambda: os.remove(out) @@ -44,6 +43,7 @@ def test_output_file(self): self.assertEqual(r.returncode, 0, r.stderr) self.assertTrue(os.path.isfile(out), "entropy.txt not created") + @needs_filesystem def test_count_after_out_value(self): """`rand -out ` binds to -out and as the byte count, even though sits immediately after the -out value. @@ -85,6 +85,7 @@ def test_plain_raw_to_stdout(self): "plain `rand %d` must emit exactly %d raw bytes " "(no encoding, no trailing newline)" % (n, n)) + @needs_filesystem def test_hex_to_file(self): """`-hex -out file` writes a hex-only file with no trailing newline.""" out = "hex_rand.hex" @@ -124,6 +125,7 @@ def _assert_dup_errors_no_leak(self, args, what): "%s must not leak random bytes to stdout" % what) return r + @needs_filesystem def test_duplicate_out_does_not_leak_to_stdout(self): """Regression: `rand -out f1 N -out f2` must error, not leak bytes. @@ -144,6 +146,7 @@ def test_duplicate_out_does_not_leak_to_stdout(self): self.assertFalse(os.path.exists(f2), "no output file should be created on duplicate -out") + @needs_filesystem def test_duplicate_out_in_value_slot_does_not_leak(self): """Regression: `rand -out -out 16` must error, not leak bytes. @@ -165,6 +168,7 @@ def test_duplicate_out_in_value_slot_does_not_leak(self): self.assertFalse(os.path.exists("16"), "no '16' file should be created on duplicate -out") + @needs_filesystem def test_duplicate_out_trailing_repeat_rejected(self): """`rand -out f1 16 -out`: the trailing -out repeat (count already consumed) must error too, exercising the main-loop seen[] path.""" @@ -188,6 +192,7 @@ def test_duplicate_base64_flag_rejected(self): self._assert_dup_errors_no_leak(["-base64", "-base64", "16"], "duplicate -base64") + @needs_filesystem def test_duplicate_flag_first_seen_in_value_slot_rejected(self): """`rand -out -base64 -base64 16`: duplicate detection is symmetric. @@ -231,6 +236,7 @@ def test_hex_flag_not_swallowed_by_help_check(self): self.assertNotIn("wolfssl rand ", out, "rand 16 -hex must not be treated as help") + @needs_filesystem def test_large_raw_request_allowed(self): """A large raw request must still work (no arbitrary size cap), keeping large keyfiles/blobs supported like `openssl rand`.""" @@ -255,6 +261,7 @@ def test_large_raw_request_allowed(self): self.assertNotEqual(data[:chunk], data[chunk:2 * chunk], "consecutive chunks must differ (no chunk repeat)") + @needs_filesystem def test_large_base64_request_allowed(self): """A large -base64 request must work too: it forces the multi-chunk fill loop and then base64-expands, guarding that interaction.""" @@ -280,6 +287,7 @@ def test_large_base64_request_allowed(self): self.assertNotEqual(decoded[:n - chunk], decoded[chunk:], "the two chunks must differ (no chunk repeat)") + @needs_filesystem def test_chunk_boundary_exact_and_plus_one(self): """Pin the single/multi-chunk transition in the fill loop. @@ -301,6 +309,7 @@ def test_chunk_boundary_exact_and_plus_one(self): self.assertNotEqual(data, b"\x00" * n, "output must not be all zeros") + @needs_filesystem def test_count_before_out_with_flag(self): """`rand -hex 16 -out f` must keep 16 as the count even though it sits ahead of the -out pair: 16 bytes -> 32 hex chars.""" @@ -313,6 +322,7 @@ def test_count_before_out_with_flag(self): self.assertEqual(os.path.getsize(out), 32, "16 byte count before -out must yield 32 hex chars") + @needs_filesystem def test_flag_as_out_value_is_consistent(self): """`rand -out -hex 16`: -hex is BOTH bound as the -out filename and matched as the -hex flag (pre-existing GetOpt whole-argv scan), while @@ -340,6 +350,7 @@ def test_flag_as_out_value_is_consistent(self): self.assertTrue(all(chr(b) in "0123456789abcdef" for b in data), "the -hex flag must still take effect (lowercase hex)") + @needs_filesystem def test_missing_count_errors(self): """`-out` with no byte count must error, not size from the path.""" out = "missing_count.bin" @@ -350,6 +361,7 @@ def test_missing_count_errors(self): self.assertNotEqual(r.returncode, 0, "rand -out with no count must error") + @needs_filesystem def test_numeric_out_path_is_not_count(self): """`rand -out 32` must treat 32 as the path, not the count: it errors (no count given) and never creates a file named '32'.""" @@ -368,6 +380,7 @@ def test_extra_positional_errors(self): self.assertNotEqual(r.returncode, 0, "rand with two positional counts must error") + @needs_filesystem def test_dangling_out_flag_with_count_errors(self): """`-out` as the final token with no filename must error, not fall through to stdout. Regressed once: the NULL filename skipped the open @@ -392,6 +405,7 @@ def test_unknown_flag_errors(self): self.assertNotEqual(r.returncode, 0, "rand with an unrecognized flag must error") + @needs_filesystem def test_bad_count_does_not_truncate_existing_out_file(self): """A bad/missing count must not truncate an existing -out file. diff --git a/tests/server/server-test.py b/tests/server/server-test.py index 4e795f05..4e299d47 100644 --- a/tests/server/server-test.py +++ b/tests/server/server-test.py @@ -8,9 +8,11 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, test_main, find_free_port +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, find_free_port, + no_filesystem, test_main) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class ServerClientTest(unittest.TestCase): @classmethod @@ -18,12 +20,6 @@ def setUpClass(cls): if not os.path.isdir(CERTS_DIR): raise unittest.SkipTest("certs directory not found") - config_log = os.path.join(".", "config.log") - if os.path.isfile(config_log): - with open(config_log, "r") as f: - if "disable-filesystem" in f.read(): - raise unittest.SkipTest("filesystem support disabled") - def test_help(self): """s_server -help prints usage and exits cleanly.""" for flag in ("-help", "-h"): diff --git a/tests/wolfclu_test.py b/tests/wolfclu_test.py index 6909c2e3..8393e170 100644 --- a/tests/wolfclu_test.py +++ b/tests/wolfclu_test.py @@ -88,6 +88,39 @@ def run_wolfssl(*args, stdin_data=None, timeout=60): return subprocess.run(cmd, **kwargs) +_NO_FILESYSTEM = None + +# The probe names a file that cannot exist, so the command must always exit +# non-zero; exit 0 means it has stopped measuring anything. +_NO_FS_PROBE_ARGS = ("x509", "-in", "wolfclu-no-filesystem-probe") + +# Case-insensitive: clu_cert_setup.c prints "No filesystem support", +# clu_request_setup.c "No Filesystem Support.". +_NO_FS_MESSAGE = "no filesystem support" + + +def no_filesystem(): + """True when the build under test has no filesystem support. + + Fails loud rather than open: returning False on a --disable-filesystem + build would stop every suite below from skipping, turning a clean SKIP + run into hundreds of unrelated failures. A missing binary, a timeout or + an unexpectedly successful probe therefore raises instead of guessing. + """ + global _NO_FILESYSTEM + if _NO_FILESYSTEM is None: + # OSError/SubprocessError deliberately uncaught: not a verdict. + r = run_wolfssl(*_NO_FS_PROBE_ARGS) + combined = r.stdout + r.stderr + if r.returncode == 0: + raise RuntimeError( + "filesystem probe `%s %s` unexpectedly succeeded; it can no " + "longer detect --disable-filesystem builds:\n%s" + % (WOLFSSL_BIN, " ".join(_NO_FS_PROBE_ARGS), combined)) + _NO_FILESYSTEM = _NO_FS_MESSAGE in combined.lower() + return _NO_FILESYSTEM + + def is_fips(): """True when linked against a FIPS wolfSSL build (per `wolfssl -v`).""" r = run_wolfssl("-v") @@ -181,6 +214,32 @@ def truncate_sparse(fileobj, size): raise ctypes.WinError() +class _CountingResult(unittest.TextTestResult): + """TextTestResult that also counts the tests which actually ran. + + testsRun cannot answer "did anything run?" on its own: a SkipTest + raised from setUpClass lands in result.skipped without incrementing + testsRun, while @unittest.skipIf increments it once per skipped + method. Counting completions is exact under either style. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.ran = 0 + + def addSuccess(self, test): + super().addSuccess(test) + self.ran += 1 + + def addExpectedFailure(self, test, err): + super().addExpectedFailure(test, err) + self.ran += 1 + + +class _CountingRunner(unittest.TextTestRunner): + resultclass = _CountingResult + + def test_main(): """Run tests with automake-compatible exit codes. @@ -188,13 +247,14 @@ def test_main(): when every test was skipped, so automake would report PASS. This wrapper runs unittest with exit=False and translates the result: - failures/errors -> exit 1 - - all skipped / no tests run -> exit 77 (automake SKIP) + - nothing actually ran -> exit 77 (automake SKIP) - otherwise -> exit 0 (automake PASS) """ - prog = unittest.main(module='__main__', exit=False) + prog = unittest.main(module='__main__', exit=False, + testRunner=_CountingRunner) result = prog.result if not result.wasSuccessful(): sys.exit(1) - if result.testsRun == 0 or len(result.skipped) == result.testsRun: + if result.ran == 0: sys.exit(77) sys.exit(0) diff --git a/tests/x509/CRL-verify-test.py b/tests/x509/CRL-verify-test.py index f2ed613a..28546bc2 100644 --- a/tests/x509/CRL-verify-test.py +++ b/tests/x509/CRL-verify-test.py @@ -6,7 +6,7 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import CERTS_DIR, no_filesystem, run_wolfssl, test_main def _has_crl(): @@ -33,6 +33,7 @@ def _cleanup(*files): os.remove(f) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCRLVerify(unittest.TestCase): """CRL verification tests.""" @@ -150,6 +151,7 @@ def test_crl_invalid_outform_error_message(self): combined)) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCRLText(unittest.TestCase): """CRL -text output tests.""" diff --git a/tests/x509/x509-ca-test.py b/tests/x509/x509-ca-test.py index 514d00d7..2c247b66 100644 --- a/tests/x509/x509-ca-test.py +++ b/tests/x509/x509-ca-test.py @@ -7,7 +7,9 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import ( + WOLFSSL_BIN, CERTS_DIR, no_filesystem, run_wolfssl, test_main +) # Use absolute forward-slash paths so wolfSSL recognizes them as absolute. # Temporary artefacts go under the build directory (CWD under automake), @@ -211,6 +213,7 @@ def _has_altextend(): return "altextend" in combined +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCAHelp(unittest.TestCase): """ca -h and -help should succeed.""" @@ -224,6 +227,7 @@ def test_ca_help(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCASelfSign(unittest.TestCase): """ca -selfsign tests.""" @@ -308,6 +312,7 @@ def test_selfsign_verify_fails_wrong_ca(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCACreateAndVerify(unittest.TestCase): """ca certificate creation and verification.""" @@ -349,6 +354,7 @@ def test_create_and_verify(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCAOverrideConfig(unittest.TestCase): """Override config options with command-line flags.""" @@ -392,7 +398,7 @@ def test_override_extensions_md_days_cert_keyfile(self): self.assertEqual(r.returncode, 0, r.stderr) - +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCAKeyMismatch(unittest.TestCase): """ca with mismatched key should fail.""" @@ -427,6 +433,7 @@ def test_key_mismatch(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCAUniqueSubjectAndSerial(unittest.TestCase): """unique_subject enforcement and serial number handling.""" @@ -547,6 +554,7 @@ def test_rand_file_changes(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCAPolicy(unittest.TestCase): """Policy section enforcement.""" @@ -646,6 +654,7 @@ def test_common_name_mismatch_fails(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCAChimera(unittest.TestCase): """Chimera certificate (altextend) tests.""" @@ -729,6 +738,7 @@ def test_chimera_cert(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestCAOutdirPath(unittest.TestCase): """Test path concatenation for -out with new_certs_dir.""" diff --git a/tests/x509/x509-process-test.py b/tests/x509/x509-process-test.py index 3e63ed86..feedbb81 100644 --- a/tests/x509/x509-process-test.py +++ b/tests/x509/x509-process-test.py @@ -8,7 +8,9 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import ( + WOLFSSL_BIN, CERTS_DIR, no_filesystem, run_wolfssl, test_main +) TESTS_X509_DIR = os.path.dirname(os.path.abspath(__file__)) HAS_OPENSSL = shutil.which("openssl") is not None @@ -84,6 +86,7 @@ def _cleanup(*files): os.remove(f) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ProcessValid(unittest.TestCase): """run1: valid PEM/DER format conversions and combined file handling.""" @@ -235,6 +238,7 @@ def test_1i_combined_pem(self): "combined PEM output differs from original") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ProcessInvalidInput(unittest.TestCase): """run2: invalid argument combinations should fail.""" @@ -292,6 +296,7 @@ def test_2p_outform_noout(self): self._fail("-outform", "-noout") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ProcessValidFiles(unittest.TestCase): """run3: valid input file operations and field extraction.""" @@ -448,6 +453,7 @@ def test_3l_email_from_generated_cert(self): self.assertEqual(r.returncode, 0, r.stderr) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ProcessInvalidFiles(unittest.TestCase): """run4: invalid input files should fail.""" @@ -504,6 +510,7 @@ def test_4f_nonexistent_file_pem(self): self.assertNotEqual(r.returncode, 0) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestMalformedArguments(unittest.TestCase): """ Regression: for malformed arguments """ @@ -518,6 +525,7 @@ def test_5a_malformed_subj_argument(self): self.assertGreater(len(r.stderr), 0) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ModulusNoout(unittest.TestCase): """Regression: x509 -modulus -noout must not crash.""" diff --git a/tests/x509/x509-req-test.py b/tests/x509/x509-req-test.py index 772a7bef..519c9739 100644 --- a/tests/x509/x509-req-test.py +++ b/tests/x509/x509-req-test.py @@ -9,7 +9,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, is_fips, run_wolfssl, test_main +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, is_fips, no_filesystem, + run_wolfssl, test_main) def _tmp(name): @@ -115,6 +116,7 @@ def _flip_last_der_byte(src, dst): f.write(data) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqNew(unittest.TestCase): """Test req -new with various options.""" @@ -479,6 +481,7 @@ def test_req_addext_unsupported_alt_type_fails(self): "test_req_addext_badtype.crt") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqPemDerRoundTrip(unittest.TestCase): """Test PEM <-> DER round-trip for CSR.""" @@ -522,6 +525,7 @@ def test_pem_to_der_to_pem(self): "PEM -> DER -> PEM round-trip mismatch") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqVerify(unittest.TestCase): """Test req -verify, including that a tampered CSR fails (F-5363).""" @@ -581,6 +585,7 @@ def test_verify_tampered_csr_no_output(self): self.assertNotIn("BEGIN CERTIFICATE REQUEST", r.stdout) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ReqSign(unittest.TestCase): """Test x509 -req -signkey signing.""" @@ -638,6 +643,7 @@ def test_x509_req_signkey_succeeds(self): self.assertEqual(r.returncode, 0, r.stderr) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ReqHashAlgorithms(unittest.TestCase): """Test hash algorithm options for x509 -req.""" @@ -708,6 +714,7 @@ def test_sha224_sig_algorithm(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509ReqExtensions(unittest.TestCase): """Test extensions from config file for x509 -req.""" @@ -752,6 +759,7 @@ def test_extfile_v3_alt_ca(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqConfigSubject(unittest.TestCase): """Test subject from config file.""" @@ -784,6 +792,7 @@ def test_subject_from_config(self): "Got: {!r}".format(subject_line)) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqDefaultBasicConstraints(unittest.TestCase): """Test default basic constraints extension.""" @@ -807,6 +816,7 @@ def test_default_ca_true(self): self.assertIn("CA:TRUE", r2.stdout) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqFIPS(unittest.TestCase): """FIPS-conditional tests.""" @@ -869,6 +879,7 @@ def test_newkey_with_passout_keyout(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqHashAndKeyAlgos(unittest.TestCase): """Test hash and key algorithm options for req.""" @@ -918,6 +929,7 @@ def test_sha512(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqAltNamesFullSkip(unittest.TestCase): """Test full alt_names extension with skipped indices.""" @@ -954,6 +966,7 @@ def test_v3_alt_req_full_tenthname(self): +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqPromptValidation(unittest.TestCase): """Test prompt-based config validation.""" @@ -994,6 +1007,7 @@ def test_long_country_code_fails(self): self.assertNotEqual(r.returncode, 0) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqCSRAttributes(unittest.TestCase): """Test CSR attribute printing.""" @@ -1023,6 +1037,7 @@ def test_unsupported_attributes_fail(self): "CSR with unsupported attributes should fail") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqCSRVersion(unittest.TestCase): """Test CSR version number.""" @@ -1117,6 +1132,7 @@ def test_csr_version_openssl_interop(self): """ +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqKeyUsageAbbrev(unittest.TestCase): """Regression: abbreviated keyUsage names must not be accepted.""" @@ -1143,6 +1159,7 @@ def test_abbreviated_ku_rejected(self): "Abbreviated keyUsage 'd' should not match digitalSignature") +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestReqChallengePassword(unittest.TestCase): """req config with challengePassword attribute must succeed.""" diff --git a/tests/x509/x509-verify-test.py b/tests/x509/x509-verify-test.py index 2a92749e..047c2345 100644 --- a/tests/x509/x509-verify-test.py +++ b/tests/x509/x509-verify-test.py @@ -6,7 +6,7 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import CERTS_DIR, no_filesystem, run_wolfssl, test_main def _has_crl(): @@ -19,6 +19,7 @@ def _has_crl(): return "recompile wolfSSL with CRL" not in combined +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509Verify(unittest.TestCase): """Certificate verification tests.""" @@ -125,6 +126,7 @@ def test_partial_chain_no_cafile_no_crash(self): # require a normal exit code regardless of verify success/failure. self.assertGreaterEqual(r.returncode, 0, r.stderr) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509VerifyCRL(unittest.TestCase): """CRL-related verification tests.""" @@ -161,6 +163,7 @@ def test_crl_check_revoked_fails(self): self.assertNotEqual(r.returncode, 0) +@unittest.skipIf(no_filesystem(), "filesystem support disabled") class TestX509VerifyChain(unittest.TestCase): """Certificate chain verification tests."""