Merge bitcoin/bitcoin#27561: test: Explicitly specify directory where to search tests for

c44f3f2319 test: Explicitly specify directory where to search tests for (Hennadii Stepanov)

Pull request description:

  For out-of-source builds, the `test/functional/test_runner.py` is supposed to be run from the build directory which allows it to pick the `test/config.ini` file generated by the build system. Currently, it works accidently for the following reasons:
  - on POSIX systems, when running a created by Autoconf symlink to the `test/functional/test_runner.py` in the source directory, it actually has the source directory location in the `sys.path`.
  - on Windows (the `build_msvc` directory) VS project puts and copies every build artifact into the source tree (which is wrong and ugly).

  This PR makes `test/functional/test_runner.py` work from a build directory in any form (a symbolic link, a hard link, a copy) on _all_ supported platforms, which is highly desirable in the upcoming [CMake-based build system](https://github.com/bitcoin/bitcoin/pull/25797).

  For the current master branch, this PR has no behaviour change.

  Required for https://github.com/hebasto/bitcoin/pull/15.

  ---

  **Steps to reproduce the issue**

  While the issue is mostly specific to Windows and CMake builds, it is still possible to reproduce it on the current master branch.

  1. Make an out-of-source build:
  ```
  $ ./autogen.sh
  $ mkdir ../build && cd ../build
  $ ../bitcoin/configure
  $ make
  ```

  2. Note that Autoconf created a symbolic link `test/functional/test_runner.py` in the `../build` directory:
  ```
  $ ls -l test/functional/test_runner.py
  lrwxrwxrwx 1 hebasto hebasto 47 May  5 17:40 test/functional/test_runner.py -> ../../../bitcoin/test/functional/test_runner.py
  ```
  which works flawlessly.

  3. However, replacing this symbolic link with a hard link or a copy of `test/functional/test_runner.py` from the source tree will cause the following error:
  ```
  $ cp ../bitcoin/test/functional/test_runner.py test/functional/test_runner.py
  $ ls -l test/functional/test_runner.py
  $ ./test/functional/test_runner.py
  Temporary test directory at /tmp/test_runner_₿_🏃_20230505_175104
  Running Unit Tests for Test Framework Modules
  E
  ======================================================================
  ERROR: test_framework (unittest.loader._FailedTest)
  ----------------------------------------------------------------------
  ImportError: Failed to import test module: test_framework
  Traceback (most recent call last):
    File "/usr/lib/python3.10/unittest/loader.py", line 154, in loadTestsFromName
      module = __import__(module_name)
  ModuleNotFoundError: No module named 'test_framework'

  ----------------------------------------------------------------------
  Ran 1 test in 0.000s

  FAILED (errors=1)
  Early exiting after failure in TestFramework unit tests
  ```

ACKs for top commit:
  stickies-v:
    re-ACK c44f3f2319
  MarcoFalke:
    lgtm ACK c44f3f2319 💸

Tree-SHA512: 622ff629080a55f76dd4c1dab6699de0e9f06b75da3315cd3b31b972ef4bde746458bf3e8a95e879b3c6a63be2368af70005a83f6a3c85c4f1ba5be51e91a61d
This commit is contained in:
fanquake
2023-05-22 10:02:35 +01:00

View File

@@ -528,6 +528,12 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=
# Test Framework Tests
print("Running Unit Tests for Test Framework Modules")
tests_dir = src_dir + '/test/functional/'
# This allows `test_runner.py` to work from an out-of-source build directory using a symlink,
# a hard link or a copy on any platform. See https://github.com/bitcoin/bitcoin/pull/27561.
sys.path.append(tests_dir)
test_framework_tests = unittest.TestSuite()
for module in TEST_FRAMEWORK_MODULES:
test_framework_tests.addTest(unittest.TestLoader().loadTestsFromName("test_framework.{}".format(module)))
@@ -536,8 +542,6 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=
logging.debug("Early exiting after failure in TestFramework unit tests")
sys.exit(False)
tests_dir = src_dir + '/test/functional/'
flags = ['--cachedir={}'.format(cache_dir)] + args
if enable_coverage: