Install
$ agentstack add skill-sgaunet-claude-plugins-go-blackbox ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Go Black Box Test Enforcement
Detect Go test files using white box testing (same package name) and propose conversion to black box testing (package foo_test). Creates export_test.go bridge files when internal symbols need external test access.
When to Use
- Creating new test files (enforce black box from the start)
- Reviewing existing test files in a Go project
- User asks to audit or improve test quality
- The golang-pro agent encounters
*_test.gofiles during implementation - The golang-pro agent encounters goroutine-spawning code while writing or reviewing tests
Prerequisites
- go.mod exists: Abort if missing.
- Go source files exist: At least one
.gofile and one*_test.gofile to analyze.
Workflow: Detect White Box Tests
Step 1: Scan Test Files
Use Glob to find all test files:
**/*_test.go
Exclude vendor/ and export_test.go files from analysis.
Step 2: Classify Each Test File
For each *_test.go file, read the package declaration (first non-comment, non-blank line starting with package).
Classification rules:
| Package declaration | Source package | Classification | |---|---|---| | package foo_test | foo | Black box (correct) | | package foo | foo | White box (needs conversion) | | package foo_test | N/A (no source) | Black box (standalone) |
To determine the source package: look for non-test .go files in the same directory and read their package declaration.
Step 3: Check for export_test.go
For each directory containing test files, check whether an export_test.go already exists.
Step 4: Report Findings
Present a summary table:
| File | Package | Classification | export_test.go | |---|---|---|---| | calc_test.go | calculator | White box | No | | math_test.go | calculator_test | Black box | N/A | | internal_test.go | parser | White box | Yes |
Workflow: Convert White Box to Black Box
For each white box test file identified:
Step 1: Analyze Unexported Symbol Usage
Read the test file and identify references to unexported symbols (lowercase-initial identifiers) from the package under test:
- Unexported functions/methods called directly
- Unexported types used in variable declarations or assertions
- Unexported struct fields accessed directly
- Unexported constants/variables referenced
Step 2: Determine Conversion Strategy
Case A — No unexported symbols used:
- Change
package footopackage foo_test - Add import for the package under test
- Prefix exported symbol references with the package name (e.g.,
Add(1, 2)→calculator.Add(1, 2))
Case B — Unexported symbols used:
- Change
package footopackage foo_testin the test file - Add import for the package under test
- Create or update
export_test.goin the same directory withpackage foo(no_testsuffix) that exports needed internals:
package foo
// Exported for testing in foo_test package.
var (
TestableInternalFunc = internalFunc
TestableInternalVar = internalVar
)
- Update test file to use the exported aliases via the package import
Case C — Heavy internal coupling (>10 unexported references):
- Flag for manual review rather than automatic conversion
- Suggest refactoring the API to export what tests need, or keeping this specific file as white box with a justifying comment
Step 3: Validate
After conversion, run:
go test ./...
go vet ./...
If tests fail, diagnose: missing imports, renamed references, or unexported symbols not yet bridged via export_test.go.
Workflow: Add Goroutine Leak Detection
After conversion (or during new test creation), detect test functions that exercise goroutine-spawning code and add go.uber.org/goleak verification.
Step 1: Identify Goroutine-Spawning Source Code
For each package under test, scan the non-test .go source files for goroutine launches:
Grep pattern: `go\s+func\s*\(|go\s+[a-zA-Z]`
This matches:
go func() { ... }()— anonymous goroutinego myFunction(...)— named function goroutinego obj.Method(...)— method goroutine
Exclude vendor/ and generated files. Record which exported functions/methods directly or transitively spawn goroutines.
Step 2: Map Tests to Goroutine-Spawning Functions
For each test file in the package, identify test functions that call (directly or via helpers) the goroutine-spawning functions found in Step 1.
Classification:
| Test Function | Calls Goroutine-Spawning Code | Action | |---|---|---| | TestWorkerPool | Yes (StartWorkers uses go) | Add goleak.VerifyNone(t) | | TestParseConfig | No | Skip — no goroutine risk | | TestServerStart | Yes (Serve uses go) | Add goleak.VerifyNone(t) |
Step 3: Add goleak to Test Functions
For each test function classified as needing leak detection:
- Add the defer call as the first statement in the test function body:
func TestWorkerPool(t *testing.T) {
defer goleak.VerifyNone(t)
// ... rest of test
}
- Add the import to the test file if not already present:
import (
"testing"
"go.uber.org/goleak"
)
- Install the module if not already in
go.mod:
go get go.uber.org/goleak@latest
go mod tidy
Step 4: Handle goleak Options
Some goroutines are expected and should not trigger false positives. Common cases:
| Scenario | Option | |---|---| | Known background goroutine from a dependency | goleak.IgnoreTopFunction("package.function") | | Goroutine matching a pattern | goleak.IgnoreAnyFunction("package.glob*") |
If goleak.VerifyNone(t) fails due to known background goroutines (e.g., from net/http or logging libraries), add options:
defer goleak.VerifyNone(t,
goleak.IgnoreTopFunction("net/http.(*Server).Serve"),
)
Do not suppress unknown goroutines — investigate them first.
Step 5: Validate
Run the tests with the race detector to confirm no leaks and no regressions:
go test -race -count=1 ./...
If goleak.VerifyNone reports leaked goroutines:
- Check if the tested code properly shuts down goroutines (context cancellation, channel close,
sync.WaitGroup) - If the goroutine is from a third-party dependency and cannot be controlled, add a targeted
goleak.IgnoreTopFunctionoption - Never blanket-ignore all goroutines — each ignore must be specific and documented
export_test.go Conventions
- File name: Always
export_test.go(Go convention) - Package: Same as the source package (NOT
_testsuffix) — this is what makes it a bridge - Build constraint: None needed — Go includes
export_test.goonly duringgo test - Naming: Prefix exported aliases with
Testableor use the capitalized form of the original name - Comment: Add
// Exported for testing in _test package.header comment - Scope: Export only what tests actually need — do not blanket-export all internals
Error Handling
| Condition | Action | |-----------|--------| | No go.mod found | Abort: "Not a Go module." | | No test files found | Report: "No test files found. Nothing to analyze." | | All tests already black box | Report: "All test files use black box naming. No conversion needed." | | Test compilation fails after conversion | Diagnose missing imports or unexported references. Attempt fix (max 2 retries). | | go vet fails after conversion | Display errors and suggest manual review. | | go get go.uber.org/goleak fails | Display error. Check network connectivity and module proxy settings. | | goleak.VerifyNone reports leaked goroutines | Investigate source. Fix goroutine lifecycle first; use IgnoreTopFunction only for third-party goroutines that cannot be controlled. | | No goroutine-spawning code found in package | Skip goleak workflow: "No goroutine usage detected. Goroutine leak detection not needed." |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: sgaunet
- Source: sgaunet/claude-plugins
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.