Skip to content

Peel namespace-request tests, plus the -sys naming docs and a UTF-16 path-length fix - #74

Merged
MikeGrier merged 6 commits into
mainfrom
mikegrier/namespace-request-tests
Sep 7, 2026
Merged

MikeGrier merged 6 commits into
mainfrom
mikegrier/namespace-request-tests

Conversation

@MikeGrier

@MikeGrier MikeGrier commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Started as a peel of 104 test cases off mikegrier/deferred-namespace-ops (#56). Review then turned up two things that could not honestly be left out, so the scope is wider than the title suggests and the description below is written to the actual changed files rather than the original intent.

No source behaviour changes. Everything here is tests or documentation, typed test / docs, so release-please cuts no version for any crate.

What is in this PR

1. The peel -- 104 test cases for windows-namespace-request-sys

module lines
path 134 the largest gap -- path handling is where a namespace crate is most exposed to odd input
open_by_id 78 identifier-based opens
open 66
volume 50
watch 48
security 40

Verified portable before the branch was cut, not after: the patch was applied to a scratch worktree checked out at origin/main with no other branch content, and the suite passed there. It carries no cross-references, so it cannot leave a dangling link on the source branch -- which three earlier peels each did.

2. Documentation: what the -sys suffix means (root README + crate README)

Prompted by a direct question -- should this crate be -sys at all, given it wraps unsafe rather than declaring FFI? -- which turned out to be unanswerable from anything a reader can reach.

By the usual ecosystem meaning the doubt is well founded: this crate takes its declarations from windows-sys and exposes 112 safe pub fn against 4 unsafe ones. By this workspace's meaning it is a textbook fit, because here the suffix marks a layer -- makes an existing Win32 API memory-safe without adding policy -- and this crate refuses policy explicitly. The convention existed only as a subordinate clause inside a decision about a different crate, so it is now stated in the root README (the record) with a short pointer from the crate README.

Also corrects a stale line: the crate README claimed "Not yet released to crates.io" while it has been published since 2026-08-29 (checked against the crates.io API).

3. Path lengths measured in the unit Win32 uses (windows-namespace-request-sys and windows-file-enumeration-sys)

absolute_path_of_length documented itself as producing UTF-16 units, computed the suffix from UTF-8 bytes, and had its result checked in scalars -- three units in one helper. They coincide for ASCII, so it passed while measuring the wrong thing.

The helper is duplicated verbatim into windows-file-enumeration-sys, doc comment included. Fixing one copy would leave two versions disagreeing about what they measure, so both are corrected. That is why this PR touches a second crate.

Adds a test that separates the units, and a guard against an underflowing length in both copies.

Why the scope grew, stated plainly

An earlier version of this description said "Tests only" and "nothing outside the crate touched". That was true when written and false by the time the review caught it -- the reviewer was right to flag it, and it is the same defect as overclaiming a sweep. The scope grew twice, each time for a reason recorded above, and this description is now written from git diff --name-only origin/main...HEAD rather than from memory.

Verification

286 tests pass in windows-namespace-request-sys, 377 in windows-file-enumeration-sys. Workspace clippy --all-targets --all-features clean, cargo fmt clean, encoding check clean, check-commit-scope confirms no release-triggering commit.

Peeled from mikegrier/deferred-namespace-ops, where these were written
alongside work that is not ready. They stand on their own: no source change
comes with them, and nothing outside the crate is touched.

Coverage by module:

  path        134 lines  -- the largest gap. Path handling is where a
                            namespace crate is most exposed to odd input
  open_by_id   78 lines  -- identifier-based opens
  open         66 lines
  volume       50 lines
  watch        48 lines
  security     40 lines

The only non-additive lines are two `use` statements widened to import
`SecurityAttributes` and `VolumeInformation` for the new cases.

Typed `test` rather than `feat` or `fix` deliberately: no behavior changes, and
release-please must not cut a version for a test-only commit.

Verified against this branch rather than assumed portable: the patch was first
applied to a scratch worktree checked out at origin/main with no other branch
content present, and the suite passed there before the branch was cut. It also
carries no cross-references -- no links to DESIGN-NOTES, checklists, or design
sessions -- so it cannot leave a dangling reference behind on the source branch,
which three earlier peels each did.

285 tests pass (217 unit, 68 across the two integration targets), clippy
--all-targets --all-features clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 6, 2026 23:28

Copilot AI left a comment

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.

🟢 Approval recommended

The changes are isolated to tests, are internally consistent, and add concrete coverage for previously-surviving mutation scenarios without altering production behavior.

Pull request overview

Adds a set of new, mutation-sweep-driven test cases in windows-namespace-request-sys to harden accessor/default wiring and boundary behavior across the six request families, without changing production code.

Changes:

  • Add targeted tests that verify accessor methods report their configured fields (and defaults) rather than returning constants.
  • Add path-boundary tests around the ordinary MAX_PATH content limit and a few additional contract edge cases.
  • Widen a couple of use imports to support the new test cases (VolumeInformation, SecurityAttributes, Wtf16String).
File summaries
File Description
crates/windows-namespace-request-sys/src/watch/tests.rs Adds tests asserting WatchDirectory subtree/filter accessors reflect both configured and default values.
crates/windows-namespace-request-sys/src/volume/tests.rs Adds an accessor-wiring test for VolumeInformation using constructed, distinct field values.
crates/windows-namespace-request-sys/src/security/tests.rs Adds a test that cross-checks raw_os_error() against the standard source() chain on capture failure.
crates/windows-namespace-request-sys/src/path/tests.rs Adds boundary/contract tests for ordinary path length limits, drive-designator rejection, and distinct failure descriptions.
crates/windows-namespace-request-sys/src/open/tests.rs Adds tests asserting configured parameters read back through accessors and that defaults remain “unset” (zero/None).
crates/windows-namespace-request-sys/src/open_by_id/tests.rs Adds accessor/default tests for the open-by-id request, including supplied SecurityAttributes visibility.
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 0
  • Review effort level: Lite

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

Prompted by a direct question -- should `windows-namespace-request-sys` be
`-sys` at all, given it wraps unsafe rather than declaring FFI? -- which turned
out to be unanswerable from anything a reader can reach.

By the usual ecosystem meaning the doubt is well founded: a `-sys` crate is
normally raw FFI declarations, and this one takes its declarations from
`windows-sys` and exposes 112 safe `pub fn` against 4 unsafe ones. By this
workspace's meaning it is a textbook fit, because here the suffix marks a
*layer* -- makes an existing Win32 API memory-safe without adding policy -- and
this crate refuses policy explicitly: it schedules nothing, chooses no delivery
model, and reports raw Win32 outcomes without normalising them.

The two readings disagree, and nothing published said which applies. The
convention existed only as a subordinate clause inside a decision about a
*different* crate (why `windows-waitable-queues` is not `-sys`), and that
decision is not on main at all -- see below. So:

- The root README gains a `Crate naming` section, and is the statement of
  record. The convention governs published crate names, so it belongs where a
  reader meets the crates.
- The crate README gains a short section answering the question for the one
  crate whose name provokes it, pointing at the root README. Kept deliberately
  brief so there is one statement and one pointer rather than two statements
  that can drift apart.

Also corrects a stale line in the crate README: it said "Not yet released to
crates.io" while the crate has been published since 2026-08-29 (0.2.0, verified
against the crates.io API rather than assumed).

