Skip to content

Improve GNU sed testsuite compatibility - #345

Open
kevinburkesegment wants to merge 1 commit into
uutils:mainfrom
kevinburkesegment:test-compatibility
Open

kevinburkesegment wants to merge 1 commit into
uutils:mainfrom
kevinburkesegment:test-compatibility

Conversation

@kevinburkesegment

Copy link
Copy Markdown
Contributor
  • Fix l command default width from 60 to 70 (matching GNU sed)
  • Wire -l flag and COLS env var to l command width
  • Reject l<N> (GNU extension) in --posix mode
  • Accept } and # as valid command terminators (fixes command-endings)
  • Accept } and # as valid substitute flag terminators
  • Eat spaces before command endings (e.g. y/1/a/ ;d)
  • Scope #n silent mode to first script source only (fixes comment-n)
  • Drop backslash for unknown escape sequences in s/// replacement (GNU behavior)
  • Match GNU sed error message format: -e expression #N, char C: for string scripts, file:line: for file scripts
  • Add get_source_index() to ScriptLineProvider
  • Add test-results.txt to .gitignore

GNU testsuite results: 7 → 9 passing (command-endings, comment-n now pass).

@github-actions

Copy link
Copy Markdown

GNU sed testsuite comparison:

Test results comparison:
  Current:   TOTAL: 65 / PASSED: 9 / FAILED: 46 / SKIPPED: 10
  Reference: TOTAL: 65 / PASSED: 7 / FAILED: 48 / SKIPPED: 10

Changes from main branch:
  TOTAL: +0
  PASSED: +2
  FAILED: -2

Test improvements (2):
  + command-endings
  + comment-n

@github-actions

Copy link
Copy Markdown

GNU sed testsuite comparison:

Test results comparison:
  Current:   TOTAL: 65 / PASSED: 9 / FAILED: 46 / SKIPPED: 10
  Reference: TOTAL: 65 / PASSED: 7 / FAILED: 48 / SKIPPED: 10

Changes from main branch:
  TOTAL: +0
  PASSED: +2
  FAILED: -2

Test improvements (2):
  + command-endings
  + comment-n

@codecov

codecov Bot commented Mar 19, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.18644% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.92%. Comparing base (7fade42) to head (e73ac32).

Files with missing lines Patch % Lines
src/sed/compiler.rs 65.62% 11 Missing ⚠️
src/sed/error_handling.rs 66.66% 5 Missing ⚠️
src/sed/script_line_provider.rs 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #345      +/-   ##
==========================================
- Coverage   82.16%   81.92%   -0.25%     
==========================================
  Files          13       13              
  Lines        5444     5454      +10     
  Branches      304      312       +8     
==========================================
- Hits         4473     4468       -5     
- Misses        969      984      +15     
  Partials        2        2              
Flag Coverage Δ
macos_latest 82.36% <71.18%> (-0.25%) ⬇️
ubuntu_latest 82.47% <71.18%> (-0.25%) ⬇️
windows_latest 0.00% <0.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sylvestre

Copy link
Copy Markdown
Contributor

Sorry but only one commit implementating all the changes isn't the best practice. In a perfect world, one pr changes or at least one commit per fix in this pr

@sylvestre

Copy link
Copy Markdown
Contributor

For example, it makes it hard to know what is cover by an existing test or not

@sylvestre
sylvestre force-pushed the test-compatibility branch from e391df1 to e73ac32 Compare April 2, 2026 16:22
@github-actions

github-actions Bot commented Apr 2, 2026

Copy link
Copy Markdown

GNU sed testsuite comparison:

Test results comparison:
  Current:   TOTAL: 65 / PASSED: 9 / FAILED: 46 / SKIPPED: 10
  Reference: TOTAL: 65 / PASSED: 7 / FAILED: 48 / SKIPPED: 10

Changes from main branch:
  TOTAL: +0
  PASSED: +2
  FAILED: -2

Test improvements (2):
  + command-endings
  + comment-n

@codspeed

codspeed Bot commented Apr 2, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ 1 benchmark spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 11 untouched benchmarks


Comparing kevinburkesegment:test-compatibility (470fafb) with main (58608af)

Open in CodSpeed

@sylvestre

Copy link
Copy Markdown
Contributor

@kevinburkesegment could you please rebase it? thanks

@sylvestre

Copy link
Copy Markdown
Contributor

are you still interested in this one? if not, i will close it, thanks

