diff --git a/appveyor.yml b/appveyor.yml index 0c10d89..969e984 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -92,11 +92,16 @@ environment: APPVEYOR_BUILD_WORKER_IMAGE: macos-monterey HOMEBREW_NO_INSTALL_CLEANUP: 1 CC: clang + CFLAGS: "-I/usr/local/include" + LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "" - TARGET: macos-x64-gcc BUILD_ENVIRONMENT: xcode APPVEYOR_BUILD_WORKER_IMAGE: macos-monterey HOMEBREW_NO_INSTALL_CLEANUP: 1 + CC: gcc + CFLAGS: "-I/usr/local/include" + LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "" - TARGET: macos-x64-gcc-python BUILD_ENVIRONMENT: xcode @@ -104,6 +109,7 @@ environment: PYTHON: "/usr/local/opt/python@3.11/bin/python3" PYTHON_CONFIG: "/usr/local/opt/python@3.11/bin/python3-config" HOMEBREW_NO_INSTALL_CLEANUP: 1 + CC: gcc CFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "--enable-python" @@ -113,6 +119,7 @@ environment: PYTHON: "/usr/local/opt/python@3.11/bin/python3" PYTHON_CONFIG: "/usr/local/opt/python@3.11/bin/python3-config" HOMEBREW_NO_INSTALL_CLEANUP: 1 + CC: gcc CFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib" CONFIGURE_OPTIONS: "--disable-dependency-tracking --prefix=/usr/local --enable-python --with-pyprefix" @@ -148,6 +155,12 @@ environment: HOMEBREW_NO_INSTALL_CLEANUP: 1 PYTHON_VERSION: 3.11 TOXENV: py311 + - TARGET: macos-tox-py312 + BUILD_ENVIRONMENT: python-tox + APPVEYOR_BUILD_WORKER_IMAGE: macos-monterey + HOMEBREW_NO_INSTALL_CLEANUP: 1 + PYTHON_VERSION: 3.12 + TOXENV: py312 - TARGET: cygwin64-gcc BUILD_ENVIRONMENT: cygwin64 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 @@ -236,7 +249,7 @@ install: .\builddokan.ps1 -Configuration ${Configuration} -Platform "x64"; } } - sh: if test ${BUILD_ENVIRONMENT} = "python-tox" || test ${BUILD_ENVIRONMENT} = "xcode"; then brew update-reset && brew update -q; fi -- sh: if test ${BUILD_ENVIRONMENT} = "python-tox" || test ${BUILD_ENVIRONMENT} = "xcode"; then brew install -q gettext gnu-sed || true; fi +- sh: if test ${BUILD_ENVIRONMENT} = "python-tox" || test ${BUILD_ENVIRONMENT} = "xcode"; then brew install -q autoconf automake gettext gnu-sed libtool openssl pkg-config || true; fi - sh: if test ${BUILD_ENVIRONMENT} = "python-tox"; then brew install -q python@${PYTHON_VERSION} tox twine-pypi || true; fi - cmd: if [%BUILD_ENVIRONMENT%]==[python] ( "%PYTHON%" -m pip install -U pip setuptools twine wheel ) diff --git a/configure.ac b/configure.ac index bd266e8..7ca350a 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.71]) AC_INIT( [libbde], - [20230930], + [20231007], [joachim.metz@gmail.com]) AC_CONFIG_SRCDIR( diff --git a/libbde.nuspec b/libbde.nuspec index 9973eb3..5060b64 100644 --- a/libbde.nuspec +++ b/libbde.nuspec @@ -2,7 +2,7 @@ libbde - 20230930 + 20231007 Joachim Metz joachimmetz LGPL-3.0-or-later @@ -10,7 +10,7 @@ false libbde Library to access the BitLocker Drive Encryption (BDE) format - Release of libbde 20230930 + Release of libbde 20231007 Copyright (C) 2011-2023 native diff --git a/m4/libcrypto.m4 b/m4/libcrypto.m4 index 87944a2..507f2bb 100644 --- a/m4/libcrypto.m4 +++ b/m4/libcrypto.m4 @@ -1,6 +1,6 @@ dnl Checks for libcrypto required headers and functions dnl -dnl Version: 20230701 +dnl Version: 20231007 dnl Function to detect whether openssl/evp.h can be used in combination with zlib.h AC_DEFUN([AX_LIBCRYPTO_CHECK_OPENSSL_EVP_ZLIB_COMPATIBILE], @@ -687,6 +687,10 @@ AC_DEFUN([AX_LIBCRYPTO_CHECK_LIB], ac_cv_libcrypto_CPPFLAGS="$openssl_CFLAGS" ac_cv_libcrypto_LIBADD="$openssl_LIBS" + AS_IF( + [test "x$ac_cv_libcrypto_LIBADD" = x], + [ac_cv_libcrypto_LIBADD="-lcrypto"]) + dnl On Cygwin also link zlib since libcrypto relies on it AS_CASE( [$host], diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index c976ee1..0000000 --- a/setup.cfg +++ /dev/null @@ -1,15 +0,0 @@ -[metadata] -name = libbde-python -version = 20230930 -description = Python bindings module for libbde -long_description = Python bindings module for libbde -author = Joachim Metz -author_email = joachim.metz@gmail.com -license = GNU Lesser General Public License v3 or later (LGPLv3+) -license_files = COPYING COPYING.LESSER -classifiers = - Development Status :: 3 - Alpha - Programming Language :: Python - -[options] -python_requires = >=3.7 diff --git a/synctestdata.ps1 b/synctestdata.ps1 index da7fe9c..03d2e7a 100644 --- a/synctestdata.ps1 +++ b/synctestdata.ps1 @@ -17,14 +17,20 @@ If (-Not (Test-Path "${TestInputDirectory}\${TestSet}")) New-Item -Name "${TestInputDirectory}\.pybde\${TestSet}" -ItemType "directory" | Out-Null New-Item -Name "${TestInputDirectory}\.bdeinfo\${TestSet}" -ItemType "directory" | Out-Null } + +@" +# libyal test data options +password=bde-TEST +"@ | Out-File -FilePath test_data_options + ForEach ($TestFile in ${TestFiles} -split " ") { $Url = "https://github.com/log2timeline/dfvfs/blob/main/test_data/${TestFile}?raw=true" Invoke-WebRequest -Uri ${Url} -OutFile "${TestInputDirectory}\${TestSet}\${TestFile}" - "-pbde-TEST" | Out-File -FilePath "${TestInputDirectory}\.libbde\${TestSet}\${TestFile}.password" - "-pbde-TEST" | Out-File -FilePath "${TestInputDirectory}\.pybde\${TestSet}\${TestFile}.password" - "-pbde-TEST" | Out-File -FilePath "${TestInputDirectory}\.bdeinfo\${TestSet}\${TestFile}.password" + Copy-Item test_data_options -Destination "${TestInputDirectory}\.libbde\${TestSet}\${TestFile}.password" + Copy-Item test_data_options -Destination "${TestInputDirectory}\.pybde\${TestSet}\${TestFile}.password" + Copy-Item test_data_options -Destination "${TestInputDirectory}\.bdeinfo\${TestSet}\${TestFile}.password" } diff --git a/synctestdata.sh b/synctestdata.sh index 568f814..8e7db27 100755 --- a/synctestdata.sh +++ b/synctestdata.sh @@ -1,7 +1,7 @@ #!/bin/sh # Script that synchronizes the local test data # -# Version: 20161009 +# Version: 20231001 TEST_SET="public"; TEST_INPUT_DIRECTORY="tests/input"; @@ -12,14 +12,19 @@ mkdir -p "${TEST_INPUT_DIRECTORY}/.libbde/${TEST_SET}"; mkdir -p "${TEST_INPUT_DIRECTORY}/.pybde/${TEST_SET}"; mkdir -p "${TEST_INPUT_DIRECTORY}/.bdeinfo/${TEST_SET}"; +cat > test_data_options << EOT +# libyal test data options +password=bde-TEST +EOT + for TEST_FILE in ${TEST_FILES}; do URL="https://github.com/log2timeline/dfvfs/blob/main/test_data/${TEST_FILE}?raw=true"; curl -L -o "${TEST_INPUT_DIRECTORY}/${TEST_SET}/${TEST_FILE}" ${URL}; - echo "-pbde-TEST" > "${TEST_INPUT_DIRECTORY}/.libbde/${TEST_SET}/${TEST_FILE}.password"; - echo "-pbde-TEST" > "${TEST_INPUT_DIRECTORY}/.pybde/${TEST_SET}/${TEST_FILE}.password"; - echo "-pbde-TEST" > "${TEST_INPUT_DIRECTORY}/.bdeinfo/${TEST_SET}/${TEST_FILE}.password"; + cp test_data_options "${TEST_INPUT_DIRECTORY}/.libbde/${TEST_SET}/${TEST_FILE}.password"; + cp test_data_options "${TEST_INPUT_DIRECTORY}/.pybde/${TEST_SET}/${TEST_FILE}.password"; + cp test_data_options "${TEST_INPUT_DIRECTORY}/.bdeinfo/${TEST_SET}/${TEST_FILE}.password"; done diff --git a/tests/pybde_test_support.py b/tests/pybde_test_support.py index 143f43e..258ba8a 100644 --- a/tests/pybde_test_support.py +++ b/tests/pybde_test_support.py @@ -37,7 +37,7 @@ def test_get_version(self): def test_check_volume_signature(self): """Tests the check_volume_signature function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") @@ -46,7 +46,7 @@ def test_check_volume_signature(self): def test_check_volume_signature_file_object(self): """Tests the check_volume_signature_file_object function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") @@ -56,7 +56,7 @@ def test_check_volume_signature_file_object(self): def test_open(self): """Tests the open function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") @@ -73,7 +73,7 @@ def test_open(self): def test_open_file_object(self): """Tests the open_file_object function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") diff --git a/tests/pybde_test_volume.py b/tests/pybde_test_volume.py index 70b3a3c..1aacebc 100644 --- a/tests/pybde_test_volume.py +++ b/tests/pybde_test_volume.py @@ -158,20 +158,27 @@ def test_signal_abort(self): def test_open(self): """Tests the open function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") - if unittest.offset: + test_offset = getattr(unittest, 'offset', None) + if test_offset: raise unittest.SkipTest("source defines offset") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) bde_volume.open(test_source) @@ -188,7 +195,7 @@ def test_open(self): def test_open_file_object(self): """Tests the open_file_object function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") @@ -196,15 +203,23 @@ def test_open_file_object(self): raise unittest.SkipTest("source not a regular file") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) @@ -221,37 +236,50 @@ def test_open_file_object(self): def test_close(self): """Tests the close function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) with self.assertRaises(IOError): bde_volume.close() def test_open_close(self): """Tests the open and close functions.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: return - if unittest.offset: + test_offset = getattr(unittest, 'offset', None) + if test_offset: raise unittest.SkipTest("source defines offset") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) # Test open and close. bde_volume.open(test_source) @@ -279,11 +307,12 @@ def test_open_close(self): def test_is_locked(self): """Tests the is_locked function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") - if unittest.offset: + test_offset = getattr(unittest, 'offset', None) + if test_offset: raise unittest.SkipTest("source defines offset") bde_volume = pybde.volume() @@ -295,14 +324,21 @@ def test_is_locked(self): bde_volume.close() - if unittest.password or unittest.recovery_password: + password = getattr(unittest, 'password', None) + recovery_password = getattr(unittest, 'recovery_password', None) + + if password or recovery_password: bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + if password: + bde_volume.set_password(password) + + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) bde_volume.open(test_source) @@ -313,20 +349,27 @@ def test_is_locked(self): def test_read_buffer(self): """Tests the read_buffer function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") - if unittest.offset: + test_offset = getattr(unittest, 'offset', None) + if test_offset: raise unittest.SkipTest("source defines offset") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) bde_volume.open(test_source) @@ -401,7 +444,7 @@ def test_read_buffer(self): def test_read_buffer_file_object(self): """Tests the read_buffer function on a file-like object.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") @@ -409,15 +452,23 @@ def test_read_buffer_file_object(self): raise unittest.SkipTest("source not a regular file") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) size = bde_volume.get_size() @@ -432,20 +483,27 @@ def test_read_buffer_file_object(self): def test_read_buffer_at_offset(self): """Tests the read_buffer_at_offset function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") - if unittest.offset: + test_offset = getattr(unittest, 'offset', None) + if test_offset: raise unittest.SkipTest("source defines offset") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) bde_volume.open(test_source) @@ -509,20 +567,27 @@ def test_read_buffer_at_offset(self): def test_seek_offset(self): """Tests the seek_offset function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") - if unittest.offset: + test_offset = getattr(unittest, 'offset', None) + if test_offset: raise unittest.SkipTest("source defines offset") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) bde_volume.open(test_source) @@ -578,20 +643,28 @@ def test_seek_offset(self): def test_get_offset(self): """Tests the get_offset function.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) @@ -602,20 +675,28 @@ def test_get_offset(self): def test_get_size(self): """Tests the get_size function and size property.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) @@ -628,20 +709,28 @@ def test_get_size(self): def test_get_encryption_method(self): """Tests the get_encryption_method function and encryption_method property.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) @@ -654,20 +743,28 @@ def test_get_encryption_method(self): def test_get_creation_time(self): """Tests the get_creation_time function and creation_time property.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) @@ -680,20 +777,28 @@ def test_get_creation_time(self): def test_get_description(self): """Tests the get_description function and description property.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) @@ -706,20 +811,28 @@ def test_get_description(self): def test_get_number_of_key_protectors(self): """Tests the get_number_of_key_protectors function and number_of_key_protectors property.""" - test_source = unittest.source + test_source = getattr(unittest, 'source', None) if not test_source: raise unittest.SkipTest("missing source") bde_volume = pybde.volume() - if unittest.password: - bde_volume.set_password(unittest.password) - if unittest.recovery_password: - bde_volume.set_recovery_password(unittest.recovery_password) - if unittest.startup_key: - bde_volume.read_startup_key(unittest.startup_key) + + password = getattr(unittest, 'password', None) + if password: + bde_volume.set_password(password) + + recovery_password = getattr(unittest, 'recovery_password', None) + if recovery_password: + bde_volume.set_recovery_password(recovery_password) + + startup_key = getattr(unittest, 'startup_key', None) + if startup_key: + bde_volume.read_startup_key(startup_key) + + test_offset = getattr(unittest, 'offset', None) with DataRangeFileObject( - test_source, unittest.offset or 0, None) as file_object: + test_source, test_offset or 0, None) as file_object: bde_volume.open_file_object(file_object) diff --git a/tests/runtests.py b/tests/runtests.py index 33c381d..271948a 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -2,22 +2,7 @@ # # Script to run Python test scripts. # -# Copyright (C) 2011-2023, Joachim Metz -# -# Refer to AUTHORS for acknowledgements. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . +# Version: 20231004 import glob import os @@ -25,6 +10,28 @@ import unittest +test_profile = ".pybde" +input_glob = "*" +option_sets = ["offset", "password", "recovery_password", "startup_key"] + + +def ReadIgnoreList(test_profile): + """Reads the test profile ignore file if it exists. + + Args: + test_profile (str): test profile. + + Returns: + set[str]: ignore list. + """ + ignore_file_path = os.path.join("tests", "input", test_profile, "ignore") + if os.path.isfile(ignore_file_path): + with open(ignore_file_path, "r", encoding="utf-8") as file_object: + return set([line.strip() for line in file_object.readlines()]) + + return set() + + if __name__ == "__main__": print(f"Using Python version {sys.version!s}") @@ -33,30 +40,37 @@ test_scripts = test_loader.discover("tests", pattern="*.py") - test_profile = ".pybde" - input_glob = "*" - - ignore_list = set() - - ignore_file_path = f"tests/input/{test_profile}/ignore" - if os.path.isfile(ignore_file_path): - with open(ignore_file_path, "r", encoding="utf-8") as file_object: - ignore_list = set([line.strip() for line in file_object.readlines()]) + ignore_list = ReadIgnoreList(test_profile) + test_set = None source_file = None - for test_set in glob.glob("tests/input/*"): - test_set = test_set.rsplit('/', maxsplit=1)[-1] + for test_set in glob.glob(os.path.join("tests", "input", "*")): + test_set = test_set.rsplit(os.path.sep, maxsplit=1)[-1] if not test_set or test_set[0] == '.' or test_set in ignore_list: continue - source_files = glob.glob(f"tests/input/{test_set:s}/{input_glob:s}") + source_files = glob.glob(os.path.join( + "tests", "input", test_set, input_glob)) if source_files: source_file = source_files[0] break setattr(unittest, "source", source_file) + for option_set in option_sets: + test_file = os.path.basename(source_file) + test_options_file_path = os.path.join( + "tests", "input", test_profile, test_set, + f"{test_file:s}.{option_set:s}") + if os.path.isfile(test_options_file_path): + with open(test_options_file_path, "r", encoding="utf-8") as file_object: + lines = [line.strip() for line in file_object.readlines()] + if lines[0] == "# libyal test data options": + for line in lines[1:]: + key, value = line.split("=", maxsplit=1) + setattr(unittest, key, value) + test_results = test_runner.run(test_scripts) if not test_results.wasSuccessful(): sys.exit(1) diff --git a/tests/test_bdeinfo.sh b/tests/test_bdeinfo.sh index bafe799..e030b6a 100755 --- a/tests/test_bdeinfo.sh +++ b/tests/test_bdeinfo.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Info tool testing script # -# Version: 20230410 +# Version: 20231005 EXIT_SUCCESS=0; EXIT_FAILURE=1; @@ -9,7 +9,7 @@ EXIT_IGNORE=77; PROFILES=("bdeinfo"); OPTIONS_PER_PROFILE=(""); -OPTION_SETS="keys password recovery_password startup_key"; +OPTION_SETS=("keys" "password" "recovery_password" "startup_key"); INPUT_GLOB="*"; @@ -71,7 +71,7 @@ do IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); - IFS=" " read -a OPTIONS <<< ${OPTIONS_PER_PROFILE[${PROFILE_INDEX}]}; + IFS=" " read -a PROFILE_OPTIONS <<< ${OPTIONS_PER_PROFILE[${PROFILE_INDEX}]}; RESULT=${EXIT_SUCCESS}; @@ -89,8 +89,49 @@ do fi TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); - run_test_on_test_set_with_options "${TEST_SET_DIRECTORY}" "bdeinfo" "with_stdout_reference" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${OPTIONS[@]}"; - RESULT=$?; + RESULT=${EXIT_SUCCESS}; + + if test -f "${TEST_SET_DIRECTORY}/files"; + then + IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); + else + IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); + fi + for INPUT_FILE in "${INPUT_FILES[@]}"; + do + TESTED_WITH_OPTIONS=0; + + for OPTION_SET in ${OPTION_SETS[@]}; + do + TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); + + if test -f ${TEST_DATA_OPTION_FILE}; + then + TESTED_WITH_OPTIONS=1; + + IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); + + run_test_on_input_file "${TEST_SET_DIRECTORY}" "bdeinfo" "with_stdout_reference" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${PROFILE_OPTIONS[@]}" "${OPTIONS[@]}"; + RESULT=$?; + + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi + fi + done + + if test ${TESTED_WITH_OPTIONS} -eq 0; + then + run_test_on_input_file "${TEST_SET_DIRECTORY}" "bdeinfo" "with_stdout_reference" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${PROFILE_OPTIONS[@]}"; + RESULT=$?; + fi + + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi + done # Ignore failures due to corrupted data. if test "${TEST_SET}" = "corrupted"; diff --git a/tests/test_library.sh b/tests/test_library.sh index 6366751..414d399 100755 --- a/tests/test_library.sh +++ b/tests/test_library.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Tests library functions and types. # -# Version: 20230410 +# Version: 20231007 EXIT_SUCCESS=0; EXIT_FAILURE=1; @@ -9,7 +9,7 @@ EXIT_IGNORE=77; LIBRARY_TESTS="aes_ccm_encrypted_key encryption_context error external_key io_handle key key_protector metadata metadata_block_header metadata_entry metadata_header notify password password_keep sector_data sector_data_vector stretch_key volume_header volume_master_key"; LIBRARY_TESTS_WITH_INPUT="support volume"; -OPTION_SETS="password recovery_password startup_key"; +OPTION_SETS=("password" "recovery_password" "startup_key"); INPUT_GLOB="*"; @@ -78,47 +78,54 @@ run_test_with_input() local TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); - local OLDIFS=${IFS}; - - # IFS="\n" is not supported by all platforms. - IFS=" -"; - if test -f "${TEST_SET_DIRECTORY}/files"; then - for INPUT_FILE in `cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"`; + IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); + else + IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); + fi + for INPUT_FILE in "${INPUT_FILES[@]}"; + do + OPTION_INPUT_FILE="${INPUT_FILE}"; + + if test "${OSTYPE}" = "msys"; + then + # A test executable built with MinGW expects a Windows path. + INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; + fi + local TESTED_WITH_OPTIONS=0; + + for OPTION_SET in ${OPTION_SETS[@]}; do - if test "${OSTYPE}" = "msys"; - then - # A test executable built with MinGW expects a Windows path. - INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; - fi - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; - RESULT=$?; + local TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${OPTION_INPUT_FILE}" "${OPTION_SET}"); - if test ${RESULT} -ne ${EXIT_SUCCESS}; + if test -f ${TEST_DATA_OPTION_FILE}; then - break; + TESTED_WITH_OPTIONS=1; + + IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); + + run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${OPTIONS[@]}"; + RESULT=$?; + + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi fi done - else - for INPUT_FILE in `ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}`; - do - if test "${OSTYPE}" = "msys"; - then - # A test executable built with MinGW expects a Windows path. - INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; - fi - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; + + if test ${TESTED_WITH_OPTIONS} -eq 0; + then + run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; RESULT=$?; + fi - if test ${RESULT} -ne ${EXIT_SUCCESS}; - then - break; - fi - done - fi - IFS=${OLDIFS}; + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi + done if test ${RESULT} -ne ${EXIT_SUCCESS}; then diff --git a/tests/test_python_module.sh b/tests/test_python_module.sh index 8501125..e9401ed 100755 --- a/tests/test_python_module.sh +++ b/tests/test_python_module.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Tests Python module functions and types. # -# Version: 20230410 +# Version: 20231005 EXIT_SUCCESS=0; EXIT_FAILURE=1; @@ -9,7 +9,7 @@ EXIT_IGNORE=77; TEST_FUNCTIONS="support"; TEST_FUNCTIONS_WITH_INPUT="volume"; -OPTION_SETS="password recovery_password startup_key"; +OPTION_SETS=("password" "recovery_password" "startup_key"); TEST_TOOL_DIRECTORY="."; INPUT_GLOB="*"; @@ -68,37 +68,47 @@ test_python_function_with_input() local TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); - local OLDIFS=${IFS}; - - # IFS="\n"; is not supported by all platforms. - IFS=" -"; - if test -f "${TEST_SET_DIRECTORY}/files"; then - for INPUT_FILE in `cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"`; + IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); + else + IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); + fi + for INPUT_FILE in "${INPUT_FILES[@]}"; + do + local TESTED_WITH_OPTIONS=0; + + for OPTION_SET in ${OPTION_SETS[@]}; do - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SETS}" "${TEST_SCRIPT}" "${INPUT_FILE}"; - RESULT=$?; + local TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); - if test ${RESULT} -ne ${EXIT_SUCCESS}; + if test -f ${TEST_DATA_OPTION_FILE}; then - break; + TESTED_WITH_OPTIONS=1; + + IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); + + run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SET}" "${TEST_SCRIPT}" "${INPUT_FILE}" "${OPTIONS[@]}"; + RESULT=$?; + + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi fi done - else - for INPUT_FILE in `ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}`; - do - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SETS}" "${TEST_SCRIPT}" "${INPUT_FILE}"; + + if test ${TESTED_WITH_OPTIONS} -eq 0; + then + run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "" "${TEST_SCRIPT}" "${INPUT_FILE}"; RESULT=$?; + fi - if test ${RESULT} -ne ${EXIT_SUCCESS}; - then - break; - fi - done - fi - IFS=${OLDIFS}; + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi + done if test ${RESULT} -ne ${EXIT_SUCCESS}; then diff --git a/tests/test_runner.sh b/tests/test_runner.sh index 6313971..da773fa 100644 --- a/tests/test_runner.sh +++ b/tests/test_runner.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Bash functions to run an executable for testing. # -# Version: 20230410 +# Version: 20231001 # # When CHECK_WITH_ASAN is set to a non-empty value the test executable # is run with asan, otherwise it is run without. @@ -406,9 +406,12 @@ read_test_data_option_file() TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); fi - local OPTIONS=() - local OPTIONS_STRING=`cat "${TEST_DATA_OPTION_FILE}" | head -n 1 | sed 's/[\r\n]*$//'`; + local OPTIONS_STRING=`head -n 1 "${TEST_DATA_OPTION_FILE}" | sed 's/[\r\n]*$//'`; + if test "${OPTIONS_STRING}" = "# libyal test data options"; + then + OPTIONS_STRING=`tail -n +2 "${TEST_DATA_OPTION_FILE}" | sed 's/^offset=/-o/;s/^password=/-p/;s/^recovery_password=/-r/;s/^startup_key=/-s/' | tr '\n' ' '`; + fi echo "${OPTIONS_STRING}"; } @@ -1073,14 +1076,10 @@ run_test_on_input_file() local ARGUMENTS=("$@"); local INPUT_NAME=`basename "${INPUT_FILE}"`; - local OPTIONS=(); local TEST_OUTPUT="${INPUT_NAME}"; if test -n "${OPTION_SET}"; then - OPTIONS_STRING=$(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); - IFS=" " read -a OPTIONS <<< "${OPTIONS_STRING}"; - TEST_OUTPUT="${INPUT_NAME}-${OPTION_SET}"; fi @@ -1092,7 +1091,7 @@ run_test_on_input_file() if test "${TEST_MODE}" = "with_callback"; then - test_callback "${TMPDIR}" "${TEST_SET_DIRECTORY}" "${TEST_OUTPUT}" "${TEST_EXECUTABLE}" "${TEST_INPUT}" ${ARGUMENTS[@]} "${OPTIONS[@]}"; + test_callback "${TMPDIR}" "${TEST_SET_DIRECTORY}" "${TEST_OUTPUT}" "${TEST_EXECUTABLE}" "${TEST_INPUT}" ${ARGUMENTS[@]}; RESULT=$?; elif test "${TEST_MODE}" = "with_stdout_reference"; @@ -1109,7 +1108,7 @@ run_test_on_input_file() local INPUT_FILE_FULL_PATH=$( readlink_f "${INPUT_FILE}" ); local TEST_LOG="${TEST_OUTPUT}.log"; - (cd ${TMPDIR} && run_test_with_input_and_arguments "${TEST_EXECUTABLE}" "${INPUT_FILE_FULL_PATH}" ${ARGUMENTS[@]} "${OPTIONS[@]}" > "${TEST_LOG}"); + (cd ${TMPDIR} && run_test_with_input_and_arguments "${TEST_EXECUTABLE}" "${INPUT_FILE_FULL_PATH}" ${ARGUMENTS[@]} > "${TEST_LOG}"); RESULT=$?; # Compare output if test ran successfully. @@ -1135,7 +1134,7 @@ run_test_on_input_file() fi else - run_test_with_input_and_arguments "${TEST_EXECUTABLE}" "${INPUT_FILE}" ${ARGUMENTS[@]} "${OPTIONS[@]}"; + run_test_with_input_and_arguments "${TEST_EXECUTABLE}" "${INPUT_FILE}" ${ARGUMENTS[@]}; RESULT=$?; fi @@ -1144,22 +1143,12 @@ run_test_on_input_file() if test -n "${TEST_DESCRIPTION}"; then ARGUMENTS=`echo "${ARGUMENTS[*]}" | tr '\n' ' ' | sed 's/[ ]\$//'`; - OPTIONS=`echo "${OPTIONS[*]}" | tr '\n' ' ' | sed 's/[ ]\$//'`; - if test -z "${ARGUMENTS}" && test -z "${OPTIONS}"; + if test -z "${ARGUMENTS}"; then echo -n "${TEST_DESCRIPTION} with input: ${INPUT_FILE}"; - - elif test -z "${ARGUMENTS}"; - then - echo -n "${TEST_DESCRIPTION} with options: '${OPTIONS}' and input: ${INPUT_FILE}"; - - elif test -z "${OPTIONS}"; - then - echo -n "${TEST_DESCRIPTION} with options: '${ARGUMENTS}' and input: ${INPUT_FILE}"; - else - echo -n "${TEST_DESCRIPTION} with options: '${ARGUMENTS} ${OPTIONS}' and input: ${INPUT_FILE}"; + echo -n "${TEST_DESCRIPTION} with options: '${ARGUMENTS}' and input: ${INPUT_FILE}"; fi if test ${RESULT} -ne ${EXIT_SUCCESS}; @@ -1172,122 +1161,3 @@ run_test_on_input_file() return ${RESULT}; } -# Runs the test with options on the input file. -# -# Note that this function is not intended to be directly invoked -# from outside the test runner script. -# -# Arguments: -# a string containing the path of the test set directory -# a string containing the description of the test -# a string containing the test mode -# a string containing the name of the test data option sets -# a string containing the path of the test executable -# a string containing the path of the test input file -# an array containing the arguments for the test executable -# -# Returns: -# an integer containg the exit status of the test executable -# -run_test_on_input_file_with_options() -{ - local TEST_SET_DIRECTORY=$1; - local TEST_DESCRIPTION=$2; - local TEST_MODE=$3; - local OPTION_SETS=$4; - local TEST_EXECUTABLE=$5; - local INPUT_FILE=$6; - shift 6; - local ARGUMENTS=("$@"); - - local RESULT=${EXIT_SUCCESS}; - local TESTED_WITH_OPTIONS=0; - - for OPTION_SET in `echo ${OPTION_SETS} | tr ' ' '\n'`; - do - local TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); - - if ! test -f ${TEST_DATA_OPTION_FILE}; - then - continue - fi - - run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "${TEST_MODE}" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" ${ARGUMENTS[@]}; - RESULT=$?; - - if test ${RESULT} -ne ${EXIT_SUCCESS}; - then - break; - fi - TESTED_WITH_OPTIONS=1; - done - - if test ${RESULT} -eq ${EXIT_SUCCESS} && test ${TESTED_WITH_OPTIONS} -eq 0; - then - run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "${TEST_MODE}" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}" ${ARGUMENTS[@]}; - RESULT=$?; - fi - return ${RESULT}; -} - -# Runs the test with options on the file entries in the test set directory. -# -# Note that this function is not intended to be directly invoked -# from outside the test runner script. -# -# Arguments: -# a string containing the path of the test set directory -# a string containing the description of the test -# a string containing the test mode -# a string containing the name of the test data option sets -# a string containing the path of the test executable -# an array containing the arguments for the test executable -# -# Returns: -# an integer containg the exit status of the test executable -# -run_test_on_test_set_with_options() -{ - local TEST_SET_DIRECTORY=$1; - local TEST_DESCRIPTION=$2; - local TEST_MODE=$3; - local OPTION_SETS=$4; - local TEST_EXECUTABLE=$5; - shift 5; - local ARGUMENTS=("$@"); - - local RESULT=${EXIT_SUCCESS}; - - # IFS="\n"; is not supported by all platforms. - IFS=" -"; - - if test -f "${TEST_SET_DIRECTORY}/files"; - then - for INPUT_FILE in `cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"`; - do - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "${TEST_MODE}" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" ${ARGUMENTS[@]}; - RESULT=$?; - - if test ${RESULT} -ne ${EXIT_SUCCESS}; - then - break; - fi - done - else - for INPUT_FILE in `ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}`; - do - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "${TEST_MODE}" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" ${ARGUMENTS[@]}; - RESULT=$?; - - if test ${RESULT} -ne ${EXIT_SUCCESS}; - then - break; - fi - done - fi - IFS=${OLDIFS}; - - return ${RESULT}; -} - diff --git a/tests/test_tools.sh b/tests/test_tools.sh index 5f045e6..e42b083 100755 --- a/tests/test_tools.sh +++ b/tests/test_tools.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Tests tools functions and types. # -# Version: 20230410 +# Version: 20231007 EXIT_SUCCESS=0; EXIT_FAILURE=1; @@ -9,7 +9,7 @@ EXIT_IGNORE=77; TOOLS_TESTS="info_handle output signal"; TOOLS_TESTS_WITH_INPUT=""; -OPTION_SETS="password recovery_password startup_key"; +OPTION_SETS=("password" "recovery_password" "startup_key"); INPUT_GLOB="*"; @@ -78,47 +78,54 @@ run_test_with_input() local TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); - local OLDIFS=${IFS}; - - # IFS="\n" is not supported by all platforms. - IFS=" -"; - if test -f "${TEST_SET_DIRECTORY}/files"; then - for INPUT_FILE in `cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"`; + IFS="" read -a INPUT_FILES <<< $(cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"); + else + IFS="" read -a INPUT_FILES <<< $(ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}); + fi + for INPUT_FILE in "${INPUT_FILES[@]}"; + do + OPTION_INPUT_FILE="${INPUT_FILE}"; + + if test "${OSTYPE}" = "msys"; + then + # A test executable built with MinGW expects a Windows path. + INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; + fi + local TESTED_WITH_OPTIONS=0; + + for OPTION_SET in ${OPTION_SETS[@]}; do - if test "${OSTYPE}" = "msys"; - then - # A test executable built with MinGW expects a Windows path. - INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; - fi - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; - RESULT=$?; + local TEST_DATA_OPTION_FILE=$(get_test_data_option_file "${TEST_SET_DIRECTORY}" "${OPTION_INPUT_FILE}" "${OPTION_SET}"); - if test ${RESULT} -ne ${EXIT_SUCCESS}; + if test -f ${TEST_DATA_OPTION_FILE}; then - break; + TESTED_WITH_OPTIONS=1; + + IFS=" " read -a OPTIONS <<< $(read_test_data_option_file "${TEST_SET_DIRECTORY}" "${INPUT_FILE}" "${OPTION_SET}"); + + run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SET}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${OPTIONS[@]}"; + RESULT=$?; + + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi fi done - else - for INPUT_FILE in `ls -1d ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}`; - do - if test "${OSTYPE}" = "msys"; - then - # A test executable built with MinGW expects a Windows path. - INPUT_FILE=`echo ${INPUT_FILE} | sed 's?/?\\\\?g'`; - fi - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; + + if test ${TESTED_WITH_OPTIONS} -eq 0; + then + run_test_on_input_file "${TEST_SET_DIRECTORY}" "${TEST_DESCRIPTION}" "default" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}"; RESULT=$?; + fi - if test ${RESULT} -ne ${EXIT_SUCCESS}; - then - break; - fi - done - fi - IFS=${OLDIFS}; + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi + done if test ${RESULT} -ne ${EXIT_SUCCESS}; then