Found while doing this, and NOT fixed here because it needs its own change:
`crates/windows-waitable-queues/DESIGN-NOTES.md` links to
`../../DESIGN-NOTES.md#the-waitable-queues-crate-is-named-plural-and-carries-no-sys-suffix`,
and that section does not exist on main. The decision is 88 lines and lives only
on mikegrier/deferred-namespace-ops, so the crate shipped with a dangling link
to reasoning that never landed. Peeling it needs its own verification pass --
six cross-references, one of which (CHECKLIST-io-domains.md) is also branch-only
-- so this commit deliberately does not cite that anchor rather than adding a
seventh reference to a missing referent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 6, 2026 23:55

Copilot AI left a comment

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.

🟡 Changes recommended

Minor but concrete documentation/test-correctness issues were found (relative link robustness and UTF-16 unit accounting in a path-length helper).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

crates/windows-namespace-request-sys/src/path/tests.rs:277

  • absolute_path_of_length is documented as producing a path of N UTF-16 units, but it computes the suffix length using prefix.len() (UTF-8 bytes) and the tests verify length via chars().count() (Unicode scalar values). This happens to work for ASCII, but it makes the helper/doc misleading and risks future edits accidentally testing the wrong unit; use encode_utf16().count() for both the prefix and the assertions so the test matches the stated contract.
  • Files reviewed: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread crates/windows-namespace-request-sys/README.md Outdated
`absolute_path_of_length` documents itself as producing "exactly `units` UTF-16
units" and then computed the suffix from `prefix.len()` (UTF-8 bytes) while its
callers checked the result with `chars().count()` (scalars). Three units in one
helper. They coincide for the ASCII it builds, so it passed -- and would have
gone on passing while measuring the wrong thing the moment a case used a
character that is not one byte, one scalar, and one UTF-16 unit at once.

UTF-16 is the unit that matters here: `MAX_PATH` is a count of `WCHAR`, and the
implementation is already correct -- `units.len()` on a `Wtf16Str` is a UTF-16
count. Only the tests were loose.

Corrected in both crates that carry the helper. It is duplicated verbatim,
including the doc comment that misdescribed it, and the test file's own header
notes the two crates carry near-identical path contracts. Fixing one copy would
have left the workspace with two versions of the same helper disagreeing about
what it measures, which is worse than the original defect.

  windows-namespace-request-sys  helper, both length assertions, and the
                                 `> 260` fixture checks in final_path and
                                 full_path, which compared a WCHAR limit against
                                 a scalar count and said "chars" in the message
  windows-file-enumeration-sys   the duplicated helper and its two assertions

Adds a test that separates the units, since a fix nothing can fail is not worth
much: a path of `C:\` plus 128 astral characters is 259 UTF-16 units but only
131 `char`s, so an implementation counting scalars would admit the 260-unit
version -- the expensive direction, since the caller is told the open may
proceed.

What that test pins is stated carefully, because sabotage showed the obvious
claim was wrong. Disabling the pre-check alone leaves it passing:
`GetFullPathNameW` reports the resolved length in UTF-16 units and a second
guard refuses on that, so the contract survives a scalar-counting pre-check. It
takes disabling both to make the test fail. So it is named for the contract it
covers rather than for arithmetic at any one site, and the comment records that
the post-check is the stronger of the two -- its count comes from Windows and
therefore cannot be in the wrong unit -- which is worth knowing before anyone
removes the pre-check as redundant.

286 tests pass in windows-namespace-request-sys, 377 in
windows-file-enumeration-sys, workspace clippy --all-targets --all-features
clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 7, 2026 00:07
@MikeGrier

Copy link
Copy Markdown
Owner Author

The UTF-16 unit accounting (suppressed comment on path/tests.rs:277)

Right, and worse than stated: the helper used three different units in one function. Documented as UTF-16 units, computed the suffix from prefix.len() (UTF-8 bytes), and its callers asserted with chars().count() (scalars). All three are 3 for C:\, so it passed and would have kept passing while measuring the wrong thing.

UTF-16 is the unit that matters -- MAX_PATH is a count of WCHAR -- and the implementation was already correct: units.len() on a Wtf16Str is a UTF-16 count. Only the tests were loose.

Swept the class rather than the site

The helper is duplicated verbatim into windows-file-enumeration-sys, doc comment and all, and this test file's own header says the two crates carry near-identical path contracts. Fixing one copy would have left two versions of the same helper disagreeing about what they measure -- worse than the original defect -- so both are corrected. That makes this PR span two crates; both changes are test-only and typed test, so no release is triggered.

Also corrected two same-crate siblings the sweep turned up: final_path and full_path asserted resolved.chars().count() > 260 against a WCHAR limit, and reported it as "chars" in the failure message.

The new test, and a correction to what I first claimed about it

A fix nothing can fail is not worth much, so I added a case that separates the units: C:\ plus 128 astral characters is 259 UTF-16 units but only 131 chars, so a scalar-counting implementation would admit the 260-unit version -- the expensive direction, since the caller is told the open may proceed.

I then sabotaged the implementation to check the test was load-bearing, and it was not, in the way I had assumed. Disabling the pre-check alone leaves the test passing: GetFullPathNameW reports the resolved length in UTF-16 units and a second guard refuses on that. It takes disabling both to make the test fail.

So I renamed it from the_ordinary_limit_counts_utf16_units_and_not_characters -- which claimed to pin one site's arithmetic -- to a_path_whose_character_count_hides_its_utf16_length_is_still_refused, which is the contract it actually covers. The comment records the two-guard finding, including that the post-check is the stronger one (its count comes from Windows, so it cannot be in the wrong unit) -- worth knowing before someone removes the pre-check as redundant.

Had I not run the sabotage I would have shipped a test whose name asserted something it does not establish.

286 tests pass in windows-namespace-request-sys, 377 in windows-file-enumeration-sys, workspace clippy --all-targets --all-features clean.

Copilot AI left a comment

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.

🔵 Needs a closer look

The PR’s scope/description claims (“tests only” / “nothing outside the crate touched”) don’t match the actual changed files, so the PR metadata or split needs to be corrected.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

README.md:34

  • The PR description says "Tests only" / "nothing outside the crate touched", but this change set also updates the workspace root README (crate naming guidance) and touches crates/windows-file-enumeration-sys/src/path/tests.rs. Please either (a) update the PR description/scope statements (and implied test:-only framing) to match what is actually changing, or (b) split the non-namespace-request changes into a separate PR.
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

"Astral plane" is real jargon -- it is what the early Perl/Unicode community
called Unicode's supplementary planes -- but it is obscure enough to cost a
reader, which is the opposite of what a test about precise unit counting should
do. Raised by a reviewer with decades of Unicode work who had not met the term.

The test now says what it means: a character above `U+FFFF` is one `char` but
two UTF-16 units, because UTF-16 encodes it as a surrogate pair. That is the
whole property the test depends on, and stating it plainly is shorter than the
jargon plus the explanation the jargon needs. `supplementary` is the Unicode
standard's own word and is used for the binding.

Scope: this corrects only the site added by this branch. The term is also used
in 19 places that predate it -- `wtf-string` (test names, and matrix case keys
such as `astral_min` / `astral_max`), and one comment in `windows-file-watcher`
-- and those are left alone here rather than folded into a test-coverage PR.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 7, 2026 00:46

Copilot AI left a comment

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.

🔵 Needs a closer look

The PR’s stated scope in the description (“tests only”, “nothing outside the crate touched”) does not match the actual changed files, and the new path-length helper should avoid underflow panics with a clear guard.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

README.md:54

  • The PR description says "Tests only" and "nothing outside the crate touched", but this PR also changes workspace documentation (root README + crate README) and updates tests in a different crate (crates/windows-file-enumeration-sys). Please either update the PR title/description to match the actual scope, or split the non-namespace-request changes into separate PRs so the peel stays as advertised.
    crates/windows-file-enumeration-sys/src/path/tests.rs:195
  • absolute_path_of_length will panic if called with units shorter than the C:\ prefix (the subtraction underflows). Adding an explicit assertion makes the helper safer and produces a clearer failure if a future test accidentally passes a too-small value.
    crates/windows-namespace-request-sys/src/path/tests.rs:267
  • absolute_path_of_length will panic if called with units shorter than the C:\ prefix (the subtraction underflows). It’s only a test helper, but adding an explicit assertion makes failures clearer and prevents accidental misuse in future cases.
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

`units - prefix_units` underflows for any `units` below 3, so a future case
asking for a 2-unit path would get "attempt to subtract with overflow" from a
line that does not mention paths or prefixes. The helper now checks first and
says which two numbers disagree.

Hoists `prefix.encode_utf16().count()` into `prefix_units` so the guard and the
subtraction cannot drift apart -- the failure this replaces is only reachable if
they do.

Applied to both copies of the helper, in windows-namespace-request-sys and
windows-file-enumeration-sys, for the same reason the previous commit corrected
both: leaving one guarded and one not is how two copies of the same code start
to differ.

Verified by execution rather than by reading: a temporary
`#[should_panic(expected = "the C:\\ prefix is already 3 units")]` case calling
`absolute_path_of_length(2)` passed, confirming the guard fires and that the
message names the prefix and its width. Removed again -- a helper's guard is not
worth a permanent test, but is worth having actually run once.