Comment thread src/sed/compiler.rs
) -> UResult<()> {
if !line.eol() && line.current() == ';' {
line.advance();
line.eat_spaces();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add tests for } / # right after a command, spaces before ;, and #n in a second -e

Comment thread src/sed/compiler.rs
/// GNU sed checks COLS env var first, then terminal width, then defaults to 70.
/// COLS values <= 0 or non-numeric are ignored.
fn output_width() -> usize {
if let Ok(cols) = std::env::var("COLS")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this COLS handling come from? i can't find it in the GNU manual.
please make sure it isn't derived from the GNU source

Comment thread src/sed/compiler.rs
literal.push(decoded);
} else {
literal.push('\\');
// Unknown escape: drop the backslash (GNU behavior)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a test for this in tests/by-util/test_sed.rs

Comment thread src/sed/compiler.rs
match parse_number(lines, line, false)? {
Some(n) => {
// 'l<N>' is a GNU extension, reject in POSIX mode
if cmd.code == 'l' && context.posix {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a test for --posix with l5

Comment thread src/sed/error_handling.rs Outdated
Err(USimpleError::new(
1,
let input_name = lines.get_input_name();
let message = if input_name.starts_with("-e expression") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matching on starts_with("-e expression") 3 times is fragile and duplicated.
could ScriptLocation store the kind of source instead?

Comment thread src/sed/mod.rs
length: matches.get_one::<u32>("length").map_or(70, |v| *v as usize),
// 0 means "not explicitly set via -l"; the l command then
// falls back to COLS, terminal width, or DEFAULT_OUTPUT_WIDTH.
length: matches.get_one::<u32>("length").map_or(0, |v| *v as usize),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with this, -l 0 falls back to the terminal width, but in GNU it means never wrap.
please add a test

Comment thread tests/by-util/test_sed.rs Outdated
.fails()
.code_is(1)
.stderr_is("sed: :0:3: error: incomplete command\n");
.stderr_is("sed: :0: incomplete command\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sed: :0: incomplete command looks broken (empty name, line 0), could you please fix it rather than update the expectation?

Comment thread tests/by-util/test_sed.rs
.fails()
.code_is(2)
.stderr_is("sed: <script argument 1>:2:3: 'input/lines1':1 error: no previous regular expression\n");
.stderr_is("sed: -e expression #1, char 3: 'input/lines1':1 error: no previous regular expression\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we lose the line info here. GNU counts char N from the start of the whole expression, not from the start of the line, no?

- Fix `l` command default width from 60 to 70 (matching GNU sed)
- Wire `-l` flag and COLS env var to `l` command width
- Reject `l<N>` (GNU extension) in --posix mode
- Accept `}` and `#` as valid command terminators (fixes command-endings)
- Accept `}` and `#` as valid substitute flag terminators
- Eat spaces before command endings (e.g. `y/1/a/ ;d`)
- Scope `#n` silent mode to first script source only (fixes comment-n)
- Drop backslash for unknown escape sequences in s/// replacement (GNU behavior)
- Match GNU sed error message format: `-e expression #N, char C:` for
  string scripts, `file:line:` for file scripts
- Add `get_source_index()` to ScriptLineProvider
- Add test-results.txt to .gitignore

GNU testsuite results: 7 → 9 passing (command-endings, comment-n now pass).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 15, 2026 16:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Diagnostic mismatches, a stale test, and width and source-numbering errors remain unresolved.

5 open findings
What changed in this PR

Improves GNU sed compatibility in script parsing, list-output widths, and diagnostic expectations.

Changes:

  • Adjusts command terminators, replacement escapes, and first-source #n handling.
  • Connects list width to -l and COLS, with a default of 70.
  • Renames expression sources and updates diagnostic documentation and assertions.
File Description
tests/​by-util/​test_sed.rs Updates diagnostic expectations.
src/​sed/​script_line_provider.rs Exposes source indices and renames expression sources.
src/​sed/​mod.rs Changes default list-width configuration.
src/​sed/​error_handling.rs Documents intended GNU diagnostic formats.
src/​sed/​compiler.rs Adjusts parsing, escapes, silent mode, and list widths.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/sed/compiler.rs
Comment on lines +797 to 799
// Unknown escape: drop the backslash (GNU behavior)
literal.push(line.current_byte());
line.advance();
Comment thread src/sed/error_handling.rs
Comment on lines +173 to +174
/// Format matches GNU sed: `-e expression #N, char C: message` for string
/// scripts, `file:line: message` for file scripts.
Comment thread src/sed/compiler.rs
Comment on lines +1248 to +1249
// Subtract 1 to avoid line wraps on terminals
return n - 1;
Comment thread src/sed/mod.rs
length: matches.get_one::<u32>("length").map_or(70, |v| *v as usize),
// 0 means "not explicitly set via -l"; the l command then
// falls back to COLS, terminal width, or DEFAULT_OUTPUT_WIDTH.
length: matches.get_one::<u32>("length").map_or(0, |v| *v as usize),
index: next_index,
reader: Box::new(BufReader::new(cursor)),
input_name: format!("<script argument {}>", next_index + 1),
input_name: format!("-e expression #{}", next_index + 1),
@github-actions

Copy link
Copy Markdown

GNU sed testsuite comparison:

Test results comparison:
  Current:   TOTAL: 65 / PASSED: 22 / FAILED: 35 / SKIPPED: 8
  Reference: TOTAL: 65 / PASSED: 18 / FAILED: 39 / SKIPPED: 8

Changes from main branch:
  TOTAL: +0
  PASSED: +4
  FAILED: -4

Test improvements (4):
  + 8to7
  + command-endings
  + comment-n
  + subst-options

@sylvestre

Copy link
Copy Markdown
Contributor

a bunch of jobs are failing

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.

3 participants