From c1902e62c44a28027db5844bd07687e32e0896f7 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Wed, 7 Jun 2017 20:39:44 +0800 Subject: [PATCH] util/testleak: make it work right (#3414) * fix testleak package * provide "make leak" to makefile --- Makefile | 7 +++++++ bootstrap_test.go | 1 + tidb_test.go | 2 ++ util/testleak/fake.go | 27 +++++++++++++++++++++++++++ util/testleak/leaktest.go | 7 ++++++- 5 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 util/testleak/fake.go diff --git a/Makefile b/Makefile index e856834cdca7f..41a134a11dc26 100644 --- a/Makefile +++ b/Makefile @@ -121,6 +121,13 @@ race: parserlib @export log_level=debug; \ $(GOTEST) -race $(PACKAGES) +leak: parserlib + @export log_level=debug; \ + for dir in $(PACKAGES); do \ + echo $$dir; \ + $(GOTEST) -tags leak $$dir | awk 'END{if($$1=="FAIL") {exit 1}}' || exit 1; \ + done; + tikv_integration_test: parserlib $(GOTEST) ./store/tikv/. -with-tikv=true diff --git a/bootstrap_test.go b/bootstrap_test.go index 164b04cb46a7b..2c1042a217d7a 100644 --- a/bootstrap_test.go +++ b/bootstrap_test.go @@ -169,6 +169,7 @@ func (s *testBootstrapSuite) testBootstrapWithError(c *C) { func (s *testBootstrapSuite) TestUpgrade(c *C) { defer testleak.AfterTest(c)() store := newStoreWithBootstrap(c, s.dbName) + defer store.Close() se := newSession(c, store, s.dbName) mustExecSQL(c, se, "USE mysql;") diff --git a/tidb_test.go b/tidb_test.go index 5ea9eb5a84068..27357fdf81619 100644 --- a/tidb_test.go +++ b/tidb_test.go @@ -254,6 +254,7 @@ func (s *testMainSuite) TestRetryOpenStore(c *C) { func (s *testMainSuite) TestSchemaValidity(c *C) { localstore.MockRemoteStore = true store := newStoreWithBootstrap(c, s.dbName+"schema_validity") + defer store.Close() dbName := "test_schema_validity" se := newSession(c, store, dbName) se1 := newSession(c, store, dbName) @@ -345,6 +346,7 @@ func (s *testMainSuite) TestSchemaValidity(c *C) { func (s *testMainSuite) TestSysSessionPoolGoroutineLeak(c *C) { // TODO: testleak package should be able to find this leak. store := newStoreWithBootstrap(c, s.dbName+"goroutine_leak") + defer store.Close() se, err := createSession(store) c.Assert(err, IsNil) diff --git a/util/testleak/fake.go b/util/testleak/fake.go new file mode 100644 index 0000000000000..db7b7f062979b --- /dev/null +++ b/util/testleak/fake.go @@ -0,0 +1,27 @@ +// Copyright 2017 PingCAP, Inc. +// +// 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, +// See the License for the specific language governing permissions and +// limitations under the License. +// +build !leak + +package testleak + +import "github.com/pingcap/check" + +// BeforeTest is a dummy implementation when build tag 'leak' is not set. +func BeforeTest() { +} + +// AfterTest is a dummy implementation when build tag 'leak' is not set. +func AfterTest(c *check.C) func() { + return func() { + } +} diff --git a/util/testleak/leaktest.go b/util/testleak/leaktest.go index 3f06416a38e7e..35fb9a38deb6d 100644 --- a/util/testleak/leaktest.go +++ b/util/testleak/leaktest.go @@ -14,6 +14,7 @@ // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. +// +build leak package testleak @@ -42,6 +43,10 @@ func interestingGoroutines() (gs []string) { strings.Contains(stack, "localstore.(*dbStore).scheduler") || strings.Contains(stack, "ddl.(*ddl).start") || strings.Contains(stack, "domain.NewDomain") || + strings.Contains(stack, "testing.(*T).Run") || + strings.Contains(stack, "tidb.asyncGetTSWorker") || // TODO: remove it + strings.Contains(stack, "domain.(*Domain).LoadPrivilegeLoop") || + strings.Contains(stack, "domain.(*Domain).UpdateTableStatsLoop") || strings.Contains(stack, "testing.Main(") || strings.Contains(stack, "runtime.goexit") || strings.Contains(stack, "created by runtime.gc") || @@ -85,6 +90,7 @@ func AfterTest(c *check.C) func() { var leaked []string for i := 0; i < 50; i++ { + leaked = leaked[:0] for _, g := range interestingGoroutines() { if !beforeTestGorountines[g] { leaked = append(leaked, g) @@ -93,7 +99,6 @@ func AfterTest(c *check.C) func() { // Bad stuff found, but goroutines might just still be // shutting down, so give it some time. if len(leaked) != 0 { - leaked = leaked[:0] time.Sleep(50 * time.Millisecond) continue }