fix(test): start the runner again by its image path, not argv[0]

The subprocess capture probes, the runner-filter tests and the git-facts diff
probe start (or copy) the test runner itself, by argv[0]. On Windows that is
the caller's spelling: the native python scheduler (run-test-wave.py) finds
the runner by search and passes it without ".exe", and an exact spawn or copy
of that path fails. Started that way, 12 subprocess tests failed and the
runner-filter tests with them; started with ".exe", the same build passed.

tf_runner_image() returns the module path on Windows (cbm_module_path_utf8)
and argv[0] elsewhere; the three sites use it.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
Martin Vogel committed 2026-10-06 05:58:38 +02:00
1 parent 8887437e6d
commit bf7ed74f7f
3 files changed
+28 -3

No files matched your search

+24 -1
View File
@@ -42,6 +42,7 @@ int tf_deselected_count = 0;
#include <io.h>
#include <winsock2.h> /* #798 follow-up: socket-isolation re-exec probe */
#include <windows.h>
#include "foundation/win_utf8.h" /* cbm_module_path_utf8 — the runner's own image */
#else
#include <unistd.h>
#ifdef __APPLE__
@@ -1891,11 +1892,33 @@ extern int tf_maybe_run_subprocess_stdout_probe(int argc, char **argv);
extern void tf_test_impact_runner_filter_set_binary(const char *path);
extern int tf_maybe_run_git_facts_diff_probe(int argc, char **argv);
/* The runner's own image, for the tests that start or copy it again. argv[0]
* is the caller's spelling, and a Windows parent that found the runner by
* search (the native python scheduler, scripts/run-test-wave.py) passes it
* without ".exe", which an exact spawn or copy of that path cannot open. */
const char *tf_runner_image(int argc, char **argv);
const char *tf_runner_image(int argc, char **argv) {
#ifdef _WIN32
static char image[4096];
if (!image[0]) {
char *module = cbm_module_path_utf8();
if (module && strlen(module) < sizeof(image)) {
memcpy(image, module, strlen(module) + 1);
}
free(module);
}
if (image[0]) {
return image;
}
#endif
return argc > 0 && argv ? argv[0] : NULL;
}
int main(int argc, char **argv) {
/* #2003: never let a caller's GIT_DIR/GIT_INDEX_FILE/... redirect fixture
* git commands at the caller's real repository. */
th_clear_git_repo_env();
tf_test_impact_runner_filter_set_binary(argc > 0 && argv ? argv[0] : NULL);
tf_test_impact_runner_filter_set_binary(tf_runner_image(argc, argv));
#ifdef CBM_TEST_COVERAGE
tf_coverage_process_init();
#ifndef _WIN32
+2 -1
View File
@@ -1507,12 +1507,13 @@ static void sp_stdout_payload(unsigned char bytes[SP_STDOUT_BYTES]) {
/* Called before normal harness setup. Normal entry remembers argv[0], whose
* storage lasts through main; the private exact argv grammar never runs suites. */
static int sp_stdin_probe(int argc, char **argv);
const char *tf_runner_image(int argc, char **argv); /* test_main.c */
int tf_maybe_run_subprocess_stdout_probe(int argc, char **argv);
int tf_maybe_run_subprocess_stdout_probe(int argc, char **argv) {
if (argc >= 2 && argv && strcmp(argv[1], "__cbm_subprocess_stdin_probe") == 0)
return sp_stdin_probe(argc, argv);
if (argc < 2 || !argv || strcmp(argv[1], "__cbm_subprocess_stdout_probe") != 0) {
sp_stdout_test_binary = argc > 0 && argv ? argv[0] : NULL;
sp_stdout_test_binary = tf_runner_image(argc, argv);
return -1;
}
if (argc != 4 || (strcmp(argv[2], "binary") != 0 && strcmp(argv[2], "text") != 0 &&
+2 -1
View File
@@ -53,6 +53,7 @@ static bool gf_write(const char *path, const void *bytes, size_t length) {
/* Native executable fixture for Git's optional diff/textconv command. Extra
* arguments added by Git are deliberately ignored. Normal harness entry keeps
* argv[0] for a private executable copy; neither mode changes the environment. */
const char *tf_runner_image(int argc, char **argv); /* test_main.c */
int tf_maybe_run_git_facts_diff_probe(int argc, char **argv);
int tf_maybe_run_git_facts_diff_probe(int argc, char **argv) {
if (argc >= 2 && argv && strcmp(argv[1], "__cbm_git_facts_diff_probe") == 0) {
@@ -74,7 +75,7 @@ int tf_maybe_run_git_facts_diff_probe(int argc, char **argv) {
}
argv[1] = "test_impact_git";
}
gf_runner_binary = argc > 0 && argv ? argv[0] : NULL;
gf_runner_binary = tf_runner_image(argc, argv);
return -1;
}