Skip to content

Commit 5700168

Browse files
committed
testing: implement testing.Cleanup
TODO: pull in more upstream tests once this package is goroutine-safe
1 parent 99bebf9 commit 5700168

File tree

2 files changed

+112
-4
lines changed

2 files changed

+112
-4
lines changed

src/testing/sub_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package testing
6+
7+
import (
8+
"reflect"
9+
)
10+
11+
func TestCleanup(t *T) {
12+
var cleanups []int
13+
t.Run("test", func(t *T) {
14+
t.Cleanup(func() { cleanups = append(cleanups, 1) })
15+
t.Cleanup(func() { cleanups = append(cleanups, 2) })
16+
})
17+
if got, want := cleanups, []int{2, 1}; !reflect.DeepEqual(got, want) {
18+
t.Errorf("unexpected cleanup record; got %v want %v", got, want)
19+
}
20+
}
21+
22+
func TestRunCleanup(t *T) {
23+
outerCleanup := 0
24+
innerCleanup := 0
25+
t.Run("test", func(t *T) {
26+
t.Cleanup(func() { outerCleanup++ })
27+
t.Run("x", func(t *T) {
28+
t.Cleanup(func() { innerCleanup++ })
29+
})
30+
})
31+
if innerCleanup != 1 {
32+
t.Errorf("unexpected inner cleanup count; got %d want 1", innerCleanup)
33+
}
34+
if outerCleanup != 1 {
35+
t.Errorf("unexpected outer cleanup count; got %d want 0", outerCleanup)
36+
}
37+
}
38+
39+
func TestCleanupParallelSubtests(t *T) {
40+
ranCleanup := 0
41+
t.Run("test", func(t *T) {
42+
t.Cleanup(func() { ranCleanup++ })
43+
t.Run("x", func(t *T) {
44+
t.Parallel()
45+
if ranCleanup > 0 {
46+
t.Error("outer cleanup ran before parallel subtest")
47+
}
48+
})
49+
})
50+
if ranCleanup != 1 {
51+
t.Errorf("unexpected cleanup count; got %d want 1", ranCleanup)
52+
}
53+
}
54+
55+
func TestNestedCleanup(t *T) {
56+
ranCleanup := 0
57+
t.Run("test", func(t *T) {
58+
t.Cleanup(func() {
59+
if ranCleanup != 2 {
60+
t.Errorf("unexpected cleanup count in first cleanup: got %d want 2", ranCleanup)
61+
}
62+
ranCleanup++
63+
})
64+
t.Cleanup(func() {
65+
if ranCleanup != 0 {
66+
t.Errorf("unexpected cleanup count in second cleanup: got %d want 0", ranCleanup)
67+
}
68+
ranCleanup++
69+
t.Cleanup(func() {
70+
if ranCleanup != 1 {
71+
t.Errorf("unexpected cleanup count in nested cleanup: got %d want 1", ranCleanup)
72+
}
73+
ranCleanup++
74+
})
75+
})
76+
})
77+
if ranCleanup != 3 {
78+
t.Errorf("unexpected cleanup count: got %d want 3", ranCleanup)
79+
}
80+
}

src/testing/testing.go

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ type common struct {
4747
w io.Writer // either &output, or at top level, os.Stdout
4848
indent string
4949

50-
failed bool // Test or benchmark has failed.
51-
skipped bool // Test of benchmark has been skipped.
52-
finished bool // Test function has completed.
53-
name string // Name of test or benchmark.
50+
failed bool // Test or benchmark has failed.
51+
skipped bool // Test of benchmark has been skipped.
52+
finished bool // Test function has completed.
53+
cleanups []func() // optional functions to be called at the end of the test
5454
parent *common
55+
name string // Name of test or benchmark.
5556
}
5657

5758
// TB is the interface common to T and B.
@@ -207,7 +208,34 @@ func (c *common) Parallel() {
207208
// Unimplemented.
208209
}
209210

211+
// Cleanup registers a function to be called when the test (or subtest) and all its
212+
// subtests complete. Cleanup functions will be called in last added,
213+
// first called order.
214+
func (c *common) Cleanup(f func()) {
215+
c.cleanups = append(c.cleanups, f)
216+
}
217+
218+
// runCleanup is called at the end of the test.
219+
func (c *common) runCleanup() {
220+
for {
221+
var cleanup func()
222+
if len(c.cleanups) > 0 {
223+
last := len(c.cleanups) - 1
224+
cleanup = c.cleanups[last]
225+
c.cleanups = c.cleanups[:last]
226+
}
227+
if cleanup == nil {
228+
return
229+
}
230+
cleanup()
231+
}
232+
}
233+
210234
func tRunner(t *T, fn func(t *T)) {
235+
defer func() {
236+
t.runCleanup()
237+
}()
238+
211239
// Run the test.
212240
if flagVerbose {
213241
fmt.Fprintf(t.w, "=== RUN %s\n", t.name)

0 commit comments

Comments
 (0)