Environment
- CubeSandbox commit: master @
002e404
- Relevant component:
network-agent (internal/service)
Problem
TestEnsureReleaseEnsureReusesTapFromPool fails deterministically. After a successful ReleaseNetwork it asserts the recycled tap is empty in tapPool and pending in abnormalTapPool ("before async preparation"), but the tap is already in tapPool.
Steps to Reproduce
cd network-agent && go test ./internal/service/ -run '^TestEnsureReleaseEnsureReusesTapFromPool$'
Actual Behavior
local_service_test.go:588: tapPool len=1, want 0 before async preparation
--- FAIL: TestEnsureReleaseEnsureReusesTapFromPool
Deterministic (10/10) — the test builds localService as a struct literal with success mocks and no maintenance goroutine, so there is no timing element.
Root cause
With only success mocks installed (cubevsPrepareTAPPolicy → nil, etc.), releaseState → prepareAndStageTapForPool runs synchronously and stages the tap straight into tapPool via stageTapForPoolLocked. Deferral into abnormalTapPool happens only when preparation fails — exactly what the sibling test TestReleaseNetworkQueuesTapWhenPoolPrepareFails exercises by injecting a prepare boom error. The assertions in TestEnsureReleaseEnsureReusesTapFromPool appear to predate the switch to synchronous-on-success staging and were left stale.
Expected Behavior
On the success path the recycled tap is staged synchronously into tapPool (tapPool==1, abnormalTapPool==0).
Proposed fix
Test-only: assert the synchronous outcome and drop the handleAbnormalTaps() step. Production code is unchanged; the intended behavior is already covered by the failure-path sibling test. Verified 50/50 pass after the change, internal/service package green. A PR follows.
Environment
002e404network-agent(internal/service)Problem
TestEnsureReleaseEnsureReusesTapFromPoolfails deterministically. After a successfulReleaseNetworkit asserts the recycled tap is empty intapPooland pending inabnormalTapPool("before async preparation"), but the tap is already intapPool.Steps to Reproduce
Actual Behavior
Deterministic (10/10) — the test builds
localServiceas a struct literal with success mocks and no maintenance goroutine, so there is no timing element.Root cause
With only success mocks installed (
cubevsPrepareTAPPolicy→ nil, etc.),releaseState→prepareAndStageTapForPoolruns synchronously and stages the tap straight intotapPoolviastageTapForPoolLocked. Deferral intoabnormalTapPoolhappens only when preparation fails — exactly what the sibling testTestReleaseNetworkQueuesTapWhenPoolPrepareFailsexercises by injecting aprepare boomerror. The assertions inTestEnsureReleaseEnsureReusesTapFromPoolappear to predate the switch to synchronous-on-success staging and were left stale.Expected Behavior
On the success path the recycled tap is staged synchronously into
tapPool(tapPool==1,abnormalTapPool==0).Proposed fix
Test-only: assert the synchronous outcome and drop the
handleAbnormalTaps()step. Production code is unchanged; the intended behavior is already covered by the failure-path sibling test. Verified 50/50 pass after the change,internal/servicepackage green. A PR follows.