Skip to content

OCPP: clean up charge point lifecycle between subtests#29873

Merged
andig merged 1 commit into
masterfrom
fix/ocpp-test-cleanup
May 14, 2026
Merged

OCPP: clean up charge point lifecycle between subtests#29873
andig merged 1 commit into
masterfrom
fix/ocpp-test-cleanup

Conversation

@andig
Copy link
Copy Markdown
Member

@andig andig commented May 14, 2026

Summary

The OCPP test suite shares a singleton CS server across subtests via ocpp.Instance(), and the drain goroutine started in startChargePoint for handler.triggerC was never stopped — every call leaked one goroutine for the lifetime of the test process. The triggerC channel was also only make(chan …, 1), so concurrent handler invocations spawned extra sender goroutines that piled up under CI CPU pressure.

This is the structural race that previous OCPP test/test-adjacent fixes did not address:

Both removed specific blocking sends inside handlers, but the leaked drain goroutines and the capacity-1 buffer remained — visible as the intermittent TestOcpp/TestAutoStart 10s timeout (followed by connection refused on TestConnect/TestTimeout) seen on otherwise unrelated PRs (e.g. #29861, plus recent Solax / Huawei EMMA branches).

This PR:

  • Increases triggerC buffer from 1 to 16 — handlers dispatch via go func() { triggerC <- … }(), so a tight buffer just multiplies blocked-sender goroutines.
  • Registers a t.Cleanup per startChargePoint that calls cp.Stop() (if still connected) and signals the drain goroutine to exit via a done channel.
  • Uses a done channel rather than close(triggerC), because the handler senders would otherwise panic with send on closed channel.

Test plan

  • go build ./charger/...
  • go vet ./charger/
  • go test -run TestOcpp -count=1 -timeout 60s ./charger/ — 5 separate invocations, all pass (~26 s each)

🤖 Generated with Claude Code

The OCPP test suite shares a singleton CS server across subtests
(ocpp.Instance()) and the drain goroutine for triggerC was never
stopped — every startChargePoint call leaked one goroutine for the
remainder of the test process. The triggerC buffer was also only 1,
so concurrent handler invocations spawned extra send goroutines
that piled up under CI CPU pressure.

This is the structural race that the prior fixes (7a24dbd #29725,
e07838b #29838) did not address: those made specific handler sends
asynchronous to unblock the WebSocket read loop, but the leaked drain
goroutines and the buffer-1 channel remained. The result is still
intermittent TestOcpp/TestAutoStart 10s timeouts on CI runners.

Increase the triggerC buffer to 16 and register a t.Cleanup that
stops the WS client and signals the drain goroutine to exit. We
cannot close triggerC directly because ocpp_test_handler.go dispatches
sends via `go func() { triggerC <- … }()`, which would panic on a
closed channel.
@andig andig added the bug Something isn't working label May 14, 2026
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In the drain goroutine, consider using case msg, ok := <-handler.triggerC and returning when !ok so that a future change that closes triggerC doesn’t result in an infinite loop continuously reading the zero value from a closed channel.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the drain goroutine, consider using `case msg, ok := <-handler.triggerC` and returning when `!ok` so that a future change that closes `triggerC` doesn’t result in an infinite loop continuously reading the zero value from a closed channel.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@andig andig merged commit be1dd84 into master May 14, 2026
13 checks passed
@andig andig deleted the fix/ocpp-test-cleanup branch May 14, 2026 11:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant