Skip to content

tests: compare against the newline the tools write, and stop piping through a shell - #215

Merged
JalonSolov merged 1 commit into
vlang:mainfrom
metif12:fix/test-newlines-and-stdin
Oct 5, 2026
Merged

JalonSolov merged 1 commit into
vlang:mainfrom
metif12:fix/test-newlines-and-stdin

Conversation

@metif12

@metif12 metif12 commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

tests: compare against the newline the tools write, and stop piping through a shell

Six of the seven test files that reach for common's eol were comparing against the
wrong byte, and three of them could not feed standard input at all. None of that is
a defect in the utilities; it is the test suite disagreeing with itself on Windows,
which is why v test . has been reporting content differences of exactly one byte
per line.

The newline

GNU writes a bare LF to stdout and stderr on every platform, Windows included.
Measured here, each of these ends its output with byte 10 and not with 13,10:

cksum, wc, sum, head, mkdir -v

while common's eol() is "\r\n" on this platform. So the six files now say so:

cksum_test.v    sum_test.v    wc_test.v
head_test.v     mkdir_test.v  shuf_test.v

One definition each, thirty-nine expectations fixed. expand_test.v defined an eol
it never used, so that one is gone.

Standard input

cksum: exit 255       the shell answering, not cksum
wc:   exit 255
sum:  exit 255

These three pipe through the shell:

res := os.execute('cat ${file} | ${executable_under_test}')

which is a command line and not a pipe on Windows, where there is no cat. Routing
it through cmd /c type does not work either, because os.exec quotes each argument
and cmd then reads a quoted pipe as part of a filename:

The filename, directory name, or volume label syntax is incorrect.

So the eleven tests that need standard input return early on Windows and print why
once, and the ones that pass a file name still run there. Feeding a pipe portably
from a test needs os.new_process with pipes, which is a piece of work of its own.

sum did not compile either

sum_test.v:16: const `util` conflicts with imported module `util`

The file imported io.util and declared const util = 'sum', so sum's suite had not
been running either. The import is io.util as vutil now and the one call that used
it says so.

Tests

cksum, head, mkdir, sum and wc are all green against uutils 0.0.17 on Windows, which
they were not before. shuf still fails, on test_random_source, and that one is left
alone: matching GNU's RNG is work already in flight on another branch, and
duplicating it here would be the wrong way to resolve that. v fmt -verify src
passes.

@JalonSolov

Copy link
Copy Markdown
Contributor

Conflicts.

metif12 added a commit to metif12/coreutils that referenced this pull request Oct 5, 2026
`make test` is `v -Wimpure-v -W test .`, and on current V it could not compile 31 of
the 49 test files:

	common/testing/testrig.v:211: error: function `execute` has been deprecated;
	    use os.exec with an argument array; command strings can allow shell injection

-W turns a deprecation into an error, so every test file that went through the
harness, and every file that called os.execute itself, was failing to build rather
than running. That is what the three Linux workflows do, and what this unblocks.

os.exec takes an argument array, so a command line has to be split somewhere. Every
command in this repository is written as a string by the tests, so this adds the one
place that does it:

	split_args.v   whitespace between words, single and double quotes, and
	               nothing else

Not a shell, on purpose. A backslash is an ordinary character everywhere in it,
because on this platform a backslash is nearly always part of a path and a shell's
rule of eating it would take the volume off `C:\Users\me\file.txt`. The shapes it
does have to handle are the ones the tests actually write, and each is pinned by a
test taken from a real call site:

	--output-delimiter="|"                  comm_test.v
	sh -c "exit 42"                        timeout_test.v
	tr -d '\r'                             sum_test.v
	C:\Users\me\coreutils\test.txt          the reason it is not a shell

An unterminated quote is not an error: the rest of the line becomes one word, so a
test that made the mistake fails on what the program said rather than on a parse in
this file.

124 call sites, 22 files. `v -Wimpure-v -W test .` on Windows:

	before   31 files could not be built at all
	after    2

and the suite goes from 25 files failing to 17, with those 17 being real test
failures rather than build failures. The two that still do not build are fixed
elsewhere: tail's string_to_i64_test.v is vlang#207 and sum's is vlang#215.

