tenzir-test 0.15.0__tar.gz → 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/PKG-INFO +1 -1
- tenzir_test-1.0.0/changelog/releases/v1.0.0/entries/auto-detect-tenzir-binary-with-uvx-fallback.md +11 -0
- tenzir_test-1.0.0/changelog/releases/v1.0.0/manifest.yaml +8 -0
- tenzir_test-1.0.0/changelog/releases/v1.0.0/notes.md +9 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/README.md +5 -3
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/pyproject.toml +1 -1
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/_python_runner.py +7 -2
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/cli.py +0 -16
- tenzir_test-1.0.0/src/tenzir_test/config.py +70 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/engine/state.py +2 -3
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/fixtures/__init__.py +4 -4
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/fixtures/node.py +13 -4
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/run.py +7 -17
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/custom_python_fixture_runner.py +3 -2
- tenzir_test-1.0.0/tests/test_config.py +106 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/tests/test_python_runner.py +2 -2
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/tests/test_run.py +10 -14
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/tests/test_run_config.py +9 -8
- tenzir_test-0.15.0/src/tenzir_test/config.py +0 -57
- tenzir_test-0.15.0/tests/test_config.py +0 -42
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/.gitignore +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/LICENSE +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/README.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/config.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.11.0/entries/01-expose-tenzir-test-as-a-library.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.11.0/manifest.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.11.0/notes.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.12.0/entries/01-honor-no-color-for-python-api-consumers.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.12.0/manifest.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.12.0/notes.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.13.0/entries/01-improve-diagnostics-when-tenzir-node-fails-to-start.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.13.0/entries/01-library-mode-and-package-dirs.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.13.0/manifest.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.13.0/notes.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.13.1/entries/strip-root-paths-from-diff-runner-output.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.13.1/manifest.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.13.1/notes.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.14.0/entries/inline-test-inputs-and-local-inputs-directories.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.14.0/manifest.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.14.0/notes.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.15.0/entries/verbose-output-flag-for-test-results.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.15.0/manifest.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/changelog/releases/v0.15.0/notes.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/README.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/bar/operators/double.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/bar/package.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/bar/test.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/bar/tests/use-foo.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/bar/tests/use-foo.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/foo/operators/increment.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/foo/package.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/foo/test.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/foo/tests/use-bar.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-library/foo/tests/use-bar.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/operators/deeply/nested/twist.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/operators/filter.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/operators/parse.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/package.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/context/01-context-list.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/context/01-context-list.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/context/02-context-update.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/context/02-context-update.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/context/03-context-inspect.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/context/03-context-inspect.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/context/test.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/inputs/sample.log +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/ops.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/ops.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/twist.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-package/tests/twist.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/fixtures/README.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/fixtures/__init__.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/fixtures/http.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/fixtures/server.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/inputs/events.ndjson +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/runners/__init__.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/runners/xxd.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/context/01-context-create.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/context/01-context-create.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/context/02-context-update.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/context/02-context-update.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/context/03-context-inspect.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/context/03-context-inspect.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/context/test.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/fail.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/fail.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/hex/hello.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/hex/hello.xxd +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/http-fixture.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/http-fixture.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/lazy.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/lazy.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/local-inputs/inputs/local-data.ndjson +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/local-inputs/read-local.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/local-inputs/read-local.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/node-fixture.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/node-fixture.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/executor-only/sum.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/executor-only/sum.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/executor-with-http-fixture/request.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/executor-with-http-fixture/request.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/executor-with-http-fixture/test.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/executor-with-node-fixture/context-manager.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/executor-with-node-fixture/context-manager.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/fixture-driving/manual_control.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/fixture-driving/manual_control.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/pure-python/flaky_coin.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/pure-python/flaky_coin.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/pure-python/hello_world.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/python/pure-python/hello_world.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/read-inline-input.input +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/read-inline-input.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/read-inline-input.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/read-inputs.tql +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/read-inputs.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/shell/exit-code-test.sh +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/shell/exit-code-test.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/shell/http-fixture-check.sh +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/shell/http-fixture-check.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/shell/tmp-dir.sh +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-project/tests/shell/tmp-dir.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/README.md +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/fixtures.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/inputs/input.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/tests/hex/reuse.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/tests/hex/reuse.xxd +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/tests/satellite/input.sh +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/tests/satellite/input.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/tests/satellite/marker.sh +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/tests/satellite/marker.txt +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/example-satellite/tests/satellite/test.yaml +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/__init__.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/engine/__init__.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/engine/operations.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/engine/registry.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/engine/worker.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/packages.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/py.typed +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/__init__.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/_utils.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/diff_runner.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/ext_runner.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/runner.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/shell_runner.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/tenzir_runner.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/tql_runner.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/tests/test_cli.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/tests/test_engine_operations.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/tests/test_runner_registry.py +0 -0
- {tenzir_test-0.15.0 → tenzir_test-1.0.0}/tests/test_shell_runner.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tenzir-test
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Reusable test execution framework extracted from the Tenzir repository.
|
|
5
5
|
Project-URL: Homepage, https://github.com/tenzir/test
|
|
6
6
|
Project-URL: Repository, https://github.com/tenzir/test
|
tenzir_test-1.0.0/changelog/releases/v1.0.0/entries/auto-detect-tenzir-binary-with-uvx-fallback.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Auto-detect Tenzir binary with uvx fallback
|
|
3
|
+
type: breaking
|
|
4
|
+
authors:
|
|
5
|
+
- mavam
|
|
6
|
+
- claude
|
|
7
|
+
pr: 7
|
|
8
|
+
created: 2026-01-23T13:05:39.988216Z
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Binary detection now follows a consistent precedence order: environment variable `TENZIR_BINARY` takes priority, followed by a PATH lookup, with `uvx` as the final fallback. The same logic applies to `TENZIR_NODE_BINARY`. Environment variables now support multi-part commands like `TENZIR_BINARY="uvx tenzir"`, giving you full control over how binaries are invoked. The `--tenzir-binary` and `--tenzir-node-binary` CLI flags have been removed in favor of environment variables, which provide more flexibility and clarity.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
created: 2026-01-23
|
|
2
|
+
title: Automatic Binary Detection
|
|
3
|
+
intro: >-
|
|
4
|
+
This release introduces automatic binary detection with a clear precedence order:
|
|
5
|
+
environment variables take priority, followed by PATH lookup, with `uvx` as fallback.
|
|
6
|
+
Environment variables now support multi-part commands for full control over binary
|
|
7
|
+
invocation. The `--tenzir-binary` and `--tenzir-node-binary` CLI flags have been
|
|
8
|
+
removed in favor of environment variables.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
This release introduces automatic binary detection with a clear precedence order: environment variables take priority, followed by PATH lookup, with `uvx` as fallback. Environment variables now support multi-part commands for full control over binary invocation. The `--tenzir-binary` and `--tenzir-node-binary` CLI flags have been removed in favor of environment variables.
|
|
2
|
+
|
|
3
|
+
## 💥 Breaking changes
|
|
4
|
+
|
|
5
|
+
### Auto-detect Tenzir binary with uvx fallback
|
|
6
|
+
|
|
7
|
+
Binary detection now follows a consistent precedence order: environment variable `TENZIR_BINARY` takes priority, followed by a PATH lookup, with `uvx` as the final fallback. The same logic applies to `TENZIR_NODE_BINARY`. Environment variables now support multi-part commands like `TENZIR_BINARY="uvx tenzir"`, giving you full control over how binaries are invoked. The `--tenzir-binary` and `--tenzir-node-binary` CLI flags have been removed in favor of environment variables, which provide more flexibility and clarity.
|
|
8
|
+
|
|
9
|
+
*By @mavam and @claude in #7.*
|
|
@@ -7,10 +7,12 @@ pieces fit together.
|
|
|
7
7
|
|
|
8
8
|
## Prerequisites
|
|
9
9
|
|
|
10
|
-
- A `tenzir` binary on your `PATH`, or an explicit `TENZIR_BINARY`.
|
|
11
|
-
- `tenzir-node` for scenarios that talk to a running node.
|
|
12
10
|
- Python 3.12+ with [`uv`](https://docs.astral.sh/uv/) (used in the commands
|
|
13
11
|
below).
|
|
12
|
+
- A `tenzir` binary on your `PATH`. If not found, the harness falls back to
|
|
13
|
+
`uvx tenzir` when `uv` is installed. Set `TENZIR_BINARY` to override.
|
|
14
|
+
- `tenzir-node` for scenarios that talk to a running node. Same fallback logic
|
|
15
|
+
applies via `TENZIR_NODE_BINARY`.
|
|
14
16
|
|
|
15
17
|
## Layout
|
|
16
18
|
|
|
@@ -83,7 +85,7 @@ example-project/
|
|
|
83
85
|
- **Satellite demo** (`../example-satellite/`): a self-contained project that
|
|
84
86
|
reuses the root fixtures **and** the `xxd` runner while adding its own
|
|
85
87
|
`satellite_marker` fixture. Invoke `uvx tenzir-test --root example-project
|
|
86
|
-
|
|
88
|
+
example-satellite` to run both projects in one go.
|
|
87
89
|
|
|
88
90
|
Every scenario keeps its expected output in a neighbouring `.txt` file. Run with
|
|
89
91
|
`--update` after deliberate behaviour changes to refresh the baselines.
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
import runpy
|
|
6
|
+
import shlex
|
|
6
7
|
import sys
|
|
7
8
|
from contextvars import Token
|
|
8
9
|
from pathlib import Path
|
|
@@ -49,14 +50,18 @@ def _push_context_from_env() -> Token[Any] | None:
|
|
|
49
50
|
config_args_raw = payload.get("config_args", ())
|
|
50
51
|
config_args = tuple(str(arg) for arg in config_args_raw)
|
|
51
52
|
env = dict(os.environ)
|
|
53
|
+
tenzir_binary_str = env.get("TENZIR_PYTHON_FIXTURE_BINARY") or env.get("TENZIR_BINARY")
|
|
54
|
+
tenzir_node_binary_str = env.get("TENZIR_NODE_BINARY")
|
|
52
55
|
context = _fixtures.FixtureContext(
|
|
53
56
|
test=test_path,
|
|
54
57
|
config=config,
|
|
55
58
|
coverage=coverage,
|
|
56
59
|
env=env,
|
|
57
60
|
config_args=config_args,
|
|
58
|
-
tenzir_binary=
|
|
59
|
-
tenzir_node_binary=
|
|
61
|
+
tenzir_binary=tuple(shlex.split(tenzir_binary_str)) if tenzir_binary_str else None,
|
|
62
|
+
tenzir_node_binary=tuple(shlex.split(tenzir_node_binary_str))
|
|
63
|
+
if tenzir_node_binary_str
|
|
64
|
+
else None,
|
|
60
65
|
)
|
|
61
66
|
token = _fixtures.push_context(context)
|
|
62
67
|
return cast(Token[Any], token)
|
|
@@ -39,18 +39,6 @@ def _normalize_exit_code(value: object) -> int:
|
|
|
39
39
|
),
|
|
40
40
|
help="Project root to scan for tests.",
|
|
41
41
|
)
|
|
42
|
-
@click.option(
|
|
43
|
-
"tenzir_binary",
|
|
44
|
-
"--tenzir-binary",
|
|
45
|
-
type=click.Path(path_type=Path, dir_okay=False, writable=False, resolve_path=False),
|
|
46
|
-
help="Path to the tenzir executable.",
|
|
47
|
-
)
|
|
48
|
-
@click.option(
|
|
49
|
-
"tenzir_node_binary",
|
|
50
|
-
"--tenzir-node-binary",
|
|
51
|
-
type=click.Path(path_type=Path, dir_okay=False, writable=False, resolve_path=False),
|
|
52
|
-
help="Path to the tenzir-node executable.",
|
|
53
|
-
)
|
|
54
42
|
@click.option(
|
|
55
43
|
"package_dirs",
|
|
56
44
|
"--package-dirs",
|
|
@@ -150,8 +138,6 @@ def cli(
|
|
|
150
138
|
ctx: click.Context,
|
|
151
139
|
*,
|
|
152
140
|
root: Path | None,
|
|
153
|
-
tenzir_binary: Path | None,
|
|
154
|
-
tenzir_node_binary: Path | None,
|
|
155
141
|
package_dirs: tuple[str, ...],
|
|
156
142
|
tests: tuple[Path, ...],
|
|
157
143
|
update: bool,
|
|
@@ -186,8 +172,6 @@ def cli(
|
|
|
186
172
|
try:
|
|
187
173
|
result = runtime.run_cli(
|
|
188
174
|
root=root,
|
|
189
|
-
tenzir_binary=tenzir_binary,
|
|
190
|
-
tenzir_node_binary=tenzir_node_binary,
|
|
191
175
|
package_dirs=package_paths,
|
|
192
176
|
tests=list(tests),
|
|
193
177
|
update=update,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import shlex
|
|
5
|
+
import shutil
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Mapping
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(slots=True)
|
|
12
|
+
class Settings:
|
|
13
|
+
"""Configuration values steering how the harness discovers binaries and data."""
|
|
14
|
+
|
|
15
|
+
root: Path
|
|
16
|
+
tenzir_binary: tuple[str, ...] | None
|
|
17
|
+
tenzir_node_binary: tuple[str, ...] | None
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def inputs_dir(self) -> Path:
|
|
21
|
+
direct = self.root / "inputs"
|
|
22
|
+
if direct.exists():
|
|
23
|
+
return direct
|
|
24
|
+
nested = self.root / "tests" / "inputs"
|
|
25
|
+
if nested.exists():
|
|
26
|
+
return nested
|
|
27
|
+
return direct
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _resolve_binary(
|
|
31
|
+
env_var: str | None,
|
|
32
|
+
binary_name: str,
|
|
33
|
+
) -> tuple[str, ...] | None:
|
|
34
|
+
"""Resolve a binary with fallback to uvx."""
|
|
35
|
+
if env_var:
|
|
36
|
+
try:
|
|
37
|
+
parts = tuple(shlex.split(env_var))
|
|
38
|
+
except ValueError as e:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
f"Invalid shell syntax in environment variable for {binary_name}: {e}"
|
|
41
|
+
) from e
|
|
42
|
+
if not parts:
|
|
43
|
+
raise ValueError(f"Empty command in environment variable for {binary_name}")
|
|
44
|
+
return parts
|
|
45
|
+
which_result = shutil.which(binary_name)
|
|
46
|
+
if which_result:
|
|
47
|
+
return (which_result,)
|
|
48
|
+
if shutil.which("uvx"):
|
|
49
|
+
if binary_name == "tenzir-node":
|
|
50
|
+
return ("uvx", "--from", "tenzir", "tenzir-node")
|
|
51
|
+
return ("uvx", binary_name)
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def discover_settings(
|
|
56
|
+
*,
|
|
57
|
+
root: Path | None = None,
|
|
58
|
+
env: Mapping[str, str] | None = None,
|
|
59
|
+
) -> Settings:
|
|
60
|
+
"""Produce harness settings by combining CLI overrides with environment defaults."""
|
|
61
|
+
|
|
62
|
+
environment = dict(os.environ if env is None else env)
|
|
63
|
+
|
|
64
|
+
chosen_root = root or environment.get("TENZIR_TEST_ROOT") or Path.cwd()
|
|
65
|
+
root_path = Path(chosen_root).resolve()
|
|
66
|
+
|
|
67
|
+
tenzir_path = _resolve_binary(environment.get("TENZIR_BINARY"), "tenzir")
|
|
68
|
+
node_path = _resolve_binary(environment.get("TENZIR_NODE_BINARY"), "tenzir-node")
|
|
69
|
+
|
|
70
|
+
return Settings(root=root_path, tenzir_binary=tenzir_path, tenzir_node_binary=node_path)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Optional
|
|
5
4
|
|
|
6
5
|
from ..config import Settings
|
|
7
6
|
from tenzir_test import run
|
|
8
7
|
|
|
9
|
-
TENZIR_BINARY:
|
|
10
|
-
TENZIR_NODE_BINARY:
|
|
8
|
+
TENZIR_BINARY: tuple[str, ...] | None = run.TENZIR_BINARY
|
|
9
|
+
TENZIR_NODE_BINARY: tuple[str, ...] | None = run.TENZIR_NODE_BINARY
|
|
11
10
|
ROOT: Path = run.ROOT
|
|
12
11
|
INPUTS_DIR: Path = run.INPUTS_DIR
|
|
13
12
|
|
|
@@ -42,8 +42,8 @@ class FixtureContext:
|
|
|
42
42
|
coverage: bool
|
|
43
43
|
env: dict[str, str]
|
|
44
44
|
config_args: Sequence[str]
|
|
45
|
-
tenzir_binary: str | None
|
|
46
|
-
tenzir_node_binary: str | None
|
|
45
|
+
tenzir_binary: tuple[str, ...] | None
|
|
46
|
+
tenzir_node_binary: tuple[str, ...] | None
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
_CONTEXT: ContextVar[FixtureContext | None] = ContextVar(
|
|
@@ -57,7 +57,7 @@ class Executor:
|
|
|
57
57
|
def __init__(self, env: Mapping[str, str] | None = None) -> None:
|
|
58
58
|
source = env or os.environ
|
|
59
59
|
try:
|
|
60
|
-
self.binary: str = source["TENZIR_NODE_CLIENT_BINARY"]
|
|
60
|
+
self.binary: tuple[str, ...] = tuple(shlex.split(source["TENZIR_NODE_CLIENT_BINARY"]))
|
|
61
61
|
except KeyError as exc: # pragma: no cover - defensive guard
|
|
62
62
|
raise RuntimeError("TENZIR_NODE_CLIENT_BINARY is not configured") from exc
|
|
63
63
|
self.endpoint: str | None = source.get("TENZIR_NODE_CLIENT_ENDPOINT")
|
|
@@ -72,7 +72,7 @@ class Executor:
|
|
|
72
72
|
self, source: str, desired_timeout: float | None = None, mirror: bool = False
|
|
73
73
|
) -> subprocess.CompletedProcess[bytes]:
|
|
74
74
|
cmd = [
|
|
75
|
-
self.binary,
|
|
75
|
+
*self.binary,
|
|
76
76
|
"--bare-mode",
|
|
77
77
|
"--console-verbosity=warning",
|
|
78
78
|
"--multi",
|
|
@@ -165,9 +165,13 @@ def node() -> Iterator[dict[str, str]]:
|
|
|
165
165
|
if context is None:
|
|
166
166
|
raise RuntimeError("node fixture requires an active test context")
|
|
167
167
|
|
|
168
|
-
node_binary = context.tenzir_node_binary
|
|
168
|
+
node_binary: tuple[str, ...] | None = context.tenzir_node_binary
|
|
169
169
|
if not node_binary:
|
|
170
|
-
raise RuntimeError(
|
|
170
|
+
raise RuntimeError(
|
|
171
|
+
"tenzir-node binary not available. The harness checks: "
|
|
172
|
+
"TENZIR_NODE_BINARY env var, PATH lookup, uvx fallback. "
|
|
173
|
+
"Ensure tenzir-node is installed, uv is available, or set TENZIR_NODE_BINARY."
|
|
174
|
+
)
|
|
171
175
|
|
|
172
176
|
env = context.env.copy()
|
|
173
177
|
# Extract and filter config arguments: we handle --config and --package-dirs separately.
|
|
@@ -240,7 +244,7 @@ def node() -> Iterator[dict[str, str]]:
|
|
|
240
244
|
test_root = context.test.parent
|
|
241
245
|
|
|
242
246
|
node_cmd = [
|
|
243
|
-
node_binary,
|
|
247
|
+
*node_binary,
|
|
244
248
|
"--bare-mode",
|
|
245
249
|
"--console-verbosity=warning",
|
|
246
250
|
f"--state-directory={state_dir}",
|
|
@@ -292,9 +296,14 @@ def node() -> Iterator[dict[str, str]]:
|
|
|
292
296
|
)
|
|
293
297
|
raise RuntimeError(f"failed to obtain endpoint from tenzir-node ({detail})")
|
|
294
298
|
|
|
299
|
+
client_binary: str | None = None
|
|
300
|
+
if context.tenzir_binary:
|
|
301
|
+
client_binary = shlex.join(context.tenzir_binary)
|
|
302
|
+
else:
|
|
303
|
+
client_binary = env.get("TENZIR_BINARY")
|
|
295
304
|
fixture_env = {
|
|
296
305
|
"TENZIR_NODE_CLIENT_ENDPOINT": endpoint,
|
|
297
|
-
"TENZIR_NODE_CLIENT_BINARY":
|
|
306
|
+
"TENZIR_NODE_CLIENT_BINARY": client_binary,
|
|
298
307
|
"TENZIR_NODE_CLIENT_TIMEOUT": str(context.config["timeout"]),
|
|
299
308
|
"TENZIR_NODE_STATE_DIRECTORY": str(state_dir),
|
|
300
309
|
"TENZIR_NODE_CACHE_DIRECTORY": str(cache_dir),
|
|
@@ -176,8 +176,8 @@ def detect_execution_mode(root: Path) -> tuple[ExecutionMode, Path | None]:
|
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
_settings: Settings | None = None
|
|
179
|
-
TENZIR_BINARY: str | None = None
|
|
180
|
-
TENZIR_NODE_BINARY: str | None = None
|
|
179
|
+
TENZIR_BINARY: tuple[str, ...] | None = None
|
|
180
|
+
TENZIR_NODE_BINARY: tuple[str, ...] | None = None
|
|
181
181
|
ROOT: Path = Path.cwd()
|
|
182
182
|
INPUTS_DIR: Path = ROOT / "inputs"
|
|
183
183
|
EXECUTION_MODE: ExecutionMode = ExecutionMode.PROJECT
|
|
@@ -1866,9 +1866,9 @@ def get_test_env_and_config_args(
|
|
|
1866
1866
|
if node_config_file.exists():
|
|
1867
1867
|
env["TENZIR_NODE_CONFIG"] = str(node_config_file)
|
|
1868
1868
|
if TENZIR_BINARY:
|
|
1869
|
-
env["TENZIR_BINARY"] = TENZIR_BINARY
|
|
1869
|
+
env["TENZIR_BINARY"] = shlex.join(TENZIR_BINARY)
|
|
1870
1870
|
if TENZIR_NODE_BINARY:
|
|
1871
|
-
env["TENZIR_NODE_BINARY"] = TENZIR_NODE_BINARY
|
|
1871
|
+
env["TENZIR_NODE_BINARY"] = shlex.join(TENZIR_NODE_BINARY)
|
|
1872
1872
|
env["TENZIR_TEST_ROOT"] = str(ROOT)
|
|
1873
1873
|
tmp_dir = _create_test_tmp_dir(test)
|
|
1874
1874
|
env[TEST_TMP_ENV_VAR] = str(tmp_dir)
|
|
@@ -2711,7 +2711,7 @@ def get_version() -> str:
|
|
|
2711
2711
|
return (
|
|
2712
2712
|
subprocess.check_output(
|
|
2713
2713
|
[
|
|
2714
|
-
TENZIR_BINARY,
|
|
2714
|
+
*TENZIR_BINARY,
|
|
2715
2715
|
"--bare-mode",
|
|
2716
2716
|
"--console-verbosity=warning",
|
|
2717
2717
|
"version | select version | write_lines",
|
|
@@ -2949,7 +2949,7 @@ def run_simple_test(
|
|
|
2949
2949
|
if not TENZIR_BINARY:
|
|
2950
2950
|
raise RuntimeError("TENZIR_BINARY must be configured before running tests")
|
|
2951
2951
|
cmd: list[str] = [
|
|
2952
|
-
TENZIR_BINARY,
|
|
2952
|
+
*TENZIR_BINARY,
|
|
2953
2953
|
"--bare-mode",
|
|
2954
2954
|
"--console-verbosity=warning",
|
|
2955
2955
|
"--multi",
|
|
@@ -3359,8 +3359,6 @@ def collect_all_tests(directory: Path) -> Iterator[Path]:
|
|
|
3359
3359
|
def run_cli(
|
|
3360
3360
|
*,
|
|
3361
3361
|
root: Path | None,
|
|
3362
|
-
tenzir_binary: Path | None,
|
|
3363
|
-
tenzir_node_binary: Path | None,
|
|
3364
3362
|
package_dirs: Sequence[Path] | None = None,
|
|
3365
3363
|
tests: Sequence[Path],
|
|
3366
3364
|
update: bool,
|
|
@@ -3448,11 +3446,7 @@ def run_cli(
|
|
|
3448
3446
|
print(f"{INFO} ignoring --update in passthrough mode")
|
|
3449
3447
|
update = False
|
|
3450
3448
|
|
|
3451
|
-
settings = discover_settings(
|
|
3452
|
-
root=root,
|
|
3453
|
-
tenzir_binary=tenzir_binary,
|
|
3454
|
-
tenzir_node_binary=tenzir_node_binary,
|
|
3455
|
-
)
|
|
3449
|
+
settings = discover_settings(root=root)
|
|
3456
3450
|
apply_settings(settings)
|
|
3457
3451
|
_set_cli_packages(list(package_dirs or []))
|
|
3458
3452
|
selected_tests = list(tests)
|
|
@@ -3796,8 +3790,6 @@ def run_cli(
|
|
|
3796
3790
|
def execute(
|
|
3797
3791
|
*,
|
|
3798
3792
|
root: Path | None = None,
|
|
3799
|
-
tenzir_binary: Path | None = None,
|
|
3800
|
-
tenzir_node_binary: Path | None = None,
|
|
3801
3793
|
tests: Sequence[Path] = (),
|
|
3802
3794
|
update: bool = False,
|
|
3803
3795
|
debug: bool = False,
|
|
@@ -3825,8 +3817,6 @@ def execute(
|
|
|
3825
3817
|
resolved_jobs = jobs if jobs is not None else get_default_jobs()
|
|
3826
3818
|
return run_cli(
|
|
3827
3819
|
root=root,
|
|
3828
|
-
tenzir_binary=tenzir_binary,
|
|
3829
|
-
tenzir_node_binary=tenzir_node_binary,
|
|
3830
3820
|
tests=list(tests),
|
|
3831
3821
|
update=update,
|
|
3832
3822
|
debug=debug,
|
{tenzir_test-0.15.0 → tenzir_test-1.0.0}/src/tenzir_test/runners/custom_python_fixture_runner.py
RENAMED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
+
import shlex
|
|
5
6
|
import subprocess
|
|
6
7
|
import sys
|
|
7
8
|
import typing
|
|
@@ -99,9 +100,9 @@ class CustomPythonFixture(ExtRunner):
|
|
|
99
100
|
endpoint = None
|
|
100
101
|
new_pythonpath = os.pathsep.join(pythonpath_entries)
|
|
101
102
|
env["PYTHONPATH"] = new_pythonpath
|
|
102
|
-
env["TENZIR_NODE_CLIENT_BINARY"] = binary
|
|
103
|
+
env["TENZIR_NODE_CLIENT_BINARY"] = shlex.join(binary)
|
|
103
104
|
env["TENZIR_NODE_CLIENT_TIMEOUT"] = str(timeout)
|
|
104
|
-
env.setdefault("TENZIR_PYTHON_FIXTURE_BINARY", binary)
|
|
105
|
+
env.setdefault("TENZIR_PYTHON_FIXTURE_BINARY", shlex.join(binary))
|
|
105
106
|
env["TENZIR_PYTHON_FIXTURE_TIMEOUT"] = str(timeout)
|
|
106
107
|
if node_requested and endpoint:
|
|
107
108
|
env["TENZIR_PYTHON_FIXTURE_ENDPOINT"] = endpoint
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from tenzir_test import config
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_discover_settings_defaults(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
|
11
|
+
monkeypatch.chdir(tmp_path)
|
|
12
|
+
monkeypatch.setattr(config.shutil, "which", lambda name: f"/tmp/{name}")
|
|
13
|
+
|
|
14
|
+
settings = config.discover_settings(env={})
|
|
15
|
+
|
|
16
|
+
assert settings.root == tmp_path.resolve()
|
|
17
|
+
assert settings.inputs_dir == tmp_path / "inputs"
|
|
18
|
+
assert settings.tenzir_binary == ("/tmp/tenzir",)
|
|
19
|
+
assert settings.tenzir_node_binary == ("/tmp/tenzir-node",)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_discover_settings_env_overrides(tmp_path: Path) -> None:
|
|
23
|
+
env = {
|
|
24
|
+
"TENZIR_TEST_ROOT": str(tmp_path / "suite"),
|
|
25
|
+
"TENZIR_BINARY": "/custom/tenzir",
|
|
26
|
+
"TENZIR_NODE_BINARY": "/custom/tenzir-node",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
settings = config.discover_settings(env=env)
|
|
30
|
+
|
|
31
|
+
assert settings.root == (tmp_path / "suite").resolve()
|
|
32
|
+
assert settings.tenzir_binary == ("/custom/tenzir",)
|
|
33
|
+
assert settings.tenzir_node_binary == ("/custom/tenzir-node",)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_discover_settings_env_multipart(tmp_path: Path) -> None:
|
|
37
|
+
"""Environment variables can specify multi-part commands like 'uvx tenzir'."""
|
|
38
|
+
env = {
|
|
39
|
+
"TENZIR_TEST_ROOT": str(tmp_path / "suite"),
|
|
40
|
+
"TENZIR_BINARY": "uvx tenzir",
|
|
41
|
+
"TENZIR_NODE_BINARY": "uvx tenzir-node",
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
settings = config.discover_settings(env=env)
|
|
45
|
+
|
|
46
|
+
assert settings.tenzir_binary == ("uvx", "tenzir")
|
|
47
|
+
assert settings.tenzir_node_binary == ("uvx", "tenzir-node")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_discover_settings_uvx_fallback(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
|
51
|
+
"""When tenzir is not found but uvx is available, fall back to uvx."""
|
|
52
|
+
monkeypatch.chdir(tmp_path)
|
|
53
|
+
|
|
54
|
+
def mock_which(name: str) -> str | None:
|
|
55
|
+
if name == "uvx":
|
|
56
|
+
return "/usr/local/bin/uvx"
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
monkeypatch.setattr(config.shutil, "which", mock_which)
|
|
60
|
+
|
|
61
|
+
settings = config.discover_settings(env={})
|
|
62
|
+
|
|
63
|
+
assert settings.tenzir_binary == ("uvx", "tenzir")
|
|
64
|
+
assert settings.tenzir_node_binary == ("uvx", "--from", "tenzir", "tenzir-node")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_discover_settings_no_binary(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
|
68
|
+
"""When no binary is found and uvx is unavailable, return None."""
|
|
69
|
+
monkeypatch.chdir(tmp_path)
|
|
70
|
+
monkeypatch.setattr(config.shutil, "which", lambda name: None)
|
|
71
|
+
|
|
72
|
+
settings = config.discover_settings(env={})
|
|
73
|
+
|
|
74
|
+
assert settings.tenzir_binary is None
|
|
75
|
+
assert settings.tenzir_node_binary is None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def test_settings_inputs_dir_nested(tmp_path: Path) -> None:
|
|
79
|
+
nested = tmp_path / "tests" / "inputs"
|
|
80
|
+
nested.mkdir(parents=True)
|
|
81
|
+
|
|
82
|
+
settings = config.discover_settings(root=tmp_path)
|
|
83
|
+
|
|
84
|
+
assert settings.inputs_dir == nested
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_discover_settings_malformed_binary(tmp_path: Path) -> None:
|
|
88
|
+
"""Malformed shell syntax in binary env var raises ValueError."""
|
|
89
|
+
env = {
|
|
90
|
+
"TENZIR_TEST_ROOT": str(tmp_path),
|
|
91
|
+
"TENZIR_BINARY": "unclosed 'quote",
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
with pytest.raises(ValueError, match="Invalid shell syntax"):
|
|
95
|
+
config.discover_settings(env=env)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_discover_settings_empty_binary(tmp_path: Path) -> None:
|
|
99
|
+
"""Empty string after parsing raises ValueError."""
|
|
100
|
+
env = {
|
|
101
|
+
"TENZIR_TEST_ROOT": str(tmp_path),
|
|
102
|
+
"TENZIR_BINARY": " ", # Whitespace-only parses to empty
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
with pytest.raises(ValueError, match="Empty command"):
|
|
106
|
+
config.discover_settings(env=env)
|
|
@@ -21,7 +21,7 @@ def python_fixture_root(tmp_path: Path) -> Path:
|
|
|
21
21
|
)
|
|
22
22
|
test_settings = config.Settings(
|
|
23
23
|
root=tmp_path,
|
|
24
|
-
tenzir_binary=run.TENZIR_BINARY or "/usr/bin/tenzir",
|
|
24
|
+
tenzir_binary=run.TENZIR_BINARY or ("/usr/bin/tenzir",),
|
|
25
25
|
tenzir_node_binary=run.TENZIR_NODE_BINARY,
|
|
26
26
|
)
|
|
27
27
|
run.apply_settings(test_settings)
|
|
@@ -267,7 +267,7 @@ def test_executor_from_env() -> None:
|
|
|
267
267
|
"TENZIR_NODE_CLIENT_TIMEOUT": "5",
|
|
268
268
|
}
|
|
269
269
|
executor = fixtures.Executor.from_env(env)
|
|
270
|
-
assert executor.binary == "/usr/bin/tenzir-node"
|
|
270
|
+
assert executor.binary == ("/usr/bin/tenzir-node",)
|
|
271
271
|
assert executor.endpoint == "localhost:0"
|
|
272
272
|
|
|
273
273
|
|
|
@@ -520,8 +520,8 @@ def test_node_fixture_uses_explicit_node_config(tmp_path, monkeypatch):
|
|
|
520
520
|
coverage=False,
|
|
521
521
|
env=env,
|
|
522
522
|
config_args=("--config=/default/tenzir.yaml", "--package-dirs=/pkg"),
|
|
523
|
-
tenzir_binary="/usr/bin/tenzir",
|
|
524
|
-
tenzir_node_binary="/usr/bin/tenzir-node",
|
|
523
|
+
tenzir_binary=("/usr/bin/tenzir",),
|
|
524
|
+
tenzir_node_binary=("/usr/bin/tenzir-node",),
|
|
525
525
|
)
|
|
526
526
|
|
|
527
527
|
token = fixture_api.push_context(context)
|
|
@@ -571,8 +571,8 @@ def test_node_fixture_skips_config_when_unset(monkeypatch):
|
|
|
571
571
|
coverage=False,
|
|
572
572
|
env=env,
|
|
573
573
|
config_args=("--config=/default/tenzir.yaml", "--package-dirs=/pkg"),
|
|
574
|
-
tenzir_binary="/usr/bin/tenzir",
|
|
575
|
-
tenzir_node_binary="/usr/bin/tenzir-node",
|
|
574
|
+
tenzir_binary=("/usr/bin/tenzir",),
|
|
575
|
+
tenzir_node_binary=("/usr/bin/tenzir-node",),
|
|
576
576
|
)
|
|
577
577
|
|
|
578
578
|
token = fixture_api.push_context(context)
|
|
@@ -620,8 +620,8 @@ def test_node_fixture_adds_package_dirs_from_env(monkeypatch):
|
|
|
620
620
|
coverage=False,
|
|
621
621
|
env=env,
|
|
622
622
|
config_args=("--config=/default/tenzir.yaml",),
|
|
623
|
-
tenzir_binary="/usr/bin/tenzir",
|
|
624
|
-
tenzir_node_binary="/usr/bin/tenzir-node",
|
|
623
|
+
tenzir_binary=("/usr/bin/tenzir",),
|
|
624
|
+
tenzir_node_binary=("/usr/bin/tenzir-node",),
|
|
625
625
|
)
|
|
626
626
|
|
|
627
627
|
token = fixture_api.push_context(context)
|
|
@@ -676,8 +676,8 @@ def test_node_fixture_deduplicates_package_dirs(monkeypatch):
|
|
|
676
676
|
coverage=False,
|
|
677
677
|
env=env,
|
|
678
678
|
config_args=("--package-dirs=/pkg,/other",),
|
|
679
|
-
tenzir_binary="/usr/bin/tenzir",
|
|
680
|
-
tenzir_node_binary="/usr/bin/tenzir-node",
|
|
679
|
+
tenzir_binary=("/usr/bin/tenzir",),
|
|
680
|
+
tenzir_node_binary=("/usr/bin/tenzir-node",),
|
|
681
681
|
)
|
|
682
682
|
|
|
683
683
|
token = fixture_api.push_context(context)
|
|
@@ -709,8 +709,8 @@ def test_node_fixture_in_suite_receives_package_dirs(monkeypatch: pytest.MonkeyP
|
|
|
709
709
|
run.apply_settings(
|
|
710
710
|
config.Settings(
|
|
711
711
|
root=package_root,
|
|
712
|
-
tenzir_binary="tenzir",
|
|
713
|
-
tenzir_node_binary="tenzir-node",
|
|
712
|
+
tenzir_binary=("tenzir",),
|
|
713
|
+
tenzir_node_binary=("tenzir-node",),
|
|
714
714
|
)
|
|
715
715
|
)
|
|
716
716
|
run._clear_directory_config_cache()
|
|
@@ -934,8 +934,6 @@ def test_cli_rejects_partial_suite_selection(
|
|
|
934
934
|
with pytest.raises(run.HarnessError) as exc_info:
|
|
935
935
|
run.run_cli(
|
|
936
936
|
root=project_root,
|
|
937
|
-
tenzir_binary=None,
|
|
938
|
-
tenzir_node_binary=None,
|
|
939
937
|
tests=[test_file],
|
|
940
938
|
update=False,
|
|
941
939
|
debug=False,
|
|
@@ -961,8 +959,6 @@ def test_cli_rejects_partial_suite_selection(
|
|
|
961
959
|
with pytest.raises(run.HarnessError) as exc_info:
|
|
962
960
|
run.run_cli(
|
|
963
961
|
root=project_root,
|
|
964
|
-
tenzir_binary=None,
|
|
965
|
-
tenzir_node_binary=None,
|
|
966
962
|
tests=[suite_subdir],
|
|
967
963
|
update=False,
|
|
968
964
|
debug=False,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
import shlex
|
|
4
5
|
import shutil
|
|
5
6
|
import sys
|
|
6
7
|
|
|
@@ -206,9 +207,9 @@ def test_get_test_env_and_config_args(configured_root: Path) -> None:
|
|
|
206
207
|
assert env_override["TENZIR_INPUTS"] == str(custom_inputs.resolve())
|
|
207
208
|
assert args_override == [f"--config={config_file}"]
|
|
208
209
|
if run.TENZIR_BINARY:
|
|
209
|
-
assert env["TENZIR_BINARY"] == run.TENZIR_BINARY
|
|
210
|
+
assert env["TENZIR_BINARY"] == shlex.join(run.TENZIR_BINARY)
|
|
210
211
|
if run.TENZIR_NODE_BINARY:
|
|
211
|
-
assert env["TENZIR_NODE_BINARY"] == run.TENZIR_NODE_BINARY
|
|
212
|
+
assert env["TENZIR_NODE_BINARY"] == shlex.join(run.TENZIR_NODE_BINARY)
|
|
212
213
|
assert "TENZIR_NODE_CONFIG" not in env
|
|
213
214
|
assert args == [f"--config={config_file}"]
|
|
214
215
|
|
|
@@ -508,7 +509,7 @@ def test_run_simple_test_injects_package_dirs(
|
|
|
508
509
|
run.apply_settings(
|
|
509
510
|
config.Settings(
|
|
510
511
|
root=package_root,
|
|
511
|
-
tenzir_binary=sys.executable,
|
|
512
|
+
tenzir_binary=(sys.executable,),
|
|
512
513
|
tenzir_node_binary=None,
|
|
513
514
|
)
|
|
514
515
|
)
|
|
@@ -559,7 +560,7 @@ def test_run_simple_test_merges_package_dirs_from_directory_config(
|
|
|
559
560
|
run.apply_settings(
|
|
560
561
|
config.Settings(
|
|
561
562
|
root=package_root,
|
|
562
|
-
tenzir_binary=sys.executable,
|
|
563
|
+
tenzir_binary=(sys.executable,),
|
|
563
564
|
tenzir_node_binary=None,
|
|
564
565
|
)
|
|
565
566
|
)
|
|
@@ -621,7 +622,7 @@ def test_run_simple_test_respects_inputs_override(
|
|
|
621
622
|
run.apply_settings(
|
|
622
623
|
config.Settings(
|
|
623
624
|
root=package_root,
|
|
624
|
-
tenzir_binary=sys.executable,
|
|
625
|
+
tenzir_binary=(sys.executable,),
|
|
625
626
|
tenzir_node_binary=None,
|
|
626
627
|
)
|
|
627
628
|
)
|
|
@@ -672,7 +673,7 @@ def test_run_simple_test_passthrough_streams_output(
|
|
|
672
673
|
run.apply_settings(
|
|
673
674
|
config.Settings(
|
|
674
675
|
root=tmp_path,
|
|
675
|
-
tenzir_binary=sys.executable,
|
|
676
|
+
tenzir_binary=(sys.executable,),
|
|
676
677
|
tenzir_node_binary=None,
|
|
677
678
|
)
|
|
678
679
|
)
|
|
@@ -718,7 +719,7 @@ def test_run_simple_test_reports_stderr_on_failure(
|
|
|
718
719
|
run.apply_settings(
|
|
719
720
|
config.Settings(
|
|
720
721
|
root=tmp_path,
|
|
721
|
-
tenzir_binary=sys.executable,
|
|
722
|
+
tenzir_binary=(sys.executable,),
|
|
722
723
|
tenzir_node_binary=None,
|
|
723
724
|
)
|
|
724
725
|
)
|
|
@@ -762,7 +763,7 @@ def test_run_simple_test_suppresses_diff_on_interrupt(
|
|
|
762
763
|
run.apply_settings(
|
|
763
764
|
config.Settings(
|
|
764
765
|
root=tmp_path,
|
|
765
|
-
tenzir_binary=sys.executable,
|
|
766
|
+
tenzir_binary=(sys.executable,),
|
|
766
767
|
tenzir_node_binary=None,
|
|
767
768
|
)
|
|
768
769
|
)
|