286 tests pass in windows-namespace-request-sys, 377 in
windows-file-enumeration-sys, workspace clippy --all-targets --all-features
clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 7, 2026 01:14
@MikeGrier MikeGrier changed the title Add 104 namespace-request test cases across the six request families Peel namespace-request tests, plus the -sys naming docs and a UTF-16 path-length fix Sep 7, 2026
@MikeGrier

Copy link
Copy Markdown
Owner Author

All three addressed in 2bcc932 plus a rewritten description.

Scope claim -- you are right, and it is the same defect twice

The description said "Tests only" and "nothing outside the crate touched". That was true when written and false by the time you read it: the scope grew twice, and each time I appended a new section rather than fixing the claim at the top. That is exactly the overclaiming I was pulled up for on #69, in a different shape -- a stale assertion left standing above accurate detail.

I chose to widen the description rather than split, and the reason is in the finding itself: the second crate is there because absolute_path_of_length is duplicated verbatim into windows-file-enumeration-sys, doc comment and all. Splitting it would ship one guarded, unit-correct copy and one unguarded copy still measuring bytes -- two versions of the same helper disagreeing about what it measures, which is worse than either the original defect or the wider PR.

The title and description are rewritten from git diff --name-only origin/main...HEAD rather than from memory, and the description now says up front that the scope is wider than the title, why it grew, and that the earlier claim was wrong.

