test: prove captured action stdin isolation
This commit is contained in:
@@ -5928,6 +5928,117 @@ Checked command-global allocation-failure parity remains owned by
|
|||||||
crosses the former fixed environment-size boundary and verifies that no
|
crosses the former fixed environment-size boundary and verifies that no
|
||||||
partial execution environment or staged `.new` state is published.
|
partial execution environment or staged `.new` state is published.
|
||||||
|
|
||||||
|
### 11.25 Implemented null standard input for captured actions
|
||||||
|
|
||||||
|
Every process launched through WW's captured asynchronous executor now receives
|
||||||
|
an explicit fd 0. An empty `exec.command.stdinpath`, which is the production
|
||||||
|
default, opens the null device read-only; a nonempty value opens that exact path.
|
||||||
|
Consequently every coordinator-executed directory test product observes
|
||||||
|
immediate EOF instead of inheriting and consuming the invoking terminal, pipe,
|
||||||
|
or file. Captured directory build plans and the compiler, assembler, and linker
|
||||||
|
processes that inherit their stdio receive the same noninteractive boundary.
|
||||||
|
|
||||||
|
#### Pinned Go evidence and pre-fix WW behavior
|
||||||
|
|
||||||
|
The authority is official Go 1.26.5 at commit
|
||||||
|
`c19862e5f8415b4f24b189d065ed739517c548ba`:
|
||||||
|
|
||||||
|
- `runTestActor.Act` constructs an `exec.Cmd`, assigns its package directory,
|
||||||
|
environment, stdout, stderr, cancellation, and wait delay, and invokes
|
||||||
|
`Run` without assigning `Stdin`
|
||||||
|
([`cmd/go/internal/test/test.go`, lines 1661–1697](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1661-L1697)).
|
||||||
|
- `Cmd.Stdin` specifies that a nil value reads from `os.DevNull`;
|
||||||
|
`childStdin` opens that device and retains the file for the child; and
|
||||||
|
`Start` installs it as the first child file before process creation
|
||||||
|
([`os/exec/exec.go`, lines 193–206, 531–538, and 710–738](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec.go#L193-L206)).
|
||||||
|
- The ordinary build-command path has the same default. `Shell.runOut` creates
|
||||||
|
an `exec.Cmd`, assigns output, directory, and environment, and runs it without
|
||||||
|
assigning `Stdin`
|
||||||
|
([`cmd/go/internal/work/shell.go`, lines 600–663](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L600-L663)).
|
||||||
|
- Official `os/exec` tests define a `cat` helper that copies stdin to EOF and
|
||||||
|
require that helper to terminate successfully when run with no `Stdin`
|
||||||
|
assignment
|
||||||
|
([`os/exec/exec_test.go`, lines 201–204 and 416–459](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec_test.go#L416-L459)).
|
||||||
|
The command testdata separately exercises deliberately supplied stdin-pipe
|
||||||
|
lifetime and closure for orphaned test descendants
|
||||||
|
([`cmd/go/testdata/script/test_timeout_stdin.txt`, lines 1–21 and 39–88](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_timeout_stdin.txt#L1-L21));
|
||||||
|
that script is adjacent stream-lifetime evidence, while the default null-fd
|
||||||
|
conclusion comes directly from the implementation chain above.
|
||||||
|
|
||||||
|
Before this slice, `lib/os/exec.start` redirected only stdout and stderr. A
|
||||||
|
directory driver invoked with a nonempty stdin file passed the same open file
|
||||||
|
description through the top-level inherited-stdio handoff, the package
|
||||||
|
coordinator, its captured builder, and the generated product. Serial products
|
||||||
|
could consume caller data; parallel products raced on the shared file offset;
|
||||||
|
a test that waited for input could wait on an interactive caller. Direct
|
||||||
|
measurement with a one-byte pipe made the same directory `@test` fail under
|
||||||
|
both Cstage and WWstage because its first read returned that byte. The raw
|
||||||
|
single-file route also read the byte and failed, but that route intentionally
|
||||||
|
remains inherited-stdio compatibility behavior.
|
||||||
|
|
||||||
|
#### Descriptor ownership, action boundaries, and concurrency
|
||||||
|
|
||||||
|
`exec.start` validates `stdinpath`, selects `/dev/null` for the empty value, and
|
||||||
|
opens the input before creating either output capture. `safefd` moves all three
|
||||||
|
standard streams above fd 2 when a caller had closed a standard descriptor.
|
||||||
|
After fork, the child maps the owned input to fd 0 before mapping the captures
|
||||||
|
to fd 1 and fd 2; setup failures travel through the existing close-on-exec
|
||||||
|
marker. The parent closes its input copy immediately after fork. Every
|
||||||
|
pre-fork error path closes every successfully acquired descriptor.
|
||||||
|
|
||||||
|
The package coordinator does not read or mutate its own fd 0. Each captured
|
||||||
|
build or run child opens an independent null descriptor, so `-j N` products
|
||||||
|
share neither readable caller data nor an input offset. Production, internal,
|
||||||
|
external, recompiled-for-test, support, and generated-main actions still form
|
||||||
|
the same graph and the one directory product still owns one process. Package
|
||||||
|
and test-only dependency initialization observes EOF inside that process.
|
||||||
|
Filters, list mode, no-match execution, failure, and timeout use the same
|
||||||
|
boundary.
|
||||||
|
|
||||||
|
Standard input is request-time process metadata only. It does not enter
|
||||||
|
canonical dotted identity, declared-name binding, actions, units, exports,
|
||||||
|
symbols, archives, generated main, executable bytes, product names, storage
|
||||||
|
keys, or diagnostics. The source path accepted by `stdinpath` is an executor
|
||||||
|
resource, not a package or filesystem-identity input.
|
||||||
|
|
||||||
|
#### Inherited-stdio routes, failure, persistence, and proof
|
||||||
|
|
||||||
|
`exec.runstdio` remains unchanged. The top-level driver therefore preserves
|
||||||
|
inherited stdin for raw single-file tests and runs, and a published test binary
|
||||||
|
invoked directly receives its invoker's fd 0. Directory `ww test -c`, including
|
||||||
|
`-c -o`, starts no product; the compiled binary acquires no embedded stdin
|
||||||
|
policy. No-selected-test packages likewise start no product. Directory build
|
||||||
|
and compile-only plans are captured actions and therefore noninteractive, but
|
||||||
|
their output, cwd, environment, graph, and publication rules are unchanged.
|
||||||
|
|
||||||
|
Failure to open an explicit input path or the default null device is a
|
||||||
|
pre-fork `termination.ERROR` with positive errno. Because input opens first,
|
||||||
|
neither output capture exists. A child-side `dup2` or close failure is reported
|
||||||
|
through the setup marker, distinguished from exit 127, and follows the existing
|
||||||
|
process-group cleanup path. Test failures, timeouts, post-build directory
|
||||||
|
removal, sibling isolation, transaction rollback, and scratch removal retain
|
||||||
|
their prior contracts.
|
||||||
|
|
||||||
|
No test-result cache exists. Caller stdin bytes never affect source actions or
|
||||||
|
persistent artifacts, and changing only the explicit proof input causes no
|
||||||
|
compile or assemble work beyond the established warm final relink. Build
|
||||||
|
workdir format remains `18`, test workdir format remains `19`, and semantic
|
||||||
|
storage remains `3` because no persisted byte schema changed.
|
||||||
|
|
||||||
|
The focused native owner remains
|
||||||
|
`directory_test_execution_working_directory` in
|
||||||
|
`test/package/package_test.ww`. It now drives every relevant command with a
|
||||||
|
known nonempty input file and requires EOF across all directory action/test
|
||||||
|
variants, production and test-only dependency initialization, serial and
|
||||||
|
parallel products, filters/list/no-match, recursive and equivalent roots,
|
||||||
|
failure, timeout, persistent cold/warm/data-only runs, and post-build child
|
||||||
|
setup failure. Tool wrappers require EOF without changing cwd, argv, locale, or
|
||||||
|
`TMPDIR`. Direct published and raw single-file binaries must instead read the
|
||||||
|
supplied data. The observer also proves input-open failure creates no captures,
|
||||||
|
source-class rejection creates no persistent state, Cstage/WWstage diagnostics
|
||||||
|
and output match, compile-only binaries are equal, persisted artifact bytes do
|
||||||
|
not change, and no `.new` residue survives.
|
||||||
|
|
||||||
## 12. Candidate architectures and hard-gate decision
|
## 12. Candidate architectures and hard-gate decision
|
||||||
|
|
||||||
Five candidates were developed as coherent systems, not as feature bins.
|
Five candidates were developed as coherent systems, not as feature bins.
|
||||||
|
|||||||
13
docs/spec.md
13
docs/spec.md
@@ -657,14 +657,23 @@ remaining separate actions. Reachable dependency initialization consequently
|
|||||||
observes the tested product's directory; a dependency tested as its own product
|
observes the tested product's directory; a dependency tested as its own product
|
||||||
observes its own directory.
|
observes its own directory.
|
||||||
|
|
||||||
|
The same coordinator-executed product reads standard input from the null
|
||||||
|
device. Its first read observes EOF regardless of the terminal, pipe, or file
|
||||||
|
connected to the invoking command. Each parallel product owns a separate null
|
||||||
|
descriptor, and production or test-only dependency initialization, filtering,
|
||||||
|
listing, no-match execution, failure, and timeout all retain that boundary.
|
||||||
|
Standard input is runtime process metadata and contributes no package, action,
|
||||||
|
artifact, or persistence identity.
|
||||||
|
|
||||||
The coordinator does not change its own cwd or environment. Parallel products
|
The coordinator does not change its own cwd or environment. Parallel products
|
||||||
receive independent child environments and each uses its own source directory.
|
receive independent child environments and each uses its own source directory.
|
||||||
Relative ordinary files, `testdata`, and writes resolve there for every
|
Relative ordinary files, `testdata`, and writes resolve there for every
|
||||||
executing filter or list path. `ww build`, directory `ww test -c` (including
|
executing filter or list path. `ww build`, directory `ww test -c` (including
|
||||||
`-c -o`), and a no-selected-test directory execute no test child and receive no
|
`-c -o`), and a no-selected-test directory execute no test child and receive no
|
||||||
execution-directory effect. A published test binary invoked directly, and the
|
execution-directory effect. A published test binary invoked directly, and the
|
||||||
raw single-file compatibility route, inherit the user's invocation cwd and
|
raw single-file compatibility route, inherit the user's invocation cwd,
|
||||||
environment; no package directory is embedded or forced by the binary.
|
environment, and standard input; no package directory or input policy is
|
||||||
|
embedded or forced by the binary.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -242,14 +242,22 @@ creates a separate process using the dependency directory. Equivalent direct,
|
|||||||
recursive, redundant, absolute, and root-symlink spellings converge before
|
recursive, redundant, absolute, and root-symlink spellings converge before
|
||||||
this runtime field is assigned.
|
this runtime field is assigned.
|
||||||
|
|
||||||
|
Every such product also receives an independently opened null device as fd 0.
|
||||||
|
Caller terminal, pipe, and file bytes remain with the coordinator; serial and
|
||||||
|
parallel products observe immediate EOF rather than consuming a shared input
|
||||||
|
offset. Production and test-only dependency initialization, filters, list mode,
|
||||||
|
no-match execution, failure, and timeout use that same process boundary.
|
||||||
|
|
||||||
The physical directory remains distinct from exact dotted package identity and
|
The physical directory remains distinct from exact dotted package identity and
|
||||||
from production, internal, external, recompiled, support, and generated-main
|
from production, internal, external, recompiled, support, and generated-main
|
||||||
action identity. Only product execution uses it. Compiler, assembler, archiver,
|
action identity. Only product execution uses it. Compiler, assembler, archiver,
|
||||||
linker, support, and generated-main commands retain their build-plan cwd and
|
linker, support, and generated-main commands retain their build-plan cwd and
|
||||||
environment. `ww build`, `ww test -c`, `-c -o`, and no-selected-test products
|
environment. Captured directory build plans begin with null stdin, which their
|
||||||
start no test child. A published test binary run directly and the raw
|
inherited-stdio tool descendants retain. `ww build`, `ww test -c`, `-c -o`, and
|
||||||
single-file compatibility path inherit the user's cwd/environment and contain
|
no-selected-test products start no test child. A published test binary run
|
||||||
no forced package-directory behavior.
|
directly and the raw single-file compatibility path inherit the user's
|
||||||
|
cwd/environment/stdin and contain no forced package-directory or input
|
||||||
|
behavior.
|
||||||
|
|
||||||
Before package grouping, both directory drivers and the shared recursive
|
Before package grouping, both directory drivers and the shared recursive
|
||||||
coordinator apply Go 1.26.5's filename OS/architecture rule for WW's fixed
|
coordinator apply Go 1.26.5's filename OS/architecture rule for WW's fixed
|
||||||
@@ -319,15 +327,18 @@ independent temporary directories from an unrelated caller cwd and compares
|
|||||||
Cstage/WWstage output for production/internal/external/combined and every
|
Cstage/WWstage output for production/internal/external/combined and every
|
||||||
test-only shape; production and test-only dependency initialization;
|
test-only shape; production and test-only dependency initialization;
|
||||||
recompiled external self-import; duplicate inherited `PWD`; ordinary data,
|
recompiled external self-import; duplicate inherited `PWD`; ordinary data,
|
||||||
`testdata`, and relative writes; direct/recursive/redundant/absolute/symlink
|
`testdata`, relative writes, and deliberately nonempty caller stdin;
|
||||||
roots; reversed request and creation order; serial and parallel products;
|
direct/recursive/redundant/absolute/symlink roots; reversed request and creation
|
||||||
filters, list, and no-match execution; failure and timeout; build/no-test and
|
order; serial and parallel products; filters, list, and no-match execution;
|
||||||
compile-only paths; direct published binaries and raw single-file execution;
|
failure and timeout; build/no-test and compile-only paths; direct published
|
||||||
build-tool cwd/argv/environment; persistent data-only reuse and artifact bytes;
|
binaries and raw single-file execution; build-tool cwd/argv/environment/stdin;
|
||||||
and deterministic post-build child-`chdir` failure isolated from a successful
|
persistent data-only reuse and artifact bytes; input-open failure before capture
|
||||||
sibling. It pads the inherited environment beyond former fixed observer sizes,
|
creation; source-class rejection with empty workdirs; and deterministic
|
||||||
requires one appended product `PWD`, and sweeps the persistent workdir for
|
post-build child-`chdir` failure isolated from a successful sibling. It pads the
|
||||||
staged residue. Command-global bounded-memory failure remains independently
|
inherited environment beyond former fixed observer sizes, requires one appended
|
||||||
|
product `PWD`, requires EOF for captured actions and caller data for inherited-
|
||||||
|
stdio routes, and sweeps the persistent workdir for staged residue.
|
||||||
|
Command-global bounded-memory failure remains independently
|
||||||
owned by `allocation_failure_is_command_global`.
|
owned by `allocation_failure_is_command_global`.
|
||||||
|
|
||||||
The same package owner contains the focused
|
The same package owner contains the focused
|
||||||
@@ -499,12 +510,14 @@ target once within one invocation, but two independent `make bootstrap`
|
|||||||
invocations are not safe to run concurrently and remain mutually exclusive.
|
invocations are not safe to run concurrently and remain mutually exclusive.
|
||||||
|
|
||||||
`lib/os/exec` is the sole reusable WW subprocess mechanism. Fixture and package
|
`lib/os/exec` is the sole reusable WW subprocess mechanism. Fixture and package
|
||||||
coordinators use its captured asynchronous path. The WW driver directly uses
|
coordinators use its captured asynchronous path. An empty captured-command
|
||||||
`os.exec.runstdio` for inherited-stdio, inherited-environment, leader-only
|
`stdinpath` opens the null device; an explicit path supplies controlled input,
|
||||||
compiler, assembler, linker, cleanup, run, and single-file-test calls. The
|
and either descriptor is installed before exec with checked setup reporting.
|
||||||
local WW `procrun` implementation is deleted. The C bootstrap retains its C
|
The WW driver directly uses `os.exec.runstdio` for inherited-stdio,
|
||||||
process implementation because it cannot consume a WW standard-library
|
inherited-environment, leader-only compiler, assembler, linker, cleanup, run,
|
||||||
module.
|
and single-file-test calls. The local WW `procrun` implementation is deleted.
|
||||||
|
The C bootstrap retains its C process implementation because it cannot consume
|
||||||
|
a WW standard-library module.
|
||||||
|
|
||||||
WW has tokens and an opaque type for future CSP/channel work, but no mature
|
WW has tokens and an opaque type for future CSP/channel work, but no mature
|
||||||
production channel operations, task runtime, or scheduler. No channel,
|
production channel operations, task runtime, or scheduler. No channel,
|
||||||
|
|||||||
@@ -174,6 +174,29 @@ fn runcommandenvdir(root: str, name: str, argv: []str, env: []str,
|
|||||||
out.stderr = readfile(c.stderrpath);
|
out.stderr = readfile(c.stderrpath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A direct descriptor mapping keeps the caller's duplicate environment and cwd
|
||||||
|
// intact while giving the nested driver known nonempty input.
|
||||||
|
fn runcommandinputenvdir(root: str, name: str, argv: []str, env: []str,
|
||||||
|
dir: str, input: str, lifetime: time.duration, out: *commandout) void = {
|
||||||
|
let c: exec.command;
|
||||||
|
c.path = argv[0];
|
||||||
|
c.argv = argv;
|
||||||
|
c.env = env;
|
||||||
|
c.dir = dir;
|
||||||
|
c.stdinpath = input;
|
||||||
|
c.stdoutpath = strings.concat(root, "/", name, ".stdout");
|
||||||
|
c.stderrpath = strings.concat(root, "/", name, ".stderr");
|
||||||
|
c.deadline = time.add(time.now(time.clock.monotonic), lifetime);
|
||||||
|
c.grace = (100i64 * (time.millisecond: i64)): time.duration;
|
||||||
|
let r: exec.result;
|
||||||
|
exec.run(&c, &r);
|
||||||
|
assert(r.errno == 0 && r.cleanuperrno == 0);
|
||||||
|
out.termination = r.termination;
|
||||||
|
out.code = r.code;
|
||||||
|
out.stdout = readfile(c.stdoutpath);
|
||||||
|
out.stderr = readfile(c.stderrpath);
|
||||||
|
};
|
||||||
|
|
||||||
fn clean(root: str) void = {
|
fn clean(root: str) void = {
|
||||||
let av: []str = ["/bin/rm", "-rf", "--", root];
|
let av: []str = ["/bin/rm", "-rf", "--", root];
|
||||||
let c: exec.command;
|
let c: exec.command;
|
||||||
@@ -592,19 +615,22 @@ fn cwdtestenv(stage: str) []str = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn cwdassertrecord(text: str, label: str, cwd: str, pwd: str,
|
fn cwdassertrecord(text: str, label: str, cwd: str, pwd: str,
|
||||||
pwdcount: str, pwdlast: str, data: str, testdata: str) void = {
|
pwdcount: str, pwdlast: str, data: str, testdata: str,
|
||||||
|
input: str) void = {
|
||||||
assert(has(text, strings.concat(label, " cwd=", cwd, "\n")));
|
assert(has(text, strings.concat(label, " cwd=", cwd, "\n")));
|
||||||
assert(has(text, strings.concat(label, " PWD=", pwd, "\n")));
|
assert(has(text, strings.concat(label, " PWD=", pwd, "\n")));
|
||||||
assert(has(text, strings.concat(label, " PWD-count=", pwdcount, "\n")));
|
assert(has(text, strings.concat(label, " PWD-count=", pwdcount, "\n")));
|
||||||
assert(has(text, strings.concat(label, " PWD-last=", pwdlast, "\n")));
|
assert(has(text, strings.concat(label, " PWD-last=", pwdlast, "\n")));
|
||||||
assert(has(text, strings.concat(label, " data=", data, "\n")));
|
assert(has(text, strings.concat(label, " data=", data, "\n")));
|
||||||
assert(has(text, strings.concat(label, " testdata=", testdata, "\n")));
|
assert(has(text, strings.concat(label, " testdata=", testdata, "\n")));
|
||||||
|
assert(has(text, strings.concat(label, " stdin=", input, "\n")));
|
||||||
assert(has(text, strings.concat(label, " create=ok\n")));
|
assert(has(text, strings.concat(label, " create=ok\n")));
|
||||||
};
|
};
|
||||||
|
|
||||||
fn cwdassertpackage(text: str, label: str, dir: str, data: str,
|
fn cwdassertpackage(text: str, label: str, dir: str, data: str,
|
||||||
testdata: str) void = {
|
testdata: str) void = {
|
||||||
cwdassertrecord(text, label, dir, dir, "1", "yes", data, testdata);
|
cwdassertrecord(text, label, dir, dir, "1", "yes", data, testdata,
|
||||||
|
"eof");
|
||||||
};
|
};
|
||||||
|
|
||||||
fn cwdwritedata(dir: str, label: str) void = {
|
fn cwdwritedata(dir: str, label: str) void = {
|
||||||
@@ -689,6 +715,35 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
mkdirall(failtree);
|
mkdirall(failtree);
|
||||||
cwdwritedata(caller, "caller");
|
cwdwritedata(caller, "caller");
|
||||||
writefile(strings.concat(caller, "/sentinel"), "parent-sentinel\n");
|
writefile(strings.concat(caller, "/sentinel"), "parent-sentinel\n");
|
||||||
|
let stdinpath: str = strings.concat(root, "/stdin.txt");
|
||||||
|
let stdinbytes: []u8 = alloc([], 4096u64)!;
|
||||||
|
let inputi: i32 = 0;
|
||||||
|
for (inputi < 2048) {
|
||||||
|
append(stdinbytes, 'X');
|
||||||
|
append(stdinbytes, '\n');
|
||||||
|
inputi += 1;
|
||||||
|
};
|
||||||
|
writefile(stdinpath, strings.frombytes(stdinbytes));
|
||||||
|
let missingstdinout: str = strings.concat(root, "/missing-stdin.stdout");
|
||||||
|
let missingstdinerr: str = strings.concat(root, "/missing-stdin.stderr");
|
||||||
|
let missingstdinav: []str = ["/bin/true"];
|
||||||
|
let missingstdincmd: exec.command;
|
||||||
|
missingstdincmd.path = missingstdinav[0];
|
||||||
|
missingstdincmd.argv = missingstdinav;
|
||||||
|
missingstdincmd.env = os.getenvs();
|
||||||
|
missingstdincmd.dir = caller;
|
||||||
|
missingstdincmd.stdinpath = strings.concat(root, "/missing-stdin");
|
||||||
|
missingstdincmd.stdoutpath = missingstdinout;
|
||||||
|
missingstdincmd.stderrpath = missingstdinerr;
|
||||||
|
missingstdincmd.deadline.sec = 0i64;
|
||||||
|
missingstdincmd.deadline.nsec = 0i64;
|
||||||
|
missingstdincmd.grace = 0i64: time.duration;
|
||||||
|
let missingstdinresult: exec.result;
|
||||||
|
exec.run(&missingstdincmd, &missingstdinresult);
|
||||||
|
assert(missingstdinresult.termination == exec.termination.ERROR);
|
||||||
|
assert(missingstdinresult.errno == 2
|
||||||
|
&& missingstdinresult.cleanuperrno == 0);
|
||||||
|
assert(!os.exists(missingstdinout) && !os.exists(missingstdinerr));
|
||||||
|
|
||||||
// Create in reverse lexical order; discovery and product emission may not
|
// Create in reverse lexical order; discovery and product emission may not
|
||||||
// inherit filesystem or request order.
|
// inherit filesystem or request order.
|
||||||
@@ -763,6 +818,7 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
" if (last == env.len - 1) { put(\"yes\\n\"); } else { put(\"no\\n\"); };\n",
|
" if (last == env.len - 1) { put(\"yes\\n\"); } else { put(\"no\\n\"); };\n",
|
||||||
" emitfile(label, \"data\", \"data.txt\");\n",
|
" emitfile(label, \"data\", \"data.txt\");\n",
|
||||||
" emitfile(label, \"testdata\", \"testdata/input.txt\");\n",
|
" emitfile(label, \"testdata\", \"testdata/input.txt\");\n",
|
||||||
|
" let input: [1]u8;\n let inputn: i64 = os.read(os.STDIN_FILENO, &input[0], 1u64);\n put(label); put(\" stdin=\");\n if (inputn == 0i64) { put(\"eof\\n\"); } else {\n if (inputn == 1i64) { put(\"data\\n\"); } else { put(\"<error>\\n\"); };\n };\n",
|
||||||
" let fd: i32 = os.open(\"created.txt\", os.flag.WRONLY |\n",
|
" let fd: i32 = os.open(\"created.txt\", os.flag.WRONLY |\n",
|
||||||
" os.flag.CREATE | os.flag.TRUNC, 384i32);\n",
|
" os.flag.CREATE | os.flag.TRUNC, 384i32);\n",
|
||||||
" put(label); put(\" create=\");\n",
|
" put(label); put(\" create=\");\n",
|
||||||
@@ -824,7 +880,7 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
"fn init() void = { probe.run(\"cmdno-init\"); };\n",
|
"fn init() void = { probe.run(\"cmdno-init\"); };\n",
|
||||||
"fn main() void = { probe.run(\"cmdno-main\"); };\n"));
|
"fn main() void = { probe.run(\"cmdno-main\"); };\n"));
|
||||||
|
|
||||||
let failnames: []str = ["p8", "p7"];
|
let failnames: []str = ["reject", "p8", "p7"];
|
||||||
i = 0;
|
i = 0;
|
||||||
for (i < failnames.len) {
|
for (i < failnames.len) {
|
||||||
let dir: str = strings.concat(failtree, "/", failnames[i]);
|
let dir: str = strings.concat(failtree, "/", failnames[i]);
|
||||||
@@ -834,6 +890,7 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
};
|
};
|
||||||
let p7: str = strings.concat(failtree, "/p7");
|
let p7: str = strings.concat(failtree, "/p7");
|
||||||
let p8: str = strings.concat(failtree, "/p8");
|
let p8: str = strings.concat(failtree, "/p8");
|
||||||
|
let reject: str = strings.concat(failtree, "/reject");
|
||||||
writefile(strings.concat(p7, "/p7_test.ww"), strings.concat(
|
writefile(strings.concat(p7, "/p7_test.ww"), strings.concat(
|
||||||
"package p7;\nimport probe;\n@test fn fails() void = {\n",
|
"package p7;\nimport probe;\n@test fn fails() void = {\n",
|
||||||
" probe.run(\"p7-fail\"); assert(false);\n};\n"));
|
" probe.run(\"p7-fail\"); assert(false);\n};\n"));
|
||||||
@@ -842,6 +899,10 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
" probe.run(\"p8-timeout\");\n",
|
" probe.run(\"p8-timeout\");\n",
|
||||||
" time.sleep((2i64 * (time.second: i64)): time.duration, ",
|
" time.sleep((2i64 * (time.second: i64)): time.duration, ",
|
||||||
"time.clock.monotonic);\n};\n"));
|
"time.clock.monotonic);\n};\n"));
|
||||||
|
writefile(strings.concat(reject, "/reject.ww"),
|
||||||
|
"package reject;\nexport fn value() i32 = { return 1; };\n");
|
||||||
|
writefile(strings.concat(reject, "/bad_test.ww"),
|
||||||
|
"package unrelated;\n@test fn unreachable() void = { assert(false); };\n");
|
||||||
|
|
||||||
let out: commandout;
|
let out: commandout;
|
||||||
let lnav: []str = ["/bin/ln", "-s", tree, treelink];
|
let lnav: []str = ["/bin/ln", "-s", tree, treelink];
|
||||||
@@ -868,9 +929,11 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
p6, p5, p4, p3, p2, p1, testdep, dep];
|
p6, p5, p4, p3, p2, p1, testdep, dep];
|
||||||
let outc: commandout;
|
let outc: commandout;
|
||||||
let outw: commandout;
|
let outw: commandout;
|
||||||
runcommandenvdir(root, "cwd-multi-c", forward, cenv, caller,
|
runcommandinputenvdir(root, "cwd-multi-c", forward, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &outc);
|
(120i64 * (time.second: i64)): time.duration, &outc);
|
||||||
runcommandenvdir(root, "cwd-multi-ww", reverse, wenv, caller,
|
runcommandinputenvdir(root, "cwd-multi-ww", reverse, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &outw);
|
(120i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outc, 0);
|
expectexit(&outc, 0);
|
||||||
expectexit(&outw, 0);
|
expectexit(&outw, 0);
|
||||||
@@ -901,7 +964,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
// selected test body runs.
|
// selected test body runs.
|
||||||
let filterav: []str = [driver("ww"), "test", "-run", "cwd_external",
|
let filterav: []str = [driver("ww"), "test", "-run", "cwd_external",
|
||||||
"-I", tree, p3];
|
"-I", tree, p3];
|
||||||
runcommandenvdir(root, "cwd-filter", filterav, cenv, caller,
|
runcommandinputenvdir(root, "cwd-filter", filterav, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &out);
|
(60i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
cwdassertpackage(out.stdout, "dep-init", p3, "p3-data", "p3-testdata");
|
cwdassertpackage(out.stdout, "dep-init", p3, "p3-data", "p3-testdata");
|
||||||
@@ -912,7 +976,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(!has(out.stdout, "p3-internal cwd="));
|
assert(!has(out.stdout, "p3-internal cwd="));
|
||||||
|
|
||||||
let listav: []str = [driver("ww_ww"), "test", "-list", "-I", tree, p3];
|
let listav: []str = [driver("ww_ww"), "test", "-list", "-I", tree, p3];
|
||||||
runcommandenvdir(root, "cwd-list", listav, wenv, caller,
|
runcommandinputenvdir(root, "cwd-list", listav, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &out);
|
(60i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
cwdassertpackage(out.stdout, "dep-init", p3, "p3-data", "p3-testdata");
|
cwdassertpackage(out.stdout, "dep-init", p3, "p3-data", "p3-testdata");
|
||||||
@@ -925,7 +990,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
|
|
||||||
let nomatchav: []str = [driver("ww"), "test", "-run", "no-such-test",
|
let nomatchav: []str = [driver("ww"), "test", "-run", "no-such-test",
|
||||||
"-I", tree, p3];
|
"-I", tree, p3];
|
||||||
runcommandenvdir(root, "cwd-no-match", nomatchav, cenv, caller,
|
runcommandinputenvdir(root, "cwd-no-match", nomatchav, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &out);
|
(60i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
cwdassertpackage(out.stdout, "dep-init", p3, "p3-data", "p3-testdata");
|
cwdassertpackage(out.stdout, "dep-init", p3, "p3-data", "p3-testdata");
|
||||||
@@ -939,9 +1005,11 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
p7];
|
p7];
|
||||||
let failw: []str = [driver("ww_ww"), "test", "-I", tree, "-I",
|
let failw: []str = [driver("ww_ww"), "test", "-I", tree, "-I",
|
||||||
failtree, p7];
|
failtree, p7];
|
||||||
runcommandenvdir(root, "cwd-fail-c", failc, cenv, caller,
|
runcommandinputenvdir(root, "cwd-fail-c", failc, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outc);
|
(60i64 * (time.second: i64)): time.duration, &outc);
|
||||||
runcommandenvdir(root, "cwd-fail-ww", failw, wenv, caller,
|
runcommandinputenvdir(root, "cwd-fail-ww", failw, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outw);
|
(60i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outc, 1);
|
expectexit(&outc, 1);
|
||||||
expectexit(&outw, 1);
|
expectexit(&outw, 1);
|
||||||
@@ -955,9 +1023,11 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
tree, "-I", failtree, p8];
|
tree, "-I", failtree, p8];
|
||||||
let timeoutw: []str = [driver("ww_ww"), "test", "-timeout-ms=50", "-I",
|
let timeoutw: []str = [driver("ww_ww"), "test", "-timeout-ms=50", "-I",
|
||||||
tree, "-I", failtree, p8];
|
tree, "-I", failtree, p8];
|
||||||
runcommandenvdir(root, "cwd-timeout-c", timeoutc, cenv, caller,
|
runcommandinputenvdir(root, "cwd-timeout-c", timeoutc, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outc);
|
(60i64 * (time.second: i64)): time.duration, &outc);
|
||||||
runcommandenvdir(root, "cwd-timeout-ww", timeoutw, wenv, caller,
|
runcommandinputenvdir(root, "cwd-timeout-ww", timeoutw, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outw);
|
(60i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outc, 1);
|
expectexit(&outc, 1);
|
||||||
expectexit(&outw, 1);
|
expectexit(&outw, 1);
|
||||||
@@ -969,11 +1039,35 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(same(outc.stderr, strings.concat("FAIL ", p8,
|
assert(same(outc.stderr, strings.concat("FAIL ", p8,
|
||||||
" [p8] (test exit 1)\n")));
|
" [p8] (test exit 1)\n")));
|
||||||
|
|
||||||
|
// Source-class rejection precedes every captured build or test child, so a
|
||||||
|
// nonempty caller input cannot create a partial persistent generation.
|
||||||
|
let rejectcwork: str = strings.concat(root, "/stdin-reject-c");
|
||||||
|
let rejectwwork: str = strings.concat(root, "/stdin-reject-ww");
|
||||||
|
assert(os.mkdir(rejectcwork, 448i32) == 0);
|
||||||
|
assert(os.mkdir(rejectwwork, 448i32) == 0);
|
||||||
|
let rejectcav: []str = [driver("ww"), "test", "-w", rejectcwork,
|
||||||
|
"-I", failtree, reject];
|
||||||
|
let rejectwav: []str = [driver("ww_ww"), "test", "-w", rejectwwork,
|
||||||
|
"-I", failtree, reject];
|
||||||
|
runcommandinputenvdir(root, "stdin-reject-c", rejectcav, cenv, caller,
|
||||||
|
stdinpath, (60i64 * (time.second: i64)): time.duration, &outc);
|
||||||
|
runcommandinputenvdir(root, "stdin-reject-ww", rejectwav, wenv, caller,
|
||||||
|
stdinpath, (60i64 * (time.second: i64)): time.duration, &outw);
|
||||||
|
expectexit(&outc, 1);
|
||||||
|
expectexit(&outw, 1);
|
||||||
|
assert(outc.stdout.len == 0 && outw.stdout.len == 0);
|
||||||
|
assert(same(outc.stderr, outw.stderr));
|
||||||
|
assert(has(outc.stderr,
|
||||||
|
"test package must match production package or <package>_test\n"));
|
||||||
|
assert(directoryisempty(rejectcwork));
|
||||||
|
assert(directoryisempty(rejectwwork));
|
||||||
|
|
||||||
// Packages without selected test sources and `ww build` never start a test
|
// Packages without selected test sources and `ww build` never start a test
|
||||||
// process, even if production initialization would make that visible.
|
// process, even if production initialization would make that visible.
|
||||||
let notestav: []str = [driver("ww_ww"), "test", "-I", tree,
|
let notestav: []str = [driver("ww_ww"), "test", "-I", tree,
|
||||||
plain, cmdno];
|
plain, cmdno];
|
||||||
runcommandenvdir(root, "cwd-no-tests", notestav, wenv, caller,
|
runcommandinputenvdir(root, "cwd-no-tests", notestav, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &out);
|
(60i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
assert(!has(out.stdout, "plain-init"));
|
assert(!has(out.stdout, "plain-init"));
|
||||||
@@ -984,7 +1078,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
let commandbin: str = strings.concat(root, "/cmdno.bin");
|
let commandbin: str = strings.concat(root, "/cmdno.bin");
|
||||||
let buildav: []str = [driver("ww"), "build", "-I", tree, "-o",
|
let buildav: []str = [driver("ww"), "build", "-I", tree, "-o",
|
||||||
commandbin, cmdno];
|
commandbin, cmdno];
|
||||||
runcommandenvdir(root, "cwd-build", buildav, cenv, caller,
|
runcommandinputenvdir(root, "cwd-build", buildav, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &out);
|
(60i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
assert(os.exists(commandbin));
|
assert(os.exists(commandbin));
|
||||||
@@ -995,7 +1090,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
// wrapper: direct invocation keeps the caller's cwd and duplicate PWDs.
|
// wrapper: direct invocation keeps the caller's cwd and duplicate PWDs.
|
||||||
assert(os.remove(strings.concat(p2, "/created.txt")) == 0);
|
assert(os.remove(strings.concat(p2, "/created.txt")) == 0);
|
||||||
let defaultcompile: []str = [driver("ww"), "test", "-c", "-I", tree, p2];
|
let defaultcompile: []str = [driver("ww"), "test", "-c", "-I", tree, p2];
|
||||||
runcommandenvdir(root, "cwd-compile-default", defaultcompile, cenv, caller,
|
runcommandinputenvdir(root, "cwd-compile-default", defaultcompile, cenv,
|
||||||
|
caller, stdinpath,
|
||||||
(90i64 * (time.second: i64)): time.duration, &out);
|
(90i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
let defaultbin: str = strings.concat(p2, "/p2.test");
|
let defaultbin: str = strings.concat(p2, "/p2.test");
|
||||||
@@ -1012,9 +1108,11 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
"-I", tree, p1];
|
"-I", tree, p1];
|
||||||
let compilew: []str = [driver("ww_ww"), "test", "-c", "-o", p1wbin,
|
let compilew: []str = [driver("ww_ww"), "test", "-c", "-o", p1wbin,
|
||||||
"-I", tree, p1];
|
"-I", tree, p1];
|
||||||
runcommandenvdir(root, "cwd-compile-c", compilec, cenv, caller,
|
runcommandinputenvdir(root, "cwd-compile-c", compilec, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(90i64 * (time.second: i64)): time.duration, &outc);
|
(90i64 * (time.second: i64)): time.duration, &outc);
|
||||||
runcommandenvdir(root, "cwd-compile-ww", compilew, wenv, caller,
|
runcommandinputenvdir(root, "cwd-compile-ww", compilew, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(90i64 * (time.second: i64)): time.duration, &outw);
|
(90i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outc, 0);
|
expectexit(&outc, 0);
|
||||||
expectexit(&outw, 0);
|
expectexit(&outw, 0);
|
||||||
@@ -1023,15 +1121,16 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(!has(outc.stdout, "dep-init") && !has(outw.stdout, "dep-init"));
|
assert(!has(outc.stdout, "dep-init") && !has(outw.stdout, "dep-init"));
|
||||||
|
|
||||||
let directbin: []str = [p1cbin, "-package=p1"];
|
let directbin: []str = [p1cbin, "-package=p1"];
|
||||||
runcommandenvdir(root, "cwd-published-direct", directbin, cenv, caller,
|
runcommandinputenvdir(root, "cwd-published-direct", directbin, cenv,
|
||||||
|
caller, stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &out);
|
(60i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
cwdassertrecord(out.stdout, "dep-init", caller,
|
cwdassertrecord(out.stdout, "dep-init", caller,
|
||||||
"/ww-cwd-inherited-first", "2", "no", "caller-data",
|
"/ww-cwd-inherited-first", "2", "no", "caller-data",
|
||||||
"caller-testdata");
|
"caller-testdata", "data");
|
||||||
cwdassertrecord(out.stdout, "p1-internal", caller,
|
cwdassertrecord(out.stdout, "p1-internal", caller,
|
||||||
"/ww-cwd-inherited-first", "2", "no", "caller-data",
|
"/ww-cwd-inherited-first", "2", "no", "caller-data",
|
||||||
"caller-testdata");
|
"caller-testdata", "data");
|
||||||
assert(os.exists(strings.concat(caller, "/created.txt")));
|
assert(os.exists(strings.concat(caller, "/created.txt")));
|
||||||
assert(os.remove(strings.concat(caller, "/created.txt")) == 0);
|
assert(os.remove(strings.concat(caller, "/created.txt")) == 0);
|
||||||
|
|
||||||
@@ -1041,10 +1140,12 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
strings.concat(p4, "/internal_test.ww")];
|
strings.concat(p4, "/internal_test.ww")];
|
||||||
let raww: []str = [driver("ww_ww"), "test", "-I", tree,
|
let raww: []str = [driver("ww_ww"), "test", "-I", tree,
|
||||||
strings.concat(p4, "/internal_test.ww")];
|
strings.concat(p4, "/internal_test.ww")];
|
||||||
runcommandenvdir(root, "cwd-raw-c", rawc, cbase, caller,
|
runcommandinputenvdir(root, "cwd-raw-c", rawc, cbase, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outc);
|
(60i64 * (time.second: i64)): time.duration, &outc);
|
||||||
assert(os.remove(strings.concat(caller, "/created.txt")) == 0);
|
assert(os.remove(strings.concat(caller, "/created.txt")) == 0);
|
||||||
runcommandenvdir(root, "cwd-raw-ww", raww, wenv, caller,
|
runcommandinputenvdir(root, "cwd-raw-ww", raww, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outw);
|
(60i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outc, 0);
|
expectexit(&outc, 0);
|
||||||
expectexit(&outw, 0);
|
expectexit(&outw, 0);
|
||||||
@@ -1052,7 +1153,7 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(same(outc.stderr, outw.stderr));
|
assert(same(outc.stderr, outw.stderr));
|
||||||
cwdassertrecord(outc.stdout, "p4-internal-only", caller,
|
cwdassertrecord(outc.stdout, "p4-internal-only", caller,
|
||||||
"/ww-cwd-inherited-first", "2", "yes", "caller-data",
|
"/ww-cwd-inherited-first", "2", "yes", "caller-data",
|
||||||
"caller-testdata");
|
"caller-testdata", "data");
|
||||||
assert(os.remove(strings.concat(caller, "/created.txt")) == 0);
|
assert(os.remove(strings.concat(caller, "/created.txt")) == 0);
|
||||||
cwdassertpackage(multiout, "dep-init", p2, "p2-data", "p2-testdata");
|
cwdassertpackage(multiout, "dep-init", p2, "p2-data", "p2-testdata");
|
||||||
cwdassertpackage(multiout, "p2-external", p2,
|
cwdassertpackage(multiout, "p2-external", p2,
|
||||||
@@ -1076,9 +1177,11 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
strings.concat(tree, "/...")];
|
strings.concat(tree, "/...")];
|
||||||
let linkrec: []str = [driver("ww_ww"), "test", "-j", "4", "-I",
|
let linkrec: []str = [driver("ww_ww"), "test", "-j", "4", "-I",
|
||||||
"../tree-link", "../tree-link/..."];
|
"../tree-link", "../tree-link/..."];
|
||||||
runcommandenvdir(root, "cwd-recursive-real", realrec, cenv, caller,
|
runcommandinputenvdir(root, "cwd-recursive-real", realrec, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &outc);
|
(120i64 * (time.second: i64)): time.duration, &outc);
|
||||||
runcommandenvdir(root, "cwd-recursive-link", linkrec, wenv, caller,
|
runcommandinputenvdir(root, "cwd-recursive-link", linkrec, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &outw);
|
(120i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outc, 0);
|
expectexit(&outc, 0);
|
||||||
expectexit(&outw, 0);
|
expectexit(&outw, 0);
|
||||||
@@ -1096,9 +1199,11 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
let equivalent: []str = [driver("ww_ww"), "test", "-j", "3", "-I",
|
let equivalent: []str = [driver("ww_ww"), "test", "-j", "3", "-I",
|
||||||
"../tree-link", "../tree/p1", p1, "../tree/./p1/../p1",
|
"../tree-link", "../tree/p1", p1, "../tree/./p1/../p1",
|
||||||
"../tree-link/p1"];
|
"../tree-link/p1"];
|
||||||
runcommandenvdir(root, "cwd-direct", direct, cenv, caller,
|
runcommandinputenvdir(root, "cwd-direct", direct, cenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outc);
|
(60i64 * (time.second: i64)): time.duration, &outc);
|
||||||
runcommandenvdir(root, "cwd-equivalent", equivalent, wenv, caller,
|
runcommandinputenvdir(root, "cwd-equivalent", equivalent, wenv, caller,
|
||||||
|
stdinpath,
|
||||||
(60i64 * (time.second: i64)): time.duration, &outw);
|
(60i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outc, 0);
|
expectexit(&outc, 0);
|
||||||
expectexit(&outw, 0);
|
expectexit(&outw, 0);
|
||||||
@@ -1124,6 +1229,9 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
"/bin/pwd >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"/bin/pwd >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
"printf 'compiler env=LC_ALL:%s TMPDIR:%s\\n' \"$LC_ALL\" ",
|
"printf 'compiler env=LC_ALL:%s TMPDIR:%s\\n' \"$LC_ALL\" ",
|
||||||
"\"$TMPDIR\" >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"\"$TMPDIR\" >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
|
"if IFS= read -r WW_CWD_STDIN; then\n",
|
||||||
|
" printf 'compiler stdin=data\\n' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
|
"else printf 'compiler stdin=eof\\n' >> \"$WW_CWD_TOOL_TRACE\"; fi\n",
|
||||||
"printf 'compiler argv' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"printf 'compiler argv' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
"for arg in \"$@\"; do printf ' <%s>' \"$arg\" >> ",
|
"for arg in \"$@\"; do printf ' <%s>' \"$arg\" >> ",
|
||||||
"\"$WW_CWD_TOOL_TRACE\"; done\n",
|
"\"$WW_CWD_TOOL_TRACE\"; done\n",
|
||||||
@@ -1135,6 +1243,9 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
"/bin/pwd >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"/bin/pwd >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
"printf 'assembler env=LC_ALL:%s TMPDIR:%s\\n' \"$LC_ALL\" ",
|
"printf 'assembler env=LC_ALL:%s TMPDIR:%s\\n' \"$LC_ALL\" ",
|
||||||
"\"$TMPDIR\" >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"\"$TMPDIR\" >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
|
"if IFS= read -r WW_CWD_STDIN; then\n",
|
||||||
|
" printf 'assembler stdin=data\\n' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
|
"else printf 'assembler stdin=eof\\n' >> \"$WW_CWD_TOOL_TRACE\"; fi\n",
|
||||||
"printf 'assembler argv' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"printf 'assembler argv' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
"for arg in \"$@\"; do printf ' <%s>' \"$arg\" >> ",
|
"for arg in \"$@\"; do printf ' <%s>' \"$arg\" >> ",
|
||||||
"\"$WW_CWD_TOOL_TRACE\"; done\n",
|
"\"$WW_CWD_TOOL_TRACE\"; done\n",
|
||||||
@@ -1146,6 +1257,9 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
"/bin/pwd >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"/bin/pwd >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
"printf 'linker env=LC_ALL:%s TMPDIR:%s\\n' \"$LC_ALL\" ",
|
"printf 'linker env=LC_ALL:%s TMPDIR:%s\\n' \"$LC_ALL\" ",
|
||||||
"\"$TMPDIR\" >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"\"$TMPDIR\" >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
|
"if IFS= read -r WW_CWD_STDIN; then\n",
|
||||||
|
" printf 'linker stdin=data\\n' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
|
"else printf 'linker stdin=eof\\n' >> \"$WW_CWD_TOOL_TRACE\"; fi\n",
|
||||||
"printf 'linker argv' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
"printf 'linker argv' >> \"$WW_CWD_TOOL_TRACE\"\n",
|
||||||
"for arg in \"$@\"; do printf ' <%s>' \"$arg\" >> ",
|
"for arg in \"$@\"; do printf ' <%s>' \"$arg\" >> ",
|
||||||
"\"$WW_CWD_TOOL_TRACE\"; done\n",
|
"\"$WW_CWD_TOOL_TRACE\"; done\n",
|
||||||
@@ -1174,7 +1288,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(os.mkdir(work, 448i32) == 0);
|
assert(os.mkdir(work, 448i32) == 0);
|
||||||
let persistav: []str = [driver("ww"), "test", "-w", work, "-I", tree,
|
let persistav: []str = [driver("ww"), "test", "-w", work, "-I", tree,
|
||||||
p1];
|
p1];
|
||||||
runcommandenvdir(root, "cwd-persist-cold", persistav, traceenv, caller,
|
runcommandinputenvdir(root, "cwd-persist-cold", persistav, traceenv,
|
||||||
|
caller, stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &outc);
|
(120i64 * (time.second: i64)): time.duration, &outc);
|
||||||
expectexit(&outc, 0);
|
expectexit(&outc, 0);
|
||||||
cwdassertpackage(outc.stdout, "dep-init", p1, "p1-data", "p1-testdata");
|
cwdassertpackage(outc.stdout, "dep-init", p1, "p1-data", "p1-testdata");
|
||||||
@@ -1188,6 +1303,10 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(has(coldtrace, "compiler env=LC_ALL:C TMPDIR:/tmp/"));
|
assert(has(coldtrace, "compiler env=LC_ALL:C TMPDIR:/tmp/"));
|
||||||
assert(has(coldtrace, "assembler env=LC_ALL:C TMPDIR:/tmp/"));
|
assert(has(coldtrace, "assembler env=LC_ALL:C TMPDIR:/tmp/"));
|
||||||
assert(has(coldtrace, "linker env=LC_ALL:C TMPDIR:/tmp/"));
|
assert(has(coldtrace, "linker env=LC_ALL:C TMPDIR:/tmp/"));
|
||||||
|
assert(has(coldtrace, "compiler stdin=eof\n"));
|
||||||
|
assert(has(coldtrace, "assembler stdin=eof\n"));
|
||||||
|
assert(has(coldtrace, "linker stdin=eof\n"));
|
||||||
|
assert(!has(coldtrace, "stdin=data\n"));
|
||||||
assert(has(coldtrace, "compiler argv <"));
|
assert(has(coldtrace, "compiler argv <"));
|
||||||
assert(has(coldtrace, ".unit.new>"));
|
assert(has(coldtrace, ".unit.new>"));
|
||||||
assert(has(coldtrace, "assembler argv <"));
|
assert(has(coldtrace, "assembler argv <"));
|
||||||
@@ -1221,7 +1340,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
rewritefile(tooltrace, "");
|
rewritefile(tooltrace, "");
|
||||||
runcommandenvdir(root, "cwd-persist-warm", persistav, traceenv, caller,
|
runcommandinputenvdir(root, "cwd-persist-warm", persistav, traceenv,
|
||||||
|
caller, stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &outw);
|
(120i64 * (time.second: i64)): time.duration, &outw);
|
||||||
expectexit(&outw, 0);
|
expectexit(&outw, 0);
|
||||||
assert(same(outc.stdout, outw.stdout));
|
assert(same(outc.stdout, outw.stdout));
|
||||||
@@ -1230,6 +1350,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(!has(warmtrace, "assembler cwd="));
|
assert(!has(warmtrace, "assembler cwd="));
|
||||||
assert(occurrences(warmtrace, "linker cwd=") == 1);
|
assert(occurrences(warmtrace, "linker cwd=") == 1);
|
||||||
assert(has(warmtrace, strings.concat("linker cwd=", caller, "\n")));
|
assert(has(warmtrace, strings.concat("linker cwd=", caller, "\n")));
|
||||||
|
assert(has(warmtrace, "linker stdin=eof\n"));
|
||||||
|
assert(!has(warmtrace, "stdin=data\n"));
|
||||||
|
|
||||||
// Non-source data does not enter graph/action/storage bytes. The established
|
// Non-source data does not enter graph/action/storage bytes. The established
|
||||||
// warm final relink remains one invocation, while the next uncached runtime
|
// warm final relink remains one invocation, while the next uncached runtime
|
||||||
@@ -1237,8 +1359,17 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
rewritefile(strings.concat(p1, "/data.txt"), "p1-data-v2\n");
|
rewritefile(strings.concat(p1, "/data.txt"), "p1-data-v2\n");
|
||||||
rewritefile(strings.concat(p1, "/testdata/input.txt"),
|
rewritefile(strings.concat(p1, "/testdata/input.txt"),
|
||||||
"p1-testdata-v2\n");
|
"p1-testdata-v2\n");
|
||||||
|
let changedstdin: []u8 = alloc([], 4096u64)!;
|
||||||
|
inputi = 0;
|
||||||
|
for (inputi < 2048) {
|
||||||
|
append(changedstdin, 'Y');
|
||||||
|
append(changedstdin, '\n');
|
||||||
|
inputi += 1;
|
||||||
|
};
|
||||||
|
rewritefile(stdinpath, strings.frombytes(changedstdin));
|
||||||
rewritefile(tooltrace, "");
|
rewritefile(tooltrace, "");
|
||||||
runcommandenvdir(root, "cwd-persist-data", persistav, traceenv, caller,
|
runcommandinputenvdir(root, "cwd-persist-data", persistav, traceenv,
|
||||||
|
caller, stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &out);
|
(120i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
cwdassertpackage(out.stdout, "dep-init", p1,
|
cwdassertpackage(out.stdout, "dep-init", p1,
|
||||||
@@ -1250,6 +1381,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
assert(!has(datatrace, "assembler cwd="));
|
assert(!has(datatrace, "assembler cwd="));
|
||||||
assert(occurrences(datatrace, "linker cwd=") == 1);
|
assert(occurrences(datatrace, "linker cwd=") == 1);
|
||||||
assert(has(datatrace, strings.concat("linker cwd=", caller, "\n")));
|
assert(has(datatrace, strings.concat("linker cwd=", caller, "\n")));
|
||||||
|
assert(has(datatrace, "linker stdin=eof\n"));
|
||||||
|
assert(!has(datatrace, "stdin=data\n"));
|
||||||
i = 0;
|
i = 0;
|
||||||
for (i < artifactpaths.len) {
|
for (i < artifactpaths.len) {
|
||||||
assert(same(artifacts[i], readfile(artifactpaths[i])));
|
assert(same(artifacts[i], readfile(artifactpaths[i])));
|
||||||
@@ -1263,7 +1396,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
let p1after: str = strings.concat(root, "/p1-after-data.test");
|
let p1after: str = strings.concat(root, "/p1-after-data.test");
|
||||||
let afterav: []str = [driver("ww_ww"), "test", "-c", "-o", p1after,
|
let afterav: []str = [driver("ww_ww"), "test", "-c", "-o", p1after,
|
||||||
"-I", tree, p1];
|
"-I", tree, p1];
|
||||||
runcommandenvdir(root, "cwd-after-data-binary", afterav, wenv, caller,
|
runcommandinputenvdir(root, "cwd-after-data-binary", afterav, wenv,
|
||||||
|
caller, stdinpath,
|
||||||
(90i64 * (time.second: i64)): time.duration, &out);
|
(90i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 0);
|
expectexit(&out, 0);
|
||||||
assert(same(readfile(p1cbin), readfile(p1after)));
|
assert(same(readfile(p1cbin), readfile(p1after)));
|
||||||
@@ -1295,8 +1429,8 @@ fn cwdwritedata(dir: str, label: str) void = {
|
|||||||
append(hideenv, strings.concat("WW_CWD_HIDE_DIR=", p1));
|
append(hideenv, strings.concat("WW_CWD_HIDE_DIR=", p1));
|
||||||
let hideav: []str = [driver("wwtest"), "package", "--ww-driver",
|
let hideav: []str = [driver("wwtest"), "package", "--ww-driver",
|
||||||
hidewrapper, "-j", "2", "-I", tree, p1, p2];
|
hidewrapper, "-j", "2", "-I", tree, p1, p2];
|
||||||
runcommandenvdir(root, strings.concat("cwd-hide-", hidestages[i]),
|
runcommandinputenvdir(root, strings.concat("cwd-hide-", hidestages[i]),
|
||||||
hideav, hideenv, caller,
|
hideav, hideenv, caller, stdinpath,
|
||||||
(120i64 * (time.second: i64)): time.duration, &out);
|
(120i64 * (time.second: i64)): time.duration, &out);
|
||||||
expectexit(&out, 1);
|
expectexit(&out, 1);
|
||||||
assert(has(out.stderr, strings.concat("wrapper-hidden=", p1, "\n")));
|
assert(has(out.stderr, strings.concat("wrapper-hidden=", p1, "\n")));
|
||||||
|
|||||||
Reference in New Issue
Block a user