Repository navigation
df: round the total row once, from the summed bytes - #14522
TanbirRamim wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved moderate findings remain in total formatting and regression-test assertions.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Updates df --total to sum raw bytes before rounding, matching GNU behavior and avoiding large-block-size overflow.
Changes:
- Accumulates raw byte totals and rounds once at output.
- Adds regression coverage for rounding and human-readable large block sizes.
- Updates integration expectations for per-row rounding differences.
File summaries
| File | Summary |
|---|---|
tests/by-util/test_df.rs |
Updates total assertions and adds regression coverage; exact-value, deterministic-filesystem, and versioned GNU-reference adjustments remain requested. |
src/uu/df/src/table.rs |
Aggregates raw bytes and formats totals; explicit -B with -h still needs GNU-compatible precedence and output handling. |
Review details
Suppressed comments (3)
src/uu/df/src/table.rs:270
- When
-his combined with an explicit-B, this branch still formats the raw total as human-readable and ignores the requested block size. For the linked issue's reproducer GNU prints1block, while this remains an E-suffixed byte value; the new integration test only checks that it does not panic. Make the-B/-hprecedence consistent with GNU and assert the resulting output.
let s = if let Some(h) = self.options.human_readable {
to_magnitude_and_suffix(bytes.into(), SuffixType::HumanReadable(h), true)
} else {
let BlockSize::Bytes(d) = self.options.block_size;
bytes.div_ceil(d).to_string()
tests/by-util/test_df.rs:502
- The regression test says the total should be one block, but
<= 1also accepts zero, so a broken or missing total accumulator could still pass. Assert the exact expected value.
assert!(total <= 1, "total row reports {total} blocks");
tests/by-util/test_df.rs:490
- This command sums every mounted filesystem, so a fixed 10-exabyte block size does not guarantee a one-block total: on a host whose included filesystems exceed 10 EB, correct output is 2 or more and this test fails. Restrict the command to a known filesystem (for example, append
.) and assert the expected result, or use only the deterministic table fixture for this regression.
"--block-size=10000000000000000000",
])
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🟡 Changes recommended
A critical total-formatting issue and a regression-test coverage gap remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
tests/by-util/test_df.rs:496
- This test only invokes
dffor., so it normally has one filesystem row. The removedBytesCellimplementation would also print1for both that row and the total, meaning this assertion does not exercise rounding across rows. Use a deterministic multi-filesystem fixture (or make the command-level test assert a real multi-row case) so the regression can fail again.
let values: Vec<&str> = output.lines().skip(1).map(str::trim).collect();
assert_eq!(values, vec!["1", "1"]);
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
|
GNU testsuite comparison: |
Merging this PR will not alter performance1 warning, 1 note
Comparing Footnotes
|
There was a problem hiding this comment.
Is it the expected behavior that the tests pass if I don't have applied your changes to table.rs?
There was a problem hiding this comment.
No, thanks for checking. With only . there was a single row, so rounding once and summing rounded rows gave the same result. The tests now pass . .: without the table.rs changes test_total_rounds_up_once gets a total of 2 instead of 1 and test_total_human_readable_with_large_block_size panics with the multiply overflow.
|
friendly bump, happy to change anything if needed |
The total row added up the block counts of the rows, each of which is already rounded up to the block size, instead of rounding the summed bytes once the way GNU df does. With a block size larger than the filesystems, every non-empty row is one block, so the total became a count of filesystems, and the human-readable output then multiplied that count back by the block size and overflowed. Keep the raw byte counts in the rows, sum those for the total row, and round at output time like every other row. Fixes uutils#14459
Run them on the filesystem of the current directory only, so the one row and the total are both exactly one block, and name the GNU version the rounding was compared against.
b7a9c31 to
fd10a16
Compare
There was a problem hiding this comment.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Copilot review overview
2 open issues
Review effort: Lite


df --totalsummed the block counts of the rows, each already rounded up to the block size, instead of rounding the summed bytes once like GNU df does. With-B 100Gon my machine GNU reports a total of 19 blocks where the rows add up to 24; we printed 24. With a block size larger than every filesystem the total degenerates into a count of filesystems, and-hthen multiplied that count back by the block size and overflowed (attempt to multiply with overflow, exit 134).This goes back to keeping the raw byte counts in the rows and rounding at output time. #10438 had moved away from that so the total would match the sum of the displayed rows, but GNU does not do that either, so
test_totalnow allows for the rounding difference.Fixes #14459