The underflow guard, in both copies

units - prefix_units underflows below 3, and the panic would have been "attempt to subtract with overflow" from a line that mentions neither paths nor prefixes. Now:

let prefix_units = prefix.encode_utf16().count();
assert!(
    units >= prefix_units,
    "asked for a {units}-unit path, but the {prefix} prefix is already \
     {prefix_units} units; the subtraction below would underflow and panic \
     without saying why"
);

I hoisted prefix.encode_utf16().count() into prefix_units so the guard and the subtraction cannot drift apart -- the failure the guard replaces is only reachable if they do.

Verified by execution, not by reading. A temporary #[should_panic(expected = "the C:\\ prefix is already 3 units")] case calling absolute_path_of_length(2) passed, which confirms the guard fires and that the message names the prefix and its width. Removed again -- a test helper's guard is not worth a permanent test, but it was worth running once rather than assuming the assertion was well formed.

Applied to both copies, for the same reason both were corrected in the previous commit.

286 tests pass in windows-namespace-request-sys, 377 in windows-file-enumeration-sys, workspace clippy clean.

Copilot AI left a comment

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.

🔵 Needs a closer look

One newly added security test asserts a non-zero last-error code for an API (IsValidSecurityDescriptor) that is not documented to set last-error, making the test potentially flaky.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

crates/windows-namespace-request-sys/src/security/tests.rs:550

  • This test assumes the capture failure always carries a non-zero Win32 last-error code (and panics if it doesn't). The failure path begins with IsValidSecurityDescriptor, which is not documented to set the thread last-error value, so io::Error::last_os_error() may be 0 or a stale value depending on prior calls; that makes this assertion potentially flaky and not a reliable property to test here. Instead, compare the typed accessor result and the source chain directly as Option<i32> without requiring it to be non-zero/present.
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 7, 2026 01:19

Copilot AI left a comment

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.

🟢 Approval recommended

The changes are confined to tests and documentation, and the updated tests/documentation appear internally consistent and aligned with Win32 UTF-16 length semantics.

Review details
  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@MikeGrier
MikeGrier merged commit 5e204d9 into main Sep 7, 2026
26 checks passed
@MikeGrier
MikeGrier deleted the mikegrier/namespace-request-tests branch September 7, 2026 01:22
MikeGrier pushed a commit that referenced this pull request Sep 7, 2026
Brings in everything peeled and reviewed since the last merge: the
namespace-request tests (#74), the Unicode terminology sweep (#75), the
security last-error correction (#76), the flush-barrier instruments (#77), and
the dangling-anchor repairs (#78).

Two conflicts, both in files this branch originated and main has since improved
through review. Took main's side in every hunk, which is the whole point of the
peel-and-review cycle -- the branch holds the drafts, main holds what survived:

  path/tests.rs      the branch still measured path lengths in bytes and
                     scalars; main's version measures UTF-16 units, guards the
                     helper against an underflowing length, and adds the case
                     that separates the units
  security/tests.rs  the branch still asserted a non-zero last-error from
                     `IsValidSecurityDescriptor`, which Windows does not
                     document as setting it; main's version compares the typed
                     accessor against the source chain instead

Verified beyond the conflicts:

- ci.yml auto-merged with no conflict; enumerated its job keys -- 20, no
  duplicates. An earlier merge on this branch produced a duplicate job exactly
  this way, and it is invisible to conflict markers.
- No conflict markers anywhere in the tree.
- cargo check --all-targets clean.
- cargo test --workspace --all-features: 3000 passed, 0 failed, 24 ignored.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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