Repository: matrixorigin/matrixcube (go)

Issue:
Enable leaked file descriptor and goroutine checks in unit tests

Pull request description:
Resolve #333 added leaked file descriptor and goroutine checks to some tests
**What type of PR is this?**

- [ ] API-change
- [ ] BUG
- [ ] Improvement
- [ ] Documentation
- [ ] Feature
- [x] Test and CI
- [ ] Code Refactoring

**Which issue(s) this PR fixes:**

Fixes #333 

**What this PR does / why we need it:**

Not Available

**Special notes for your reviewer:**

Not Available

**Additional documentation (e.g. design docs, usage docs, etc.):**

Not Available


Patch:
diff --git a/.gitignore b/.gitignore
index 46be181..3fe13a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,5 +18,8 @@
 
 hrl
 dist
+*safe_to_delete*
+*safe-to-delete*
+.DS_Store
 .vscode/
 vendor/


Test patch:
diff --git a/logdb/logdb_test.go b/logdb/logdb_test.go
index 5085c1d..b5c3930 100644
--- a/logdb/logdb_test.go
+++ b/logdb/logdb_test.go
@@ -41,6 +41,7 @@ import (
 	"github.com/matrixorigin/matrixcube/components/log"
 	"github.com/matrixorigin/matrixcube/storage"
 	"github.com/matrixorigin/matrixcube/storage/kv/pebble"
+	"github.com/matrixorigin/matrixcube/util/leaktest"
 	"github.com/matrixorigin/matrixcube/vfs"
 )
 