Nothing that a test asserts. The commands are the same strings, the arguments are the
same arguments, and no test was reworded; the difference is only that the split is
done in V rather than by a shell. Twenty files under src/ and the three under
common/testing/ and no other.
…hrough a shell

Six of the seven test files that reach for common's eol were comparing against the
wrong byte, and three of them could not feed standard input at all. None of that is
a defect in the utilities; it is the test suite disagreeing with itself on Windows,
which is why `v test .` has been reporting content differences of exactly one byte
per line.

GNU writes a bare LF to stdout and stderr on every platform, Windows included.
Measured here, each of these ends its output with byte 10 and not with 13,10:

	cksum, wc, sum, head, mkdir -v

while common's eol() is "\r\n" on this platform. So the six files now say so:

	cksum_test.v    sum_test.v    wc_test.v
	head_test.v     mkdir_test.v  shuf_test.v

One definition each, thirty-nine expectations fixed. expand_test.v defined an eol
it never used, so that one is gone.

	cksum: exit 255       the shell answering, not cksum
	wc:   exit 255
	sum:  exit 255

These three pipe through the shell:

	res := os.execute('cat ${file} | ${executable_under_test}')

which is a command line and not a pipe on Windows, where there is no cat. Routing
it through `cmd /c type` does not work either, because os.exec quotes each argument
and cmd then reads a quoted pipe as part of a filename:

	The filename, directory name, or volume label syntax is incorrect.

So the eleven tests that need standard input return early on Windows and print why
once, and the ones that pass a file name still run there. Feeding a pipe portably
from a test needs os.new_process with pipes, which is a piece of work of its own.

	sum_test.v:16: const `util` conflicts with imported module `util`

The file imported io.util and declared `const util = 'sum'`, so sum's suite had not
been running either. The import is `io.util as vutil` now and the one call that used
it says so.

cksum, head, mkdir, sum and wc are all green against uutils 0.0.17 on Windows, which
they were not before. shuf still fails, on `test_random_source`, and that one is left
alone: matching GNU's RNG is work already in flight on another branch, and
duplicating it here would be the wrong way to resolve that. `v fmt -verify src`
passes.
@metif12
metif12 force-pushed the fix/test-newlines-and-stdin branch from 62e96ed to b28ba86 Compare October 5, 2026 18:22
@JalonSolov
JalonSolov merged commit a6f27e5 into vlang:main Oct 5, 2026
JalonSolov pushed a commit that referenced this pull request Oct 6, 2026
…t V (#218)

`make test` is `v -Wimpure-v -W test .`, and on current V it could not compile 31 of
the 49 test files:

	common/testing/testrig.v:211: error: function `execute` has been deprecated;
	    use os.exec with an argument array; command strings can allow shell injection

-W turns a deprecation into an error, so every test file that went through the
harness, and every file that called os.execute itself, was failing to build rather
than running. That is what the three Linux workflows do, and what this unblocks.

os.exec takes an argument array, so a command line has to be split somewhere. Every
command in this repository is written as a string by the tests, so this adds the one
place that does it:

	split_args.v   whitespace between words, single and double quotes, and
	               nothing else

Not a shell, on purpose. A backslash is an ordinary character everywhere in it,
because on this platform a backslash is nearly always part of a path and a shell's
rule of eating it would take the volume off `C:\Users\me\file.txt`. The shapes it
does have to handle are the ones the tests actually write, and each is pinned by a
test taken from a real call site:

	--output-delimiter="|"                  comm_test.v
	sh -c "exit 42"                        timeout_test.v
	tr -d '\r'                             sum_test.v
	C:\Users\me\coreutils\test.txt          the reason it is not a shell

An unterminated quote is not an error: the rest of the line becomes one word, so a
test that made the mistake fails on what the program said rather than on a parse in
this file.

124 call sites, 22 files. `v -Wimpure-v -W test .` on Windows:

	before   31 files could not be built at all
	after    2

and the suite goes from 25 files failing to 17, with those 17 being real test
failures rather than build failures. The two that still do not build are fixed
elsewhere: tail's string_to_i64_test.v is #207 and sum's is #215.

Nothing that a test asserts. The commands are the same strings, the arguments are the
same arguments, and no test was reworded; the difference is only that the split is
done in V rather than by a shell. Twenty files under src/ and the three under
common/testing/ and no other.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants