Skip to content

test: add credential-free wire tests for client options, key lifetime, list locker and status - #255

Open
sophiecarreras wants to merge 1 commit into
Backblaze:mainfrom
sophiecarreras:test/offline-httptest-base-files-keys-lock
Open

sophiecarreras wants to merge 1 commit into
Backblaze:mainfrom
sophiecarreras:test/offline-httptest-base-files-keys-lock

Conversation

@sophiecarreras

@sophiecarreras sophiecarreras commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary: add credential-free wire tests for client options, key lifetime, ListLocker and Status, which no offline test reached before.

Motivation

Most of the offline wire tests for base and b2 already landed (#205, #206, #210, #231). A coverage run on current main still shows these paths with no offline test, so they were only reachable with live credentials or not at all:

  • FailSomeUploads, ExpireSomeAuthTokens, ForceCapExceeded in base and b2 (0% covered in either package's own tests)
  • UserAgent composition (80% in base, 0% in b2)
  • Bucket.BaseURL and Bucket.S3URL in base
  • Deadline (0%) on b2_create_key (Lifetime already had offline tests in create_key_wire_test.go; the lifetime and no-option subtests here overlap them)
  • ListLocker (0%)
  • MethodList.CountByMethod through Client.Status (0%)

Changes

Two new test files, no library code:

  • base/session_options_wire_test.go: the X-Bz-Test-Mode values (each option alone, none, and all three) on b2_authorize_account, a JSON call and a download; UserAgent order against DefaultUserAgent; BaseURL and S3URL taken from distinct values in the authorize response.
  • b2/client_options_wire_test.go: the same client options through NewClient; validDurationInSeconds for Lifetime, Deadline and no option (omitted); ListLocker held during every list request and released and balanced afterwards; Status().RPCs counts by method.

All tests use internal/b2wiretest and need no network or credentials.

Testing

make build vet fmt-check tidy-check verify test b2keys crosscompile changelog-check scripts-test with BASE_REF=upstream/main, Go 1.26.10: all passed (test is go test -race -shuffle=on ./...). make lint was NOT RUN here (it builds golangci-lint, which does not fit on this machine); CI's lint job is the check.

Coverage, go test -coverpkg=./... ./... on main vs this branch: 86.2% to 86.9% of statements. Package alone: b2 89.7% to 90.6%, base 71.3% to 73.0%.

Each test fails when the behavior it pins is broken. I broke the code one line at a time in a throwaway copy and ran the matching test; every one failed:

Change to the code Test that failed
drop the expire_some_account_authorization_tokens header in addHeaders TestTestModeOptionsSendHeaderOnEveryRequestKind
swap the order in base.UserAgent TestUserAgentOptionsArePrependedToTheDefault
Bucket.S3URL returns the download URL TestBucketURLsComeFromTheAuthorizeResponse
authOptions drops base.ForceCapExceeded() TestClientTestModeOptionsReachTheWire
authOptions drops base.UserAgent(agent) TestClientUserAgentOptionsReachTheWire
Deadline returns Lifetime(0) TestKeyLifetimeAndDeadlineSendValidDuration/deadline_is_converted_to_the_time_left
Lifetime ignores its argument TestKeyLifetimeAndDeadlineSendValidDuration
page no longer calls locker.Lock() TestListLockerIsHeldDuringEachListRequest
page unlocks before the request instead of deferring TestListLockerIsHeldDuringEachListRequest
CountByMethod stops counting TestStatusCountsRPCsByMethod

Live test: none needed. The tests pin what blazer sends and how it reads the authorize response; nothing depends on how B2 answers. The simulator contract is NOT RUN for the same reason as #205: only _test.go files change.

Risk

None for callers: test files only, no exported API or request changes. The riskiest part is TestKeyLifetimeAndDeadlineSendValidDuration/deadline_is_converted_to_the_time_left, which allows 30 seconds between the Deadline call and the request.

How to revert

Reverting this commit is enough.

Checklist

  • make ci passes locally, except lint (see Testing).
  • A fresh-context review ran on the diff (a separate pass that read only the diff and this text); it reported 0 Important and 3 Nit, posted as a comment on this PR. Nit 1 (Motivation wording) is fixed above. Nit 2 (order of the three test-mode headers is pinned) and Nit 3 (30 second Deadline window) are intentional: the order is the one addHeaders has always sent, and the window passed 30 runs under -race -shuffle=on -cpu 1,4.
  • A .changes/unreleased entry exists, or the PR is labelled skip-changelog. (Not needed: only _test.go files change, which changelog-check excludes.)
  • New or changed behavior is pinned by a test that asserts the request sent to B2. (No behavior changes; the new tests assert the requests.)
  • Behavior that depends on B2 has a live test, or the description says why not.
  • Godoc, README and AGENTS.md are updated if needed. (None needed.)
  • The description matches the final code.

🤖 Generated with Claude Code

…, list locker and status

Cover paths that no offline test reached:

- base: the X-Bz-Test-Mode headers set by FailSomeUploads, ExpireSomeAuthTokens
  and ForceCapExceeded appear on authorize, JSON and download requests; UserAgent
  options are prepended to the default in order; Bucket.BaseURL and Bucket.S3URL
  come from the authorize response.
- b2: the same client options reach the wire through NewClient; Lifetime and
  Deadline set validDurationInSeconds on b2_create_key and no option omits it;
  ListLocker is held during every list request and released after; Status
  reports RPC counts by method.

Test-only change, so no changelog entry.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sophiecarreras

Copy link
Copy Markdown
Contributor Author

0 Important, 3 Nit, 0 Pre-existing

Independent review per REVIEW.md, from a fresh context that read only the diff and the PR text. Checked against f90171a on upstream/main, Go 1.26.10 (darwin/arm64). No live B2 and no simulator were used, so nothing B2-dependent was exercised.

  • Read REVIEW.md, AGENTS.md, docs/testing.md, git diff upstream/main...HEAD (two new _test.go files, no library code) and the PR description.
  • go test -race -shuffle=on ./...: all packages ok. The 8 new tests with -race -shuffle=on -count=30 -cpu 1,4: ok (no flake, order dependence, data race or leaked goroutine seen). make ci and make lint were NOT RUN by the reviewer.
  • Mutation checks, one line broken at a time and restored with git checkout: 17 breaks, all failed the intended test. They cover each of the three X-Bz-Test-Mode lines in addHeaders, removing addHeaders on the JSON path and on the download path, both UserAgent orderings, BaseURL/S3URL swapped, each test-mode and user-agent line in authOptions, ListLocker (no Lock, no Unlock, early Unlock), Deadline and Lifetime, and CountByMethod. Every row of the PR's table reproduces.
  • Assertions compare exact header value slices and exact strings; none accepts an unrelated error.
  • Coverage re-run with and without the two files: 86.2% to 86.9% (-coverpkg=./...), b2 89.7% to 90.6%, base 71.3% to 73.0%. Matches the PR.
  • No internal or non-public references in the diff, commit message or PR text. Changelog entry correctly absent (changelog-check excludes *_test.go). No sensitive paths touched.
Severity File:Line Pass: finding
Nit PR description, Motivation; b2/client_options_wire_test.go:85-90 Compliance: Motivation lists Lifetime on b2_create_key as having no offline test, but b2/create_key_wire_test.go:56-146 already asserts validDurationInSeconds for Lifetime(time.Hour) and its absence with no option. Only Deadline is new. Reword.
Nit base/session_options_wire_test.go:80-86 Bugs (test strictness): the all three case pins the order fail_some_uploads, expire_some_account_authorization_tokens, force_cap_exceeded, which is the order of the if blocks in addHeaders, not an order B2 requires. Compare as a set or comment that the order is deliberate.
Nit b2/client_options_wire_test.go:97-99 Bugs (timing): Deadline is checked against a 30 second window. Fails only if the process stalls 30 s or the clock steps; clean at -count=30. Optionally widen.

This branch has not been deployed

No deployments
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.

1 participant