@@ -61,6 +62,8 @@ func getTestStorage(fs vfs.FS) storage.KVStorage {
 }
 
 func runLogDBTest(t *testing.T, tf func(t *testing.T, db *KVLogDB), fs vfs.FS) {
+	defer vfs.ReportLeakedFD(fs, t)
+	defer leaktest.AfterTest(t)()
 	kv := getTestStorage(fs)
 	defer kv.Close()
 	db := NewKVLogDB(kv, log.GetDefaultZapLogger())
diff --git a/raftstore/execute_context_test.go b/raftstore/execute_context_test.go
index 774304a..257e281 100644
--- a/raftstore/execute_context_test.go
+++ b/raftstore/execute_context_test.go
@@ -40,7 +40,9 @@ func TestWriteContextCanBeInitialized(t *testing.T) {
 	}
 
 	shard := Shard{ID: 12345}
-	base := kv.NewBaseStorage(mem.NewStorage(), vfs.GetTestFS())
+	fs := vfs.GetTestFS()
+	defer vfs.ReportLeakedFD(fs, t)
+	base := kv.NewBaseStorage(mem.NewStorage(), fs)
 	defer base.Close()
 	ctx := newWriteContext(base)
 	assert.False(t, ctx.hasRequest())
diff --git a/raftstore/replica_destroy_test.go b/raftstore/replica_destroy_test.go
index 061e66e..d5cbe84 100644
--- a/raftstore/replica_destroy_test.go
+++ b/raftstore/replica_destroy_test.go
@@ -21,12 +21,13 @@ import (
 
 	"github.com/matrixorigin/matrixcube/components/log"
 	"github.com/matrixorigin/matrixcube/storage"
-	"github.com/matrixorigin/matrixcube/util/leaktest"
+	// "github.com/matrixorigin/matrixcube/util/leaktest"
 	"github.com/matrixorigin/matrixcube/util/task"
 )
 
 func TestDestroyReplica(t *testing.T) {
-	defer leaktest.AfterTest(t)()
+	// FIXME: re-enable the leak test below
+	// defer leaktest.AfterTest(t)()
 	r := Replica{ID: 1}
 	s := NewSingleTestClusterStore(t).GetStore(0).(*store)
 	kv := s.DataStorageByGroup(0).(storage.KVStorageWrapper).GetKVStorage()
diff --git a/raftstore/replica_event_loop_test.go b/raftstore/replica_event_loop_test.go
index 4450f6a..68a1757 100644
--- a/raftstore/replica_event_loop_test.go
+++ b/raftstore/replica_event_loop_test.go
@@ -24,6 +24,7 @@ import (
 	"github.com/matrixorigin/matrixcube/logdb"
 	"github.com/matrixorigin/matrixcube/storage"
 	"github.com/matrixorigin/matrixcube/storage/kv/pebble"
+	"github.com/matrixorigin/matrixcube/util/leaktest"
 	"github.com/matrixorigin/matrixcube/util/task"
 	"github.com/matrixorigin/matrixcube/vfs"
 )
@@ -42,7 +43,7 @@ func getTestStorage() storage.KVStorage {
 
 // TODO: we need this here largely because it is pretty difficult to write unit
 // tests for the replica type when it has an injected store instance in it.
-func getCloseableReplica() *replica {
+func getCloseableReplica() (*replica, func()) {
 	l := log.GetDefaultZapLogger()
 	r := Replica{}
 	shardID := uint64(1)
@@ -79,10 +80,13 @@ func getCloseableReplica() *replica {
 		closedC:           make(chan struct{}),
 		unloadedC:         make(chan struct{}),
 		sm:                &stateMachine{},
-	}
+	}, func() { kv.Close() }
 }
 
 func TestReplicaCanBeClosed(t *testing.T) {
-	r := getCloseableReplica()
+	defer leaktest.AfterTest(t)()
+	r, closer := getCloseableReplica()
+	defer r.close()
+	defer closer()
 	assert.True(t, r.handleEvent(nil))
 }
diff --git a/raftstore/replica_event_raft_ready_test.go b/raftstore/replica_event_raft_ready_test.go
index 4c7ec7e..6846fd3 100644
--- a/raftstore/replica_event_raft_ready_test.go
+++ b/raftstore/replica_event_raft_ready_test.go
@@ -17,11 +17,13 @@ import (
 	"testing"
 
 	"github.com/cockroachdb/errors"
-	"github.com/matrixorigin/matrixcube/pb/meta"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"go.etcd.io/etcd/raft/v3"
 	"go.etcd.io/etcd/raft/v3/raftpb"
+
+	"github.com/matrixorigin/matrixcube/pb/meta"
+	"github.com/matrixorigin/matrixcube/util/leaktest"
 )
 
 func getRaftMessageTypes() []raftpb.MessageType {
@@ -68,6 +70,7 @@ func TestIsMsgApp(t *testing.T) {
 }
 
 func TestSendRaftMesasgeReturnsErrUnknownReplicaWhenReplicaIsUnknown(t *testing.T) {
+	defer leaktest.AfterTest(t)()
 	r := replica{
 		store: &store{},
 		sm:    &stateMachine{},
@@ -88,6 +91,7 @@ func (t *replicaTestTransport) Send(m meta.RaftMessage) {
 }
 
 func TestSendRaftMessageAttachsExpectedShardDetails(t *testing.T) {
+	defer leaktest.AfterTest(t)()
 	trans := &replicaTestTransport{}
 	r := replica{
 		replica:   Replica{ID: 100},
@@ -127,6 +131,7 @@ func TestSendRaftMessageAttachsExpectedShardDetails(t *testing.T) {
 }
 
 func testSendMessages(t *testing.T, appendOnly bool) {
+	defer leaktest.AfterTest(t)()
 	trans := &replicaTestTransport{}
 	r := replica{
 		replica:   Replica{ID: 100},
diff --git a/raftstore/replica_state_machine_test.go b/raftstore/replica_state_machine_test.go
index 3d69feb..d0ba913 100644
--- a/raftstore/replica_state_machine_test.go
+++ b/raftstore/replica_state_machine_test.go
@@ -31,10 +31,12 @@ import (
 	"github.com/matrixorigin/matrixcube/storage/executor/simple"
 	"github.com/matrixorigin/matrixcube/storage/kv"
 	"github.com/matrixorigin/matrixcube/storage/kv/pebble"
+	"github.com/matrixorigin/matrixcube/util/leaktest"
 	"github.com/matrixorigin/matrixcube/vfs"
 )
 
 func TestStateMachineApplyContextCanBeInitialized(t *testing.T) {
+	defer leaktest.AfterTest(t)()
 	req := rpc.RequestBatch{
 		Header: rpc.RequestBatchHeader{
 			ID: []byte{0x1, 0x2, 0x3},
@@ -63,6 +65,7 @@ func TestStateMachineApplyContextCanBeInitialized(t *testing.T) {
 }
 
 func TestStateMachineApplyContextCanBeInitializedForConfigChange(t *testing.T) {
+	defer leaktest.AfterTest(t)()
 	batch := rpc.RequestBatch{
 		Header: rpc.RequestBatchHeader{
 			ID:      []byte{0x1, 0x2, 0x3},
@@ -103,6 +106,8 @@ func runSimpleStateMachineTest(t *testing.T,
 	l := log.GetDefaultZapLogger(zap.OnFatal(zapcore.WriteThenPanic))
 	shard := Shard{ID: 100}
 	fs := vfs.NewMemFS()
+	defer vfs.ReportLeakedFD(fs, t)
+	defer leaktest.AfterTest(t)()
 	opts := &cpebble.Options{
 		FS: vfs.NewPebbleFS(fs),
 	}
diff --git a/raftstore/snapshotter_test.go b/raftstore/snapshotter_test.go
index 12d0280..074a97a 100644
--- a/raftstore/snapshotter_test.go
+++ b/raftstore/snapshotter_test.go
@@ -79,6 +79,7 @@ func getTestSnapshotter(ldb logdb.LogDB, fs vfs.FS) *snapshotter {
 func runSnapshotterTest(t *testing.T,
 	fn func(t *testing.T, logdb logdb.LogDB, snapshotter *snapshotter), fs vfs.FS) {
 	defer leaktest.AfterTest(t)()
+	defer vfs.ReportLeakedFD(fs, t)
 	deleteSnapshotterTestDir(fs)
 	ldb, closer := getNewTestDB()
 	defer closer()
diff --git a/snapshot/snapshot_env_test.go b/snapshot/snapshot_env_test.go
index ce2fed5..15dc1db 100644
--- a/snapshot/snapshot_env_test.go
+++ b/snapshot/snapshot_env_test.go
@@ -53,6 +53,7 @@ func TestGetFinalDirWillPanicWhenIndexIsNotFinalizedInCreatingMode(t *testing.T)
 		return "/data"
 	}
 	fs := vfs.GetTestFS()
+	defer reportLeakedFD(fs, t)
 	env := NewSSEnv(f, 1, 1, 1, 2, CreatingMode, fs)
 	env.GetFinalDir()
 }
@@ -62,6 +63,7 @@ func TestGetFinalDirWillNotPanicInReceivingMode(t *testing.T) {
 		return "/data"
 	}
 	fs := vfs.GetTestFS()
+	defer reportLeakedFD(fs, t)
 	env := NewSSEnv(f, 1, 1, 1, 2, ReceivingMode, fs)
 	assert.Equal(t, "/data/snapshot-0000000000000001", env.GetFinalDir())
 }
@@ -71,6 +73,7 @@ func TestGetFinalDirWillNotPanicWhenIndexIsFinalizedInCreatingMode(t *testing.T)
 		return "/data"
 	}
 	fs := vfs.GetTestFS()
+	defer reportLeakedFD(fs, t)
 	env := NewSSEnv(f, 1, 1, 1, 2, CreatingMode, fs)
 	env.FinalizeIndex(100)
 	assert.Equal(t, "/data/snapshot-0000000000000064", env.GetFinalDir())
@@ -127,6 +130,7 @@ func TestTempSuffix(t *testing.T) {
 		return "/data"
 	}
 	fs := vfs.GetTestFS()
+	defer reportLeakedFD(fs, t)
 	env := NewSSEnv(f, 1, 1, 1, 2, CreatingMode, fs)
 	dir := env.GetTempDir()
 	if !strings.Contains(dir, ".generating") {
@@ -137,7 +141,6 @@ func TestTempSuffix(t *testing.T) {
 	if !strings.Contains(dir, ".receiving") {
 		t.Errorf("unexpected suffix: %s", dir)
 	}
-	reportLeakedFD(fs, t)
 }
 
 func TestFinalSnapshotDirDoesNotContainTempSuffix(t *testing.T) {
@@ -145,6 +148,7 @@ func TestFinalSnapshotDirDoesNotContainTempSuffix(t *testing.T) {
 		return "/data"
 	}
 	fs := vfs.GetTestFS()
+	defer reportLeakedFD(fs, t)
 	env := NewSSEnv(f, 1, 1, 1, 2, CreatingMode, fs)
 	env.FinalizeIndex(1)
 	dir := env.GetFinalDir()
@@ -158,17 +162,18 @@ func TestRootDirIsTheParentOfTempFinalDirs(t *testing.T) {
 		return "/data"
 	}
 	fs := vfs.GetTestFS()
+	defer reportLeakedFD(fs, t)
 	env := NewSSEnv(f, 1, 1, 1, 2, ReceivingMode, fs)
 	tmpDir := env.GetTempDir()
 	finalDir := env.GetFinalDir()
 	rootDir := env.GetRootDir()
 	mustBeChild(rootDir, tmpDir)
 	mustBeChild(rootDir, finalDir)
-	reportLeakedFD(fs, t)
 }
 
 func runEnvTest(t *testing.T, f func(t *testing.T, env SSEnv), fs vfs.FS) {
 	rd := "server-pkg-test-data-safe-to-delete"
+	defer reportLeakedFD(fs, t)
 	defer func() {
 		if err := fs.RemoveAll(rd); err != nil {
 			t.Fatalf("%v", err)
@@ -185,7 +190,6 @@ func runEnvTest(t *testing.T, f func(t *testing.T, env SSEnv), fs vfs.FS) {
 		}
 		f(t, env)
 	}()
-	reportLeakedFD(fs, t)
 }
 
 func TestRenameTempDirToFinalDir(t *testing.T) {
diff --git a/util/leaktest/leak.go b/util/leaktest/leak.go
index cf16adf..4661367 100644
--- a/util/leaktest/leak.go
+++ b/util/leaktest/leak.go
@@ -20,7 +20,7 @@ import (
 )
 
 var (
-	disabled = true
+	disabled = false
 )
 
 func AfterTest(t testing.TB) func() {