mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 09:52:49 +00:00
Merge pull request #115456 from pohly/goroutine-leak-check
test/integration: goroutine leak check
This commit is contained in:
commit
4cf352c4bb
25
LICENSES/vendor/go.uber.org/goleak/LICENSE
generated
vendored
Normal file
25
LICENSES/vendor/go.uber.org/goleak/LICENSE
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
= vendor/go.uber.org/goleak licensed under: =
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Uber Technologies, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
= vendor/go.uber.org/goleak/LICENSE 62372d5c70f0438c59165224c1c21ee0
|
1
go.mod
1
go.mod
@ -74,6 +74,7 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.10.0
|
||||
go.opentelemetry.io/otel/trace v1.10.0
|
||||
go.opentelemetry.io/proto/otlp v0.19.0
|
||||
go.uber.org/goleak v1.2.1
|
||||
go.uber.org/zap v1.19.0
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/net v0.5.0
|
||||
|
3
go.sum
3
go.sum
@ -762,7 +762,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
|
@ -497,7 +497,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
|
2
staging/src/k8s.io/apiserver/go.sum
generated
2
staging/src/k8s.io/apiserver/go.sum
generated
@ -529,7 +529,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
|
2
staging/src/k8s.io/cloud-provider/go.sum
generated
2
staging/src/k8s.io/cloud-provider/go.sum
generated
@ -376,7 +376,7 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
|
@ -62,7 +62,7 @@ require (
|
||||
go.opentelemetry.io/otel/metric v0.31.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/goleak v1.2.0 // indirect
|
||||
go.uber.org/goleak v1.2.1 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/net v0.5.0 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
|
||||
|
4
staging/src/k8s.io/component-base/go.sum
generated
4
staging/src/k8s.io/component-base/go.sum
generated
@ -324,8 +324,8 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
|
||||
|
2
staging/src/k8s.io/controller-manager/go.sum
generated
2
staging/src/k8s.io/controller-manager/go.sum
generated
@ -369,7 +369,7 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
|
2
staging/src/k8s.io/kube-aggregator/go.sum
generated
2
staging/src/k8s.io/kube-aggregator/go.sum
generated
@ -373,7 +373,7 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
|
2
staging/src/k8s.io/pod-security-admission/go.sum
generated
2
staging/src/k8s.io/pod-security-admission/go.sum
generated
@ -371,7 +371,7 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
|
2
staging/src/k8s.io/sample-apiserver/go.sum
generated
2
staging/src/k8s.io/sample-apiserver/go.sum
generated
@ -371,7 +371,7 @@ go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||
|
@ -29,10 +29,10 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"go.uber.org/goleak"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/kubernetes/pkg/util/env"
|
||||
)
|
||||
|
||||
@ -182,37 +182,48 @@ func EtcdMain(tests func() int) {
|
||||
// Bail out early when -help was given as parameter.
|
||||
flag.Parse()
|
||||
|
||||
before := runtime.NumGoroutine()
|
||||
// Must be called *before* creating new goroutines.
|
||||
goleakOpts := IgnoreBackgroundGoroutines()
|
||||
|
||||
goleakOpts = append(goleakOpts,
|
||||
// lumberjack leaks a goroutine:
|
||||
// https://github.com/natefinch/lumberjack/issues/56 This affects tests
|
||||
// using --audit-log-path (like
|
||||
// ./test/integration/apiserver/admissionwebhook/reinvocation_test.go).
|
||||
// In normal production that should be harmless. We don't know here
|
||||
// whether the test is using that, so we have to suppress reporting
|
||||
// this leak for all tests.
|
||||
//
|
||||
// Both names occurred in practice.
|
||||
goleak.IgnoreTopFunction("k8s.io/kubernetes/vendor/gopkg.in/natefinch/lumberjack%2ev2.(*Logger).millRun"),
|
||||
goleak.IgnoreTopFunction("gopkg.in/natefinch/lumberjack%2ev2.(*Logger).millRun"),
|
||||
)
|
||||
|
||||
stop, err := startEtcd()
|
||||
if err != nil {
|
||||
klog.Fatalf("cannot run integration tests: unable to start etcd: %v", err)
|
||||
}
|
||||
result := tests()
|
||||
stop() // Don't defer this. See os.Exit documentation.
|
||||
klog.StopFlushDaemon()
|
||||
|
||||
checkNumberOfGoroutines := func() (bool, error) {
|
||||
// We leave some room for leaked goroutines as there are
|
||||
// still some leaks, mostly:
|
||||
// - leak from lumberjack package we're vendoring
|
||||
// - leak from apiserve healthz
|
||||
// - leak from opencensus library
|
||||
// Once fixed, we should be able to bring it down to zero.
|
||||
if dg := runtime.NumGoroutine() - before; dg <= 3 {
|
||||
return true, nil
|
||||
// Several tests don't wait for goroutines to stop. goleak.Find retries
|
||||
// internally, but not long enough. 5 seconds seemed to be enough for
|
||||
// most tests, even when testing in the CI.
|
||||
timeout := 5 * time.Second
|
||||
start := time.Now()
|
||||
for {
|
||||
err := goleak.Find(goleakOpts...)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if time.Now().Sub(start) >= timeout {
|
||||
klog.ErrorS(err, "EtcdMain goroutine check")
|
||||
result = 1
|
||||
break
|
||||
}
|
||||
// Allow goroutines to schedule and die off.
|
||||
runtime.Gosched()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// It generally takes visibly less than 1s to finish all goroutines.
|
||||
// But we keep the limit higher to account for cpu-starved environments.
|
||||
if err := wait.Poll(100*time.Millisecond, 5*time.Second, checkNumberOfGoroutines); err != nil {
|
||||
after := runtime.NumGoroutine()
|
||||
stacktraces := make([]byte, 1<<20)
|
||||
runtime.Stack(stacktraces, true)
|
||||
klog.Fatalf("unexpected number of goroutines: before: %d after %d\n%sd", before, after, string(stacktraces))
|
||||
}
|
||||
os.Exit(result)
|
||||
}
|
||||
|
||||
|
36
test/integration/framework/goleak.go
Normal file
36
test/integration/framework/goleak.go
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package framework
|
||||
|
||||
import (
|
||||
"go.uber.org/goleak"
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
)
|
||||
|
||||
// IgnoreBackgroundGoroutines returns options for goleak.Find
|
||||
// which ignore goroutines created by "go test" and init functions,
|
||||
// like the one from go.opencensus.io/stats/view/worker.go.
|
||||
//
|
||||
// Goroutines that normally get created later when using the apiserver
|
||||
// get created already when calling this function, therefore they
|
||||
// also get ignored.
|
||||
func IgnoreBackgroundGoroutines() []goleak.Option {
|
||||
// Ensure that on-demand goroutines are running.
|
||||
_ = healthz.LogHealthz.Check(nil)
|
||||
|
||||
return []goleak.Option{goleak.IgnoreCurrent()}
|
||||
}
|
5
vendor/go.uber.org/goleak/.gitignore
generated
vendored
Normal file
5
vendor/go.uber.org/goleak/.gitignore
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
vendor/
|
||||
/bin
|
||||
/lint.log
|
||||
/cover.out
|
||||
/cover.html
|
59
vendor/go.uber.org/goleak/CHANGELOG.md
generated
vendored
Normal file
59
vendor/go.uber.org/goleak/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.2.1]
|
||||
### Changed
|
||||
- Drop golang/x/lint dependency.
|
||||
|
||||
[1.2.1]: https://github.com/uber-go/goleak/compare/v1.2.0...v1.2.1
|
||||
|
||||
## [1.2.0]
|
||||
### Added
|
||||
- Add Cleanup option that can be used for registering cleanup callbacks. (#78)
|
||||
|
||||
### Changed
|
||||
- Mark VerifyNone as a test helper. (#75)
|
||||
|
||||
Thanks to @tallclair for their contribution to this release.
|
||||
|
||||
[1.2.0]: https://github.com/uber-go/goleak/compare/v1.1.12...v1.2.0
|
||||
|
||||
## [1.1.12]
|
||||
### Fixed
|
||||
- Fixed logic for ignoring trace related goroutines on Go versions 1.16 and above.
|
||||
|
||||
[1.1.12]: https://github.com/uber-go/goleak/compare/v1.1.11...v1.1.12
|
||||
|
||||
## [1.1.11]
|
||||
### Fixed
|
||||
- Documentation fix on how to test.
|
||||
- Update dependency on stretchr/testify to v1.7.0. (#59)
|
||||
- Update dependency on golang.org/x/tools to address CVE-2020-14040. (#62)
|
||||
|
||||
[1.1.11]: https://github.com/uber-go/goleak/compare/v1.1.10...v1.1.11
|
||||
|
||||
## [1.1.10]
|
||||
### Added
|
||||
- [#49]: Add option to ignore current goroutines, which checks for any additional leaks and allows for incremental adoption of goleak in larger projects.
|
||||
|
||||
Thanks to @denis-tingajkin for their contributions to this release.
|
||||
|
||||
[#49]: https://github.com/uber-go/goleak/pull/49
|
||||
[1.1.10]: https://github.com/uber-go/goleak/compare/v1.0.0...v1.1.10
|
||||
|
||||
## [1.0.0]
|
||||
### Changed
|
||||
- Migrate to Go modules.
|
||||
|
||||
### Fixed
|
||||
- Ignore trace related goroutines that cause false positives with -trace.
|
||||
|
||||
[1.0.0]: https://github.com/uber-go/goleak/compare/v0.10.0...v1.0.0
|
||||
|
||||
## [0.10.0]
|
||||
- Initial release.
|
||||
|
||||
[0.10.0]: https://github.com/uber-go/goleak/compare/v0.10.0...HEAD
|
21
vendor/go.uber.org/goleak/LICENSE
generated
vendored
Normal file
21
vendor/go.uber.org/goleak/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 Uber Technologies, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
41
vendor/go.uber.org/goleak/Makefile
generated
vendored
Normal file
41
vendor/go.uber.org/goleak/Makefile
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
export GOBIN ?= $(shell pwd)/bin
|
||||
|
||||
REVIVE = $(GOBIN)/revive
|
||||
|
||||
GO_FILES := $(shell \
|
||||
find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
|
||||
-o -name '*.go' -print | cut -b3-)
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
go build ./...
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
go mod download
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v -race ./...
|
||||
go test -v -trace=/dev/null .
|
||||
|
||||
.PHONY: cover
|
||||
cover:
|
||||
go test -race -coverprofile=cover.out -coverpkg=./... ./...
|
||||
go tool cover -html=cover.out -o cover.html
|
||||
|
||||
$(REVIVE):
|
||||
cd tools && go install github.com/mgechev/revive
|
||||
|
||||
.PHONY: lint
|
||||
lint: $(REVIVE)
|
||||
@rm -rf lint.log
|
||||
@echo "Checking formatting..."
|
||||
@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
|
||||
@echo "Checking vet..."
|
||||
@go vet ./... 2>&1 | tee -a lint.log
|
||||
@echo "Checking lint..."
|
||||
@$(REVIVE) -set_exit_status ./... 2>&1 | tee -a lint.log
|
||||
@echo "Checking for unresolved FIXMEs..."
|
||||
@git grep -i fixme | grep -v -e '^vendor/' -e '^Makefile' | tee -a lint.log
|
||||
@[ ! -s lint.log ]
|
74
vendor/go.uber.org/goleak/README.md
generated
vendored
Normal file
74
vendor/go.uber.org/goleak/README.md
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
# goleak [![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci] [![Coverage Status][cov-img]][cov]
|
||||
|
||||
Goroutine leak detector to help avoid Goroutine leaks.
|
||||
|
||||
## Installation
|
||||
|
||||
You can use `go get` to get the latest version:
|
||||
|
||||
`go get -u go.uber.org/goleak`
|
||||
|
||||
`goleak` also supports semver releases.
|
||||
|
||||
Note that go-leak only [supports][release] the two most recent minor versions of Go.
|
||||
|
||||
## Quick Start
|
||||
|
||||
To verify that there are no unexpected goroutines running at the end of a test:
|
||||
|
||||
```go
|
||||
func TestA(t *testing.T) {
|
||||
defer goleak.VerifyNone(t)
|
||||
|
||||
// test logic here.
|
||||
}
|
||||
```
|
||||
|
||||
Instead of checking for leaks at the end of every test, `goleak` can also be run
|
||||
at the end of every test package by creating a `TestMain` function for your
|
||||
package:
|
||||
|
||||
```go
|
||||
func TestMain(m *testing.M) {
|
||||
goleak.VerifyTestMain(m)
|
||||
}
|
||||
```
|
||||
|
||||
## Determine Source of Package Leaks
|
||||
|
||||
When verifying leaks using `TestMain`, the leak test is only run once after all tests
|
||||
have been run. This is typically enough to ensure there's no goroutines leaked from
|
||||
tests, but when there are leaks, it's hard to determine which test is causing them.
|
||||
|
||||
You can use the following bash script to determine the source of the failing test:
|
||||
|
||||
```sh
|
||||
# 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
|
||||
```
|
||||
|
||||
This will only print names of failing tests which can be investigated individually. E.g.,
|
||||
|
||||
```
|
||||
.....
|
||||
TestLeakyTest failed
|
||||
.......
|
||||
```
|
||||
|
||||
## Stability
|
||||
|
||||
goleak is v1 and follows [SemVer](http://semver.org/) strictly.
|
||||
|
||||
No breaking changes will be made to exported APIs before 2.0.
|
||||
|
||||
[doc-img]: https://godoc.org/go.uber.org/goleak?status.svg
|
||||
[doc]: https://godoc.org/go.uber.org/goleak
|
||||
[ci-img]: https://github.com/uber-go/goleak/actions/workflows/go.yml/badge.svg
|
||||
[ci]: https://github.com/uber-go/goleak/actions/workflows/go.yml
|
||||
[cov-img]: https://codecov.io/gh/uber-go/goleak/branch/master/graph/badge.svg
|
||||
[cov]: https://codecov.io/gh/uber-go/goleak
|
||||
[release]: https://go.dev/doc/devel/release#policy
|
22
vendor/go.uber.org/goleak/doc.go
generated
vendored
Normal file
22
vendor/go.uber.org/goleak/doc.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2018 Uber Technologies, Inc.
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// Package goleak is a Goroutine leak detector.
|
||||
package goleak // import "go.uber.org/goleak"
|
8
vendor/go.uber.org/goleak/glide.yaml
generated
vendored
Normal file
8
vendor/go.uber.org/goleak/glide.yaml
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
package: go.uber.org/goleak
|
||||
import: []
|
||||
testImport:
|
||||
- package: github.com/stretchr/testify
|
||||
version: ^1.1.4
|
||||
subpackages:
|
||||
- assert
|
||||
- require
|
22
vendor/go.uber.org/goleak/internal/stack/doc.go
generated
vendored
Normal file
22
vendor/go.uber.org/goleak/internal/stack/doc.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2017-2023 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
// Package stack is used for parsing stacks from `runtime.Stack`.
|
||||
package stack
|
155
vendor/go.uber.org/goleak/internal/stack/stacks.go
generated
vendored
Normal file
155
vendor/go.uber.org/goleak/internal/stack/stacks.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package stack
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const _defaultBufferSize = 64 * 1024 // 64 KiB
|
||||
|
||||
// Stack represents a single Goroutine's stack.
|
||||
type Stack struct {
|
||||
id int
|
||||
state string
|
||||
firstFunction string
|
||||
fullStack *bytes.Buffer
|
||||
}
|
||||
|
||||
// ID returns the goroutine ID.
|
||||
func (s Stack) ID() int {
|
||||
return s.id
|
||||
}
|
||||
|
||||
// State returns the Goroutine's state.
|
||||
func (s Stack) State() string {
|
||||
return s.state
|
||||
}
|
||||
|
||||
// Full returns the full stack trace for this goroutine.
|
||||
func (s Stack) Full() string {
|
||||
return s.fullStack.String()
|
||||
}
|
||||
|
||||
// FirstFunction returns the name of the first function on the stack.
|
||||
func (s Stack) FirstFunction() string {
|
||||
return s.firstFunction
|
||||
}
|
||||
|
||||
func (s Stack) String() string {
|
||||
return fmt.Sprintf(
|
||||
"Goroutine %v in state %v, with %v on top of the stack:\n%s",
|
||||
s.id, s.state, s.firstFunction, s.Full())
|
||||
}
|
||||
|
||||
func getStacks(all bool) []Stack {
|
||||
var stacks []Stack
|
||||
|
||||
var curStack *Stack
|
||||
stackReader := bufio.NewReader(bytes.NewReader(getStackBuffer(all)))
|
||||
for {
|
||||
line, err := stackReader.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// We're reading using bytes.NewReader which should never fail.
|
||||
panic("bufio.NewReader failed on a fixed string")
|
||||
}
|
||||
|
||||
// If we see the goroutine header, start a new stack.
|
||||
isFirstLine := false
|
||||
if strings.HasPrefix(line, "goroutine ") {
|
||||
// flush any previous stack
|
||||
if curStack != nil {
|
||||
stacks = append(stacks, *curStack)
|
||||
}
|
||||
id, goState := parseGoStackHeader(line)
|
||||
curStack = &Stack{
|
||||
id: id,
|
||||
state: goState,
|
||||
fullStack: &bytes.Buffer{},
|
||||
}
|
||||
isFirstLine = true
|
||||
}
|
||||
curStack.fullStack.WriteString(line)
|
||||
if !isFirstLine && curStack.firstFunction == "" {
|
||||
curStack.firstFunction = parseFirstFunc(line)
|
||||
}
|
||||
}
|
||||
|
||||
if curStack != nil {
|
||||
stacks = append(stacks, *curStack)
|
||||
}
|
||||
return stacks
|
||||
}
|
||||
|
||||
// All returns the stacks for all running goroutines.
|
||||
func All() []Stack {
|
||||
return getStacks(true)
|
||||
}
|
||||
|
||||
// Current returns the stack for the current goroutine.
|
||||
func Current() Stack {
|
||||
return getStacks(false)[0]
|
||||
}
|
||||
|
||||
func getStackBuffer(all bool) []byte {
|
||||
for i := _defaultBufferSize; ; i *= 2 {
|
||||
buf := make([]byte, i)
|
||||
if n := runtime.Stack(buf, all); n < i {
|
||||
return buf[:n]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseFirstFunc(line string) string {
|
||||
line = strings.TrimSpace(line)
|
||||
if idx := strings.LastIndex(line, "("); idx > 0 {
|
||||
return line[:idx]
|
||||
}
|
||||
panic(fmt.Sprintf("function calls missing parents: %q", line))
|
||||
}
|
||||
|
||||
// parseGoStackHeader parses a stack header that looks like:
|
||||
// goroutine 643 [runnable]:\n
|
||||
// And returns the goroutine ID, and the state.
|
||||
func parseGoStackHeader(line string) (goroutineID int, state string) {
|
||||
line = strings.TrimSuffix(line, ":\n")
|
||||
parts := strings.SplitN(line, " ", 3)
|
||||
if len(parts) != 3 {
|
||||
panic(fmt.Sprintf("unexpected stack header format: %q", line))
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(parts[1])
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to parse goroutine ID: %v in line %q", parts[1], line))
|
||||
}
|
||||
|
||||
state = strings.TrimSuffix(strings.TrimPrefix(parts[2], "["), "]")
|
||||
return id, state
|
||||
}
|
102
vendor/go.uber.org/goleak/leaks.go
generated
vendored
Normal file
102
vendor/go.uber.org/goleak/leaks.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package goleak
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/goleak/internal/stack"
|
||||
)
|
||||
|
||||
// TestingT is the minimal subset of testing.TB that we use.
|
||||
type TestingT interface {
|
||||
Error(...interface{})
|
||||
}
|
||||
|
||||
// filterStacks will filter any stacks excluded by the given opts.
|
||||
// filterStacks modifies the passed in stacks slice.
|
||||
func filterStacks(stacks []stack.Stack, skipID int, opts *opts) []stack.Stack {
|
||||
filtered := stacks[:0]
|
||||
for _, stack := range stacks {
|
||||
// Always skip the running goroutine.
|
||||
if stack.ID() == skipID {
|
||||
continue
|
||||
}
|
||||
// Run any default or user-specified filters.
|
||||
if opts.filter(stack) {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, stack)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
// Find looks for extra goroutines, and returns a descriptive error if
|
||||
// any are found.
|
||||
func Find(options ...Option) error {
|
||||
cur := stack.Current().ID()
|
||||
|
||||
opts := buildOpts(options...)
|
||||
if opts.cleanup != nil {
|
||||
return errors.New("Cleanup can only be passed to VerifyNone or VerifyTestMain")
|
||||
}
|
||||
var stacks []stack.Stack
|
||||
retry := true
|
||||
for i := 0; retry; i++ {
|
||||
stacks = filterStacks(stack.All(), cur, opts)
|
||||
|
||||
if len(stacks) == 0 {
|
||||
return nil
|
||||
}
|
||||
retry = opts.retry(i)
|
||||
}
|
||||
|
||||
return fmt.Errorf("found unexpected goroutines:\n%s", stacks)
|
||||
}
|
||||
|
||||
type testHelper interface {
|
||||
Helper()
|
||||
}
|
||||
|
||||
// VerifyNone marks the given TestingT as failed if any extra goroutines are
|
||||
// found by Find. This is a helper method to make it easier to integrate in
|
||||
// tests by doing:
|
||||
//
|
||||
// defer VerifyNone(t)
|
||||
func VerifyNone(t TestingT, options ...Option) {
|
||||
opts := buildOpts(options...)
|
||||
var cleanup func(int)
|
||||
cleanup, opts.cleanup = opts.cleanup, nil
|
||||
|
||||
if h, ok := t.(testHelper); ok {
|
||||
// Mark this function as a test helper, if available.
|
||||
h.Helper()
|
||||
}
|
||||
|
||||
if err := Find(opts); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if cleanup != nil {
|
||||
cleanup(0)
|
||||
}
|
||||
}
|
178
vendor/go.uber.org/goleak/options.go
generated
vendored
Normal file
178
vendor/go.uber.org/goleak/options.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package goleak
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.uber.org/goleak/internal/stack"
|
||||
)
|
||||
|
||||
// Option lets users specify custom verifications.
|
||||
type Option interface {
|
||||
apply(*opts)
|
||||
}
|
||||
|
||||
// We retry up to 20 times if we can't find the goroutine that
|
||||
// we are looking for. In between each attempt, we will sleep for
|
||||
// a short while to let any running goroutines complete.
|
||||
const _defaultRetries = 20
|
||||
|
||||
type opts struct {
|
||||
filters []func(stack.Stack) bool
|
||||
maxRetries int
|
||||
maxSleep time.Duration
|
||||
cleanup func(int)
|
||||
}
|
||||
|
||||
// implement apply so that opts struct itself can be used as
|
||||
// an Option.
|
||||
func (o *opts) apply(opts *opts) {
|
||||
opts.filters = o.filters
|
||||
opts.maxRetries = o.maxRetries
|
||||
opts.maxSleep = o.maxSleep
|
||||
opts.cleanup = o.cleanup
|
||||
}
|
||||
|
||||
// optionFunc lets us easily write options without a custom type.
|
||||
type optionFunc func(*opts)
|
||||
|
||||
func (f optionFunc) apply(opts *opts) { f(opts) }
|
||||
|
||||
// IgnoreTopFunction ignores any goroutines where the specified function
|
||||
// is at the top of the stack. The function name should be fully qualified,
|
||||
// e.g., go.uber.org/goleak.IgnoreTopFunction
|
||||
func IgnoreTopFunction(f string) Option {
|
||||
return addFilter(func(s stack.Stack) bool {
|
||||
return s.FirstFunction() == f
|
||||
})
|
||||
}
|
||||
|
||||
// Cleanup sets up a cleanup function that will be executed at the
|
||||
// end of the leak check.
|
||||
// When passed to [VerifyTestMain], the exit code passed to cleanupFunc
|
||||
// will be set to the exit code of TestMain.
|
||||
// When passed to [VerifyNone], the exit code will be set to 0.
|
||||
// This cannot be passed to [Find].
|
||||
func Cleanup(cleanupFunc func(exitCode int)) Option {
|
||||
return optionFunc(func(opts *opts) {
|
||||
opts.cleanup = cleanupFunc
|
||||
})
|
||||
}
|
||||
|
||||
// IgnoreCurrent records all current goroutines when the option is created, and ignores
|
||||
// them in any future Find/Verify calls.
|
||||
func IgnoreCurrent() Option {
|
||||
excludeIDSet := map[int]bool{}
|
||||
for _, s := range stack.All() {
|
||||
excludeIDSet[s.ID()] = true
|
||||
}
|
||||
return addFilter(func(s stack.Stack) bool {
|
||||
return excludeIDSet[s.ID()]
|
||||
})
|
||||
}
|
||||
|
||||
func maxSleep(d time.Duration) Option {
|
||||
return optionFunc(func(opts *opts) {
|
||||
opts.maxSleep = d
|
||||
})
|
||||
}
|
||||
|
||||
func addFilter(f func(stack.Stack) bool) Option {
|
||||
return optionFunc(func(opts *opts) {
|
||||
opts.filters = append(opts.filters, f)
|
||||
})
|
||||
}
|
||||
|
||||
func buildOpts(options ...Option) *opts {
|
||||
opts := &opts{
|
||||
maxRetries: _defaultRetries,
|
||||
maxSleep: 100 * time.Millisecond,
|
||||
}
|
||||
opts.filters = append(opts.filters,
|
||||
isTestStack,
|
||||
isSyscallStack,
|
||||
isStdLibStack,
|
||||
isTraceStack,
|
||||
)
|
||||
for _, option := range options {
|
||||
option.apply(opts)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func (o *opts) filter(s stack.Stack) bool {
|
||||
for _, filter := range o.filters {
|
||||
if filter(s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *opts) retry(i int) bool {
|
||||
if i >= o.maxRetries {
|
||||
return false
|
||||
}
|
||||
|
||||
d := time.Duration(int(time.Microsecond) << uint(i))
|
||||
if d > o.maxSleep {
|
||||
d = o.maxSleep
|
||||
}
|
||||
time.Sleep(d)
|
||||
return true
|
||||
}
|
||||
|
||||
// isTestStack is a default filter installed to automatically skip goroutines
|
||||
// that the testing package runs while the user's tests are running.
|
||||
func isTestStack(s stack.Stack) bool {
|
||||
// Until go1.7, the main goroutine ran RunTests, which started
|
||||
// the test in a separate goroutine and waited for that test goroutine
|
||||
// to end by waiting on a channel.
|
||||
// Since go1.7, a separate goroutine is started to wait for signals.
|
||||
// T.Parallel is for parallel tests, which are blocked until all serial
|
||||
// tests have run with T.Parallel at the top of the stack.
|
||||
switch s.FirstFunction() {
|
||||
case "testing.RunTests", "testing.(*T).Run", "testing.(*T).Parallel":
|
||||
// In pre1.7 and post-1.7, background goroutines started by the testing
|
||||
// package are blocked waiting on a channel.
|
||||
return strings.HasPrefix(s.State(), "chan receive")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isSyscallStack(s stack.Stack) bool {
|
||||
// Typically runs in the background when code uses CGo:
|
||||
// https://github.com/golang/go/issues/16714
|
||||
return s.FirstFunction() == "runtime.goexit" && strings.HasPrefix(s.State(), "syscall")
|
||||
}
|
||||
|
||||
func isStdLibStack(s stack.Stack) bool {
|
||||
// Importing os/signal starts a background goroutine.
|
||||
// The name of the function at the top has changed between versions.
|
||||
if f := s.FirstFunction(); f == "os/signal.signal_recv" || f == "os/signal.loop" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Using signal.Notify will start a runtime goroutine.
|
||||
return strings.Contains(s.Full(), "runtime.ensureSigM")
|
||||
}
|
69
vendor/go.uber.org/goleak/testmain.go
generated
vendored
Normal file
69
vendor/go.uber.org/goleak/testmain.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2017 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package goleak
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Variables for stubbing in unit tests.
|
||||
var (
|
||||
_osExit = os.Exit
|
||||
_osStderr io.Writer = os.Stderr
|
||||
)
|
||||
|
||||
// TestingM is the minimal subset of testing.M that we use.
|
||||
type TestingM interface {
|
||||
Run() int
|
||||
}
|
||||
|
||||
// VerifyTestMain can be used in a TestMain function for package tests to
|
||||
// verify that there were no goroutine leaks.
|
||||
// To use it, your TestMain function should look like:
|
||||
//
|
||||
// func TestMain(m *testing.M) {
|
||||
// goleak.VerifyTestMain(m)
|
||||
// }
|
||||
//
|
||||
// See https://golang.org/pkg/testing/#hdr-Main for more details.
|
||||
//
|
||||
// This will run all tests as per normal, and if they were successful, look
|
||||
// for any goroutine leaks and fail the tests if any leaks were found.
|
||||
func VerifyTestMain(m TestingM, options ...Option) {
|
||||
exitCode := m.Run()
|
||||
opts := buildOpts(options...)
|
||||
|
||||
var cleanup func(int)
|
||||
cleanup, opts.cleanup = opts.cleanup, nil
|
||||
if cleanup == nil {
|
||||
cleanup = _osExit
|
||||
}
|
||||
defer func() { cleanup(exitCode) }()
|
||||
|
||||
if exitCode == 0 {
|
||||
if err := Find(opts); err != nil {
|
||||
fmt.Fprintf(_osStderr, "goleak: Errors on successful test run: %v\n", err)
|
||||
exitCode = 1
|
||||
}
|
||||
}
|
||||
}
|
34
vendor/go.uber.org/goleak/tracestack_new.go
generated
vendored
Normal file
34
vendor/go.uber.org/goleak/tracestack_new.go
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2021 Uber Technologies, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package goleak
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"go.uber.org/goleak/internal/stack"
|
||||
)
|
||||
|
||||
func isTraceStack(s stack.Stack) bool {
|
||||
return strings.Contains(s.Full(), "runtime.ReadTrace")
|
||||
}
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@ -973,6 +973,10 @@ go.starlark.net/syntax
|
||||
# go.uber.org/atomic v1.7.0
|
||||
## explicit; go 1.13
|
||||
go.uber.org/atomic
|
||||
# go.uber.org/goleak v1.2.1
|
||||
## explicit; go 1.18
|
||||
go.uber.org/goleak
|
||||
go.uber.org/goleak/internal/stack
|
||||
# go.uber.org/multierr v1.6.0
|
||||
## explicit; go 1.12
|
||||
go.uber.org/multierr
|
||||
|
Loading…
Reference in New Issue
Block a user