Skip to content

test(b2): strengthen live tests and add credential-free twins - #248

Merged
ffumero2003 merged 7 commits into
mainfrom
test-issue-204-b2-live-assertions
Oct 30, 2026
Merged

ffumero2003 merged 7 commits into
mainfrom
test-issue-204-b2-live-assertions

Conversation

@ffumero2003

@ffumero2003 ffumero2003 commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Context

Part of the test-integrity audit (#97). This PR covers the b2/integration_test.go items of #204's ### b2 section (slice C2). Those are live tests: they only run with B2 credentials, in the live CI job on main, so several of them asserted less than their names say and nothing checked them offline.

Changes

Test-only.

Live tests strengthened (compile-checked locally; they run in the live job):

  • TestResumeWriterWithoutExtantFile, TestFileBufferLive: close the writer, read the object back and compare its SHA1 with the input.
  • TestZeroByteObject, TestWriteEmpty: assert Size == 0 and empty content on read-back.
  • TestDeleteWithoutName: a fresh handle's Attrs must return not-exist after delete.
  • TestListUnfinishedLargeFiles: asserts the exact names, the count and Err(); the chunk size is raised to B2's 5 MB part minimum.
  • TestCopyLive: compares the copy's SHA1 with the source's, not the destination's own.
  • TestReauthPreservesOptions, TestNewBucket, TestBucketDefaultEncryption: assert behavior instead of an internal struct, and no longer depend on the account's default encryption.

Credential-free twins (new *_wire_test.go, using internal/b2wiretest):

  • TestZeroByteObjectWire, TestDeleteWithoutNameWire
  • TestReauthPreservesOptionsWire: user agents, all three test modes, the transport, the endpoint and the refreshed token survive reauthorization, checked on real HTTP requests.
  • TestNewBucketAttributesWire, TestNewBucketDefaultEncryptionWire: create fields, omitted versus explicit SSE (per b2_create_bucket), and decoding of the service's answer.

Verification

Each break was applied alone to production code; the twin failed, then passed after revert. The live tests are compile-checked only (they run with B2 credentials in the live job on main).

Item Tests Status / assertion catches
R1 TestResumeWriterWithoutExtantFile Done: live-only, compile-checked; catches missing finalization or altered/truncated content after resume without an existing upload
R2 TestZeroByteObject; TestZeroByteObjectWire Done: live-only, compile-checked; catches nonzero size metadata for an empty upload; cheap offline twin M1
R3 TestDeleteWithoutName; TestWriteEmpty; TestDeleteWithoutNameWire; TestZeroByteObjectWire Done: live-only, compile-checked; catches deletion that reports success while leaving the object readable, and nonempty content after an empty write; cheap offline twins M2/M1
R4 TestListUnfinishedLargeFiles Done: live-only, compile-checked; catches wrong names, missing/extra entries and iterator errors; valid part sizes and writer finalization after listing
R5 TestFileBufferLive Done: live-only, compile-checked; catches altered/truncated bytes uploaded through the file buffer
R6 TestCopyLive Done: live-only, compile-checked; catches a corrupt copy even when its own reported SHA1 matches its corrupt content
R7 TestReauthPreservesOptions; TestReauthPreservesOptionsWire Done: live-only, compile-checked; catches a refreshed client that cannot access the original bucket; M3/M4/M8 pin user agents, all three test modes, transport, endpoint, refreshed token and account on real HTTP requests
R8 TestNewBucket; TestBucketDefaultEncryption; TestNewBucketAttributesWire; TestNewBucketDefaultEncryptionWire Done: live-only, compile-checked; catches a wrong bucket name or explicit SSE-B2 setting; M5/M6/M7 pin create fields, omitted/explicit SSE and decoded service settings without an account default assumption
Break Twin / production behavior Temporary mutation Failing output
M1 (R2/R3) TestZeroByteObjectWire; b2/b2.go:attrsFromFileInfo Map Size to size + 1 empty object size = 1, want 0 (both chunk-size cases); test failed
M2 (R3) TestDeleteWithoutNameWire; b2/b2.go:Object.Delete Return nil instead of calling deleteFileVersion Attrs after Delete = <nil>, want not-exist; delete calls = 0, want 1; test failed
M3 (R7) TestReauthPreservesOptionsWire; b2/backend.go:beRoot.reauthorizeAccount Clear userAgents in the options passed to reauthorization Requests 2/3: User-Agent = "blazer/0.9.0", want both custom agents before blazer/; test failed
M4 (R7) TestReauthPreservesOptionsWire; b2/backend.go:beRoot.reauthorizeAccount Clear transport in the options passed to reauthorization configured transport calls = 2, want 4; test failed
M5 (R8) TestNewBucketAttributesWire; b2/b2.go:Client.NewBucket Pass nil lifecycle rules to createBucket b2_create_bucket body lifecycleRules: got null instead of the two literal rules; test failed
M6 (R8) TestNewBucketDefaultEncryptionWire; base/base.go:B2.CreateBucket Always send SSE-B2/AES256, even when omitted defaultServerSideEncryption: got {"algorithm":"AES256","mode":"SSE-B2"}, want missing (both omitted cases); test failed
M7 (R8) TestNewBucketDefaultEncryptionWire; b2/baseline.go:b2Bucket.attrs Decode the returned SSE mode as broken default encryption = &{Mode:broken Algorithm:AES256}, want &{Mode:SSE-B2 Algorithm:AES256}; test failed
M8 (R7) TestReauthPreservesOptionsWire; b2/baseline.go:authOptions Omit the capExceeded block that adds base.ForceCapExceeded() Requests 0–3 each lacked force_cap_exceeded; test failed

Added for review: TestNewBucketAttributesWire also asserts the decoded bucket.Attrs(ctx) (bucket info and each lifecycle-rule field) from literal B2-shaped create and list responses. Dropping lifecycle-rule decoding fails it with Attrs LifecycleRules = 0 rules, want 2.

make ci (tail)

go build ./...
go vet ./...
go mod tidy -diff
go mod verify
all modules verified
0 issues.
go test -race -shuffle=on ./...
ok  	github.com/Backblaze/blazer/b2	17.902s
ok  	github.com/Backblaze/blazer/b2/sync	4.557s
ok  	github.com/Backblaze/blazer/base	8.654s
ok  	github.com/Backblaze/blazer/internal/b2types	1.789s
ok  	github.com/Backblaze/blazer/internal/b2wiretest	3.293s
ok  	github.com/Backblaze/blazer/internal/blog	2.783s
ok  	github.com/Backblaze/blazer/internal/retry	1.603s
ok  	github.com/Backblaze/blazer/x/b2sim	2.340s
ok  	github.com/Backblaze/blazer/x/consistent	3.578s
ok  	github.com/Backblaze/blazer/x/transport	2.827s
ok  	github.com/Backblaze/blazer/x/window	2.167s
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ./...
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build ./...
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build ./...
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build ./...
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build ./...
... scripts/*_test.sh: all ok

Part of #204

@ffumero2003 ffumero2003 added this to the 0.10.0 milestone Oct 30, 2026
@ffumero2003 ffumero2003 added the skip-changelog No changelog entry needed; skips the changelog check label Oct 30, 2026
@ffumero2003
ffumero2003 requested a review from goanpeca as a code owner October 30, 2026 18:52
@ffumero2003 ffumero2003 self-assigned this Oct 30, 2026

@david-santacruz-backblaze david-santacruz-backblaze 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.

Mate, all good. Two small asks:

  • TestNewBucketAttributesWire: also assert the decoded bucket.Attrs(ctx). The fixture has empty info and lifecycle rules, so the live round-trip has no twin.
  • intent/b2-live-assertions/: drop it and move the proof table to the PR body, or add intent.md and spec.md.

@ffumero2003

Copy link
Copy Markdown
Contributor Author

@david-santacruz-backblaze Thanks, both done:

  • TestNewBucketAttributesWire: added the decoded bucket.Attrs(ctx) check (f3e02fe). The fake's create and list responses now return the bucket info and lifecycle rules as literal B2-shaped JSON, and the test asserts each field through Attrs, so the live create → Attrs round trip has an offline twin. Dropping lifecycle-rule decoding fails it with Attrs LifecycleRules = 0 rules, want 2.
  • Intent folder: removed (804b628). The full R1–R8 / M1–M8 proof table is now in the PR description, with the make ci tail; the branch is synced with main.

@ffumero2003
ffumero2003 merged commit 6a6f50e into main Oct 30, 2026
23 of 24 checks passed
@ffumero2003
ffumero2003 deleted the test-issue-204-b2-live-assertions branch October 30, 2026 21:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changelog No changelog entry needed; skips the changelog check

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants