uber-go/goleak

repository·master·Indexed 26 days ago

https://github.com/uber-go/goleak

A goroutine leak detector for Go tests. It provides tools to identify unexpected goroutine leaks using VerifyNone for individual tests, VerifyTestMain for entire packages, and the Find function for custom searches. Includes filtering options such as IgnoreTopFunction, IgnoreAnyFunction, and IgnoreCreatedBy to exclude specific goroutines from leak reports.

Tokens
1.5K
Snippets
8
Records
15
Agent score
87%

What's inside goleak

  1. Identify the source of package-level leaks

    master

    When using goleak.VerifyTestMain, leaks are only reported once after all tests have finished, making it difficult to identify the specific failing test. You can use the following bash script to run each test individually and identify which one causes the leak:

    1. Compile the tests into a binary.
    2. Iterate through all tests (including Examples) and run them one by one using the binary, printing a . for success and the test name for failure.
    # Create a test binary which will be used to run each test individually
    $ go test -c -o tests
    
    # Run each test individually, printing "." for successful tests, or the test name
    # for failing tests.
    $ for test in $(go test -list . | grep -E "^(Test|Example)"); do ./tests -test.run "^$test$" &>/dev/null && echo -n "." || echo -e "\n$test failed"; done
  2. Verify no goroutine leaks for an entire package

    master

    To check for leaks at the end of every test in a package rather than per test, implement a TestMain function and call goleak.VerifyTestMain(m). This is the recommended approach for packages that use t.Parallel().

    func TestMain(m *testing.M) {
    	goleak.VerifyTestMain(m)
    }
  3. Verify no goroutine leaks in a single test

    master

    To check for unexpected goroutines at the end of an individual test, use goleak.VerifyNone(t) within a defer statement.

    Warning: goleak cannot distinguish between a leaky goroutine and a test that is still running when using t.Parallel(). If your tests use t.Parallel(), use goleak.VerifyTestMain instead.

    func TestA(t *testing.T) {
    	defer goleak.VerifyNone(t)
    
    	// test logic here.
    }
  4. Filter goroutines using IgnoreTopFunction

    master

    Use IgnoreTopFunction to ignore any goroutines where a specific function is at the top of the stack. The function name must be fully qualified.

    Example: go.uber.org/goleak.IgnoreTopFunction

  5. Configure a cleanup function with Cleanup

    master

    Use Cleanup to provide a function that executes at the end of the leak check.

    • When passed to VerifyTestMain, the exitCode passed to the cleanup function will be the exit code of TestMain.
    • When passed to VerifyNone, the exitCode will be 0.
    • Note: This option cannot be passed to Find.
  6. Detect goroutine leaks with Find

    master

    The Find function searches for unexpected goroutines. If any extra goroutines are found, it returns a descriptive error containing the stack traces of the leaked goroutines. You can pass optional Option arguments to customize the search behavior.

    Note: Certain options like Cleanup and RunOnFailure are restricted and cannot be used with Find (they are intended for VerifyNone or VerifyTestMain respectively).

  7. Verify package-level goroutine leaks with VerifyTestMain

    master

    Use VerifyTestMain within a TestMain function to ensure that no goroutine leaks occur across your entire package's test suite.

    VerifyTestMain executes all tests in the package via m.Run(). If the tests pass, it then checks for goroutine leaks. If leaks are detected, it will report the error to stderr and fail the test run (by exiting with a non-zero code).

    To use it, implement a TestMain function in your test files that calls goleak.VerifyTestMain(m).

    func TestMain(m *testing.M) {
    	goleak.VerifyTestMain(m)
    }
  8. Verify no goroutine leaks with VerifyNone

    master

    The VerifyNone function is a helper designed for easy integration into Go tests. It marks the provided TestingT (typically *testing.T) as failed if any extra goroutines are detected.

    Common usage pattern:

    defer goleak.VerifyNone(t)

    Limitations: VerifyNone is incompatible with t.Parallel(). Because it cannot associate specific goroutines with specific tests, goroutines leaked by other tests running in parallel may cause this check to fail. If you need to run tests in parallel, use VerifyTestMain instead to verify that no leaking goroutines exist after all tests have finished.

    func VerifyNone(t TestingT, options ...Option)
  9. Filter goroutines using IgnoreAnyFunction

    master

    Use IgnoreAnyFunction to ignore goroutines where a specific function is present anywhere in the stack. The function name must be fully qualified.

    For methods, use the format: go.uber.org/goleak.(*MyType).MyMethod