Skip to content

Five source-text assertions prove nothing #84

Description

@ALERTua

Found by a whole-repository review.

What is wrong

The suite cannot dot-source the script, so anything in the linear body can only be pinned by an assertion about the source text. Such an assertion is worth something only when it asserts order, count or adjacency - finding two strings somewhere in a 2868-line file proves nothing.

Five assertions do not clear that bar:

  • dev_drive.Tests.ps1:65
  • dev_drive.Tests.ps1:109
  • dev_drive.Tests.ps1:186
  • dev_drive.Tests.ps1:273
  • dev_drive.Tests.ps1:375

Two of them are worse than merely weak

:273 names a condition in its own title - that something happens when BitLocker is skipped - which its assertion never checks. It is also superseded by the stronger test at :342-373, which does pin the adjacency. It can go.

:375 is a global negative grep for the phrase "try again" across the whole file. It passes today, but it will fail the first time a legitimate future message contains those words in an unrelated sentence, and the failure will name a constraint that has nothing to do with the change. A test that will one day be wrong for the wrong reason is a maintenance trap.

What to do

For each: either rewrite it to assert order, count or adjacency - the syntax tree is available and gives exact branch membership, which is stronger than any text proximity - or delete it if a stronger test already covers the same ground.

A worked example already in the file: the assertions that check every withheld deduplication parameter sits inside an if ($DedupCapability.UsesBlockDedup) body do it by walking IfStatementAst and comparing offsets, and were proved to have teeth by inverting the guard on a copy and watching them fail. That is the standard the five should meet.

Scope

dev_drive.Tests.ps1 only. No production code changes.


Updated 2026-08-26, after #97

The line numbers above are stale - the test file has roughly doubled - so find the five by their titles.

There are now several worked examples in the file of assertions that do clear the bar, all of them proved to have teeth by reintroducing their defect on a scratch copy:

  • walking the parent chain of a CommandAst to prove a call sits inside no loop of any shape, including the script block ForEach-Object is handed
  • reading the parameter names off a CommandAst to prove every New-Partition either gives an explicit size or names the virtual disk
  • lifting a function out of the tree and enumerating the rejection tokens it can answer, to prove another function has wording for each of them

The third is the pattern most likely to help here: rather than asserting that a string appears, ask the syntax tree a question whose answer changes when the defect returns.


Updated 2026-08-26, second pass — the five are named, and three more join them

The five are identified by title. The stale line numbers were resolved against 4e54197, the last commit to touch the test file before this issue was filed. All five still exist under these titles, so nobody has to hunt for them again:

  • turns on strict mode
  • does not claim the weekly scrub job runs at a time it never schedules
  • starts the compression level unset, so no message can print one nobody chose
  • prints a plan summary line when BitLocker is skipped
  • never tells the user to just try again

The verdicts recorded above still stand: the fourth names a condition its assertion never checks and is superseded by a stronger neighbour, and the fifth is a whole-file negative grep that will one day fail for a reason unrelated to the change.

Three more, moved here from #87

#87 proposed lifting the BitLocker and deduplication blocks into phase functions so these behaviours could be tested. Measured at 269045b, that is the expensive way to close them: 20 of the 21 own functions those blocks call already have a Describe block, and Describe 'The script itself' already holds 77 assertions, 49 of them touching the syntax tree. What is genuinely uncovered is uncovered structurally, and closes here without touching production code.

1. Upgrade catches a failed automatic unlock before it calls the BitLocker setup a success. It compares four anchors in text order. That catches the inner try around Enable-BitLockerAutoUnlock being deleted, but not it being widened to wrap the whole BitLocker sequence — the offsets keep their order either way, and a widened try is exactly the defect the separate try exists to prevent. Ask the tree instead: the Enable-BitLockerAutoUnlock call must sit inside a TryStatementAst that is not the one wrapping the sequence.

2. Upgrade checks that the drive accepts writes after BitLocker and before deduplication. Three anchors in text order, so it catches deletion and nothing else. Compare node positions instead: the Get-VolumeWriteState call and the throw that follows it must fall between the end of the BitLocker if body and the Enable-ReFSDedup call.

3. New — nothing covers the password retry loop at all. The while guarding the BitLocker attempt is the only thing standing between a machine that keeps refusing a password and an endless prompt. Assert that its condition names the retry counter against its ceiling, that the counter is incremented inside the body, and that the throw follows the loop. Resolve-BitLockerFailure and Request-BitLockerFailureChoice are both already tested, so what is missing is the wiring, not the decision.

Standard, unchanged

Every one of these must be proved to have teeth by reintroducing its defect on a scratch copy of the script and watching the assertion fail. Scope is still dev_drive.Tests.ps1 only.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions