From c983c1e5cc9d061dd70dfd94d8ae844f1134b76f Mon Sep 17 00:00:00 2001 From: Joachim Metz Date: Sat, 21 Oct 2023 07:57:39 +0200 Subject: [PATCH] Applied updates and changes for deployment --- .github/workflows/build_wheel.yml | 42 ++++++++ .gitignore | 6 +- appveyor.yml | 13 +++ configure.ac | 3 +- m4/python.m4 | 10 +- pypff/pypff_file_object_io_handle.c | 6 +- pyproject.toml | 4 + setup.cfg | 13 +++ setup.cfg.in | 15 +++ setup.py | 158 +++++++--------------------- tests/runtests.py | 77 ++++++++++++++ tests/test_library.sh | 75 +++++++------ tests/test_pffexport.sh | 106 ++++++++++++------- tests/test_pffinfo.sh | 51 ++++++++- tests/test_python_module.sh | 58 +++++----- tests/test_runner.sh | 152 ++------------------------ tests/test_tools.sh | 75 +++++++------ tox.ini | 21 ++-- 18 files changed, 471 insertions(+), 414 deletions(-) create mode 100644 .github/workflows/build_wheel.yml create mode 100644 pyproject.toml create mode 100644 setup.cfg.in create mode 100755 tests/runtests.py diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml new file mode 100644 index 00000000..cb0224a9 --- /dev/null +++ b/.github/workflows/build_wheel.yml @@ -0,0 +1,42 @@ +# Build wheel from source using tox. +name: build_wheel +on: [push, pull_request] +permissions: read-all +jobs: + build_wheel: + runs-on: ubuntu-22.04 + strategy: + matrix: + include: + - python-version: '3.7' + toxenv: 'py37' + - python-version: '3.8' + toxenv: 'py38' + - python-version: '3.9' + toxenv: 'py39' + - python-version: '3.10' + toxenv: 'py310' + - python-version: '3.11' + toxenv: 'py311' + - python-version: '3.12' + toxenv: 'py312' + steps: + - uses: actions/checkout@v3 + - name: Install build dependencies + run: | + sudo add-apt-repository universe && + sudo add-apt-repository -y ppa:deadsnakes/ppa && + sudo apt-get update && + sudo apt-get install -y autoconf automake autopoint build-essential git libtool pkg-config python${{ matrix.python-version }} python${{ matrix.python-version }}-dev python${{ matrix.python-version }}-venv python3-distutils python3-pip python3-setuptools + - name: Install tox + run: | + python3 -m pip install tox + - name: Download test data + run: | + if test -x "synctestdata.sh"; then ./synctestdata.sh; fi + - name: Prepare build + run: | + ./synclibs.sh --use-head && ./autogen.sh && ./configure + - name: Build Python wheel + run: | + tox -e${{ matrix.toxenv }} diff --git a/.gitignore b/.gitignore index 9f2cdf34..97e30ee2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # Files to ignore by git # -# Version: 20230405 +# Version: 20230926 # Generic auto-generated build files *~ @@ -25,10 +25,13 @@ *.swp *.Tpo *.trs +*.whl /*.egg-info/ +__pycache__ .deps .dirstamp .libs +.tox INSTALL Makefile Makefile.bcc @@ -125,6 +128,7 @@ stamp-h[1-9] /libpff/libpff.rc /libpff/libpff_definitions.h /pypff-python[23]/*.[ch] +/setup.cfg /jpff/classnoinst.stamp /pfftools/*.exe /pfftools/pffexport diff --git a/appveyor.yml b/appveyor.yml index 425586da..f319193f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -84,11 +84,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 @@ -96,6 +101,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" @@ -105,6 +111,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" @@ -140,6 +147,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 diff --git a/configure.ac b/configure.ac index d7471667..0e3a7f82 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.71]) AC_INIT( [libpff], - [20230906], + [20231022], [joachim.metz@gmail.com]) AC_CONFIG_SRCDIR( @@ -219,6 +219,7 @@ AC_CONFIG_FILES([dpkg/changelog]) AC_CONFIG_FILES([libpff/libpff.rc]) AC_CONFIG_FILES([libpff.pc]) AC_CONFIG_FILES([libpff.spec]) +AC_CONFIG_FILES([setup.cfg]) dnl Generate a source configuration file AC_CONFIG_HEADERS([common/config.h]) diff --git a/m4/python.m4 b/m4/python.m4 index 307e15c0..e10bc9f7 100644 --- a/m4/python.m4 +++ b/m4/python.m4 @@ -1,6 +1,6 @@ dnl Functions for Python bindings dnl -dnl Version: 20211114 +dnl Version: 20230923 dnl Function to check if the python binary is available dnl "python${PYTHON_VERSION} python python# python#.#" @@ -8,7 +8,7 @@ AC_DEFUN([AX_PROG_PYTHON], [AS_IF( [test "x${PYTHON_VERSION}" != x], [ax_python_progs="python${PYTHON_VERSION}"], - [ax_python_progs="python python3 python3.11 python3.10 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2 python2.7 python2.6 python2.5"]) + [ax_python_progs="python python3 python3.12 python3.11 python3.10 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2 python2.7 python2.6 python2.5"]) AC_CHECK_PROGS( [PYTHON], [$ax_python_progs]) @@ -58,7 +58,7 @@ AC_DEFUN([AX_PROG_PYTHON2], dnl Function to check if the python3 binary is available dnl "python3 python3.#" AC_DEFUN([AX_PROG_PYTHON3], - [ax_python3_progs="python3 python3.11 python3.10 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0" + [ax_python3_progs="python3 python3.12 python3.11 python3.10 python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0" AC_CHECK_PROGS( [PYTHON3], [$ax_python3_progs]) @@ -95,7 +95,7 @@ AC_DEFUN([AX_PROG_PYTHON_CONFIG], [test "x${PYTHON_CONFIG}" = x], [AC_CHECK_PROGS( [PYTHON_CONFIG], - [python-config python3-config python3.11-config python3.10-config python3.9-config python3.8-config python3.7-config python3.6-config python3.5-config python3.4-config python3.3-config python3.2-config python3.1-config python3.0-config python2-config python2.7-config python2.6-config python2.5-config]) + [python-config python3-config python3.12-config python3.11-config python3.10-config python3.9-config python3.8-config python3.7-config python3.6-config python3.5-config python3.4-config python3.3-config python3.2-config python3.1-config python3.0-config python2-config python2.7-config python2.6-config python2.5-config]) ]) AS_IF( [test "x${PYTHON_CONFIG}" = x], @@ -131,7 +131,7 @@ AC_DEFUN([AX_PROG_PYTHON3_CONFIG], [test "x${PYTHON3_CONFIG}" = x], [AC_CHECK_PROGS( [PYTHON3_CONFIG], - [python3-config python3.11-config python3.10-config python3.9-config python3.8-config python3.7-config python3.6-config python3.5-config python3.4-config python3.3-config python3.2-config python3.1-config python3.0-config]) + [python3-config python3.12-config python3.11-config python3.10-config python3.9-config python3.8-config python3.7-config python3.6-config python3.5-config python3.4-config python3.3-config python3.2-config python3.1-config python3.0-config]) ]) AS_IF( [test "x${PYTHON3_CONFIG}" = x], diff --git a/pypff/pypff_file_object_io_handle.c b/pypff/pypff_file_object_io_handle.c index 251918bd..bd0dc6cf 100644 --- a/pypff/pypff_file_object_io_handle.c +++ b/pypff/pypff_file_object_io_handle.c @@ -232,13 +232,13 @@ int pypff_file_object_io_handle_free( Py_DecRef( ( *file_object_io_handle )->file_object ); - PyGILState_Release( - gil_state ); - PyMem_Free( *file_object_io_handle ); *file_object_io_handle = NULL; + + PyGILState_Release( + gil_state ); } return( 1 ); } diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..1870a2ed --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,4 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" + diff --git a/setup.cfg b/setup.cfg index 1ded777e..af7c8ce5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,15 @@ [metadata] +name = libpff-python +version = 20231022 +description = Python bindings module for libpff +long_description = Python bindings module for libpff +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/setup.cfg.in b/setup.cfg.in new file mode 100644 index 00000000..84515baf --- /dev/null +++ b/setup.cfg.in @@ -0,0 +1,15 @@ +[metadata] +name = libpff-python +version = @VERSION@ +description = Python bindings module for libpff +long_description = Python bindings module for libpff +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/setup.py b/setup.py index afd9215c..3a86854a 100755 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # # Script to build and install Python-bindings. -# Version: 20230411 +# Version: 20230909 from __future__ import print_function @@ -25,44 +25,11 @@ from setuptools.command.build_ext import build_ext from setuptools.command.sdist import sdist -try: - from distutils.command.bdist_msi import bdist_msi -except ImportError: - bdist_msi = None -try: - from setuptools.command.bdist_rpm import bdist_rpm -except ImportError: - from distutils.command.bdist import bdist as bdist_rpm - - -if not bdist_msi: - custom_bdist_msi = None -else: - class custom_bdist_msi(bdist_msi): - """Custom handler for the bdist_msi command.""" - - def run(self): - """Builds an MSI.""" - # Make a deepcopy of distribution so the following version changes - # only apply to bdist_msi. - self.distribution = copy.deepcopy(self.distribution) - - # bdist_msi does not support the library version so we add ".1" - # as a work around. - self.distribution.metadata.version = "{0:s}.1".format( - self.distribution.metadata.version) - - bdist_msi.run(self) - - -class custom_bdist_rpm(bdist_rpm): - """Custom handler for the bdist_rpm command.""" - - def run(self): - """Builds a RPM.""" - print("'setup.py bdist_rpm' command not supported use 'rpmbuild' instead.") - sys.exit(1) +if (sys.version_info[0], sys.version_info[1]) < (3, 7): + print(("Unsupported Python version: {0:s}, version 3.7 or higher " + "required.").format(sys.version)) + sys.exit(1) class custom_build_ext(build_ext): @@ -218,49 +185,25 @@ def module_name(self): """The Python module name.""" return "py{0:s}".format(self.library_name[3:]) - @property - def package_name(self): - """The package name.""" - return "{0:s}-python".format(self.library_name) - - @property - def package_description(self): - """The package description.""" - return "Python bindings module for {0:s}".format(self.library_name) - - @property - def project_url(self): - """The project URL.""" - return "https://github.com/libyal/{0:s}/".format(self.library_name) - def _ReadConfigureAc(self): """Reads configure.ac to initialize the project information.""" - file_object = open("configure.ac", "rb") - if not file_object: - raise IOError("Unable to open: configure.ac") - - found_ac_init = False - found_library_name = False - for line in file_object.readlines(): - line = line.strip() - if found_library_name: - library_version = line[1:-2] - if sys.version_info[0] >= 3: - library_version = library_version.decode("ascii") - self.library_version = library_version - break - - elif found_ac_init: - library_name = line[1:-2] - if sys.version_info[0] >= 3: - library_name = library_name.decode("ascii") - self.library_name = library_name - found_library_name = True - - elif line.startswith(b"AC_INIT"): - found_ac_init = True - - file_object.close() + with open("configure.ac", "r", encoding="utf-8") as file_object: + found_ac_init = False + found_library_name = False + for line in file_object.readlines(): + line = line.strip() + if found_library_name: + library_version = line[1:-2] + self.library_version = library_version + break + + elif found_ac_init: + library_name = line[1:-2] + self.library_name = library_name + found_library_name = True + + elif line.startswith("AC_INIT"): + found_ac_init = True if not self.library_name or not self.library_version: raise RuntimeError( @@ -271,30 +214,23 @@ def _ReadMakefileAm(self): if not self.library_name: raise RuntimeError("Missing library name") - file_object = open("Makefile.am", "rb") - if not file_object: - raise IOError("Unable to open: Makefile.am") - - found_subdirs = False - for line in file_object.readlines(): - line = line.strip() - if found_subdirs: - library_name, _, _ = line.partition(b" ") - if sys.version_info[0] >= 3: - library_name = library_name.decode("ascii") + with open("Makefile.am", "r", encoding="utf-8") as file_object: + found_subdirs = False + for line in file_object.readlines(): + line = line.strip() + if found_subdirs: + library_name, _, _ = line.partition(" ") - self.include_directories.append(library_name) + self.include_directories.append(library_name) - if library_name.startswith("lib"): - self.library_names.append(library_name) + if library_name.startswith("lib"): + self.library_names.append(library_name) - if library_name == self.library_name: - break + if library_name == self.library_name: + break - elif line.startswith(b"SUBDIRS"): - found_subdirs = True - - file_object.close() + elif line.startswith("SUBDIRS"): + found_subdirs = True if not self.include_directories or not self.library_names: raise RuntimeError( @@ -306,12 +242,8 @@ def _ReadMakefileAm(self): CMDCLASS = { "build_ext": custom_build_ext, - "bdist_rpm": custom_bdist_rpm, "sdist": custom_sdist} -if custom_bdist_msi: - CMDCLASS["bdist_msi"] = custom_bdist_msi - SOURCES = [] # TODO: replace by detection of MSC @@ -344,18 +276,7 @@ def _ReadMakefileAm(self): # TODO: find a way to detect missing python.h # e.g. on Ubuntu python-dev is not installed by python-pip -# TODO: what about description and platform in egg file - -setup( - name=project_information.package_name, - url=project_information.project_url, - version=project_information.library_version, - description=project_information.package_description, - long_description=project_information.package_description, - long_description_content_type="text/plain", - author="Joachim Metz", - author_email="joachim.metz@gmail.com", - license="GNU Lesser General Public License v3 or later (LGPLv3+)", +setup_args = dict( cmdclass=CMDCLASS, ext_modules=[ Extension( @@ -364,8 +285,9 @@ def _ReadMakefileAm(self): include_dirs=project_information.include_directories, libraries=[], library_dirs=[], - sources=SOURCES, - ), - ], + sources=SOURCES + ) + ] ) +setup(**setup_args) diff --git a/tests/runtests.py b/tests/runtests.py new file mode 100755 index 00000000..f7e87efb --- /dev/null +++ b/tests/runtests.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# +# Script to run Python test scripts. +# +# Version: 20231009 + +import glob +import os +import sys +import unittest + + +test_profile = ".pypff" +input_glob = "*" +option_sets = [] + + +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}") + + test_loader = unittest.TestLoader() + test_runner = unittest.TextTestRunner(verbosity=2) + + test_scripts = test_loader.discover("tests", pattern="*.py") + + ignore_list = ReadIgnoreList(test_profile) + + test_set = None + source_file = None + + 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(os.path.join( + "tests", "input", test_set, input_glob)) + if source_files: + source_file = source_files[0] + break + + setattr(unittest, "source", source_file) + + if 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_library.sh b/tests/test_library.sh index 40be80fc..ff676460 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="allocation_table attached_file_io_handle attachment bit_stream block_descriptor block_tree block_tree_node checksum column_definition compression data_array data_array_entry data_block deflate descriptors_index encryption error file_header folder free_map huffman_tree index index_node index_value io_handle item item_descriptor item_tree item_values local_descriptor_value local_descriptors local_descriptors_node local_descriptors_tree mapi_value message multi_value name_to_id_map_entry notify offsets_index record_entry record_set reference_descriptor table table_block_index table_header table_index_value value_type"; LIBRARY_TESTS_WITH_INPUT="file support"; -OPTION_SETS=""; +OPTION_SETS=(); 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_pffexport.sh b/tests/test_pffexport.sh index c9d97e0a..b519b596 100755 --- a/tests/test_pffexport.sh +++ b/tests/test_pffexport.sh @@ -1,14 +1,15 @@ #!/usr/bin/env bash # Export tool testing script # -# Version: 20230410 +# Version: 20231005 EXIT_SUCCESS=0; EXIT_FAILURE=1; EXIT_IGNORE=77; -OPTION_SETS=""; -OPTIONS=(-d); +PROFILES=("pffexport"); +OPTIONS_PER_PROFILE=("-d"); +OPTION_SETS=(); INPUT_GLOB="*"; @@ -115,61 +116,86 @@ then exit ${EXIT_IGNORE}; fi -TEST_PROFILE_DIRECTORY=$(get_test_profile_directory "input" "pffexport"); +for PROFILE_INDEX in ${!PROFILES[*]}; +do + TEST_PROFILE=${PROFILES[${PROFILE_INDEX}]}; -IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); + TEST_PROFILE_DIRECTORY=$(get_test_profile_directory "input" "${TEST_PROFILE}"); -RESULT=${EXIT_SUCCESS}; + IGNORE_LIST=$(read_ignore_list "${TEST_PROFILE_DIRECTORY}"); -for TEST_SET_INPUT_DIRECTORY in input/*; -do - if ! test -d "${TEST_SET_INPUT_DIRECTORY}"; - then - continue; - fi - if check_for_directory_in_ignore_list "${TEST_SET_INPUT_DIRECTORY}" "${IGNORE_LIST}"; - then - continue; - fi + IFS=" " read -a PROFILE_OPTIONS <<< ${OPTIONS_PER_PROFILE[${PROFILE_INDEX}]}; - TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); + RESULT=${EXIT_SUCCESS}; - OLDIFS=${IFS}; + for TEST_SET_INPUT_DIRECTORY in input/*; + do + if ! test -d "${TEST_SET_INPUT_DIRECTORY}"; + then + continue; + fi + TEST_SET=`basename ${TEST_SET_INPUT_DIRECTORY}`; - # IFS="\n"; is not supported by all platforms. - IFS=" -"; + if check_for_test_set_in_ignore_list "${TEST_SET}" "${IGNORE_LIST}"; + then + continue; + fi + TEST_SET_DIRECTORY=$(get_test_set_directory "${TEST_PROFILE_DIRECTORY}" "${TEST_SET_INPUT_DIRECTORY}"); - if test -f "${TEST_SET_DIRECTORY}/files"; - then - for INPUT_FILE in `cat ${TEST_SET_DIRECTORY}/files | sed "s?^?${TEST_SET_INPUT_DIRECTORY}/?"`; + 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 - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "pffexport" "with_callback" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${OPTIONS[@]}"; - RESULT=$?; + TESTED_WITH_OPTIONS=0; - if test ${RESULT} -ne ${EXIT_SUCCESS}; + 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}" "pffinfo" "with_callback" "${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 - break; + run_test_on_input_file "${TEST_SET_DIRECTORY}" "pffinfo" "with_callback" "" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${PROFILE_OPTIONS[@]}"; + RESULT=$?; fi - done - else - for INPUT_FILE in `ls -1 ${TEST_SET_INPUT_DIRECTORY}/${INPUT_GLOB}`; - do - run_test_on_input_file_with_options "${TEST_SET_DIRECTORY}" "pffexport" "with_callback" "${OPTION_SETS}" "${TEST_EXECUTABLE}" "${INPUT_FILE}" "${OPTIONS[@]}"; - RESULT=$?; if test ${RESULT} -ne ${EXIT_SUCCESS}; then break; fi done - fi - IFS=${OLDIFS}; - if test ${RESULT} -ne ${EXIT_SUCCESS}; - then - break; - fi + # Ignore failures due to corrupted data. + if test "${TEST_SET}" = "corrupted"; + then + RESULT=${EXIT_SUCCESS}; + fi + if test ${RESULT} -ne ${EXIT_SUCCESS}; + then + break; + fi + done done exit ${RESULT}; diff --git a/tests/test_pffinfo.sh b/tests/test_pffinfo.sh index f4fce3c7..9add2a05 100755 --- a/tests/test_pffinfo.sh +++ b/tests/test_pffinfo.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=("pffinfo"); OPTIONS_PER_PROFILE=(""); -OPTION_SETS=""; +OPTION_SETS=(); 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}" "pffinfo" "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}" "pffinfo" "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}" "pffinfo" "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_python_module.sh b/tests/test_python_module.sh index 1a42a311..daaead13 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=""; TEST_FUNCTIONS_WITH_INPUT="file support"; -OPTION_SETS=""; +OPTION_SETS=(); 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 63139717..e527367a 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: 20231013 # # 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/;s/virtual_address=/-v/' | 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 ea21489a..aa0aa6f9 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=""; +OPTION_SETS=(); 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/tox.ini b/tox.ini index df530a0f..ce99f27b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,15 +1,20 @@ [tox] -envlist = py3{7,8,9,10,11} +envlist = py3{7,8,9,10,11,12} [testenv] usedevelop = True -allowlist_externals = ./setup.py pip_pre = True passenv = - CFLAGS - CPPFLAGS - INCLUDE - LDFLAGS - LIB + CFLAGS + CPPFLAGS + INCLUDE + LDFLAGS + LIB +deps = + build + setuptools + wheel commands = - ./setup.py bdist_wheel + python -m build --no-isolation --outdir=dist --wheel + python -m pip install --no-index --find-links=dist libpff-python + python tests/runtests.py