summaryrefslogtreecommitdiff
path: root/xdelta3/go/src/xdelta/tgroup.go
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3/go/src/xdelta/tgroup.go')
-rw-r--r--xdelta3/go/src/xdelta/tgroup.go97
1 files changed, 97 insertions, 0 deletions
diff --git a/xdelta3/go/src/xdelta/tgroup.go b/xdelta3/go/src/xdelta/tgroup.go
new file mode 100644
index 0000000..602b1e1
--- /dev/null
+++ b/xdelta3/go/src/xdelta/tgroup.go
@@ -0,0 +1,97 @@
1package xdelta
2
3import (
4 "fmt"
5 "runtime"
6 "sync"
7)
8
9type TestGroup struct {
10 *Runner
11 main *Goroutine
12 sync.Mutex
13 sync.WaitGroup
14 running []*Goroutine
15 errors []error
16 nonerrors []error // For tolerated / expected conditions
17}
18
19type Goroutine struct {
20 *TestGroup
21 name string
22 done bool
23}
24
25func (g *Goroutine) String() string {
26 return fmt.Sprint("[", g.name, "]")
27}
28
29func (g *Goroutine) finish(err error) {
30 wait := false
31 tg := g.TestGroup
32 sbuf := make([]byte, 4096)
33 sbuf = sbuf[0:runtime.Stack(sbuf, false)]
34 if err != nil {
35 err = fmt.Errorf("%v:%v:%v", g.name, err, string(sbuf))
36 }
37 tg.Lock()
38 if g.done {
39 if err != nil {
40 tg.nonerrors = append(tg.nonerrors, err)
41 }
42 } else {
43 wait = true
44 g.done = true
45 if err != nil {
46 tg.errors = append(tg.errors, err)
47 }
48 }
49 tg.Unlock()
50 if wait {
51 tg.WaitGroup.Done()
52 }
53}
54
55func (g *Goroutine) OK() {
56 g.finish(nil)
57}
58
59func (g *Goroutine) Panic(err error) {
60 g.finish(err)
61 if g != g.TestGroup.main {
62 runtime.Goexit()
63 }
64}
65
66func (t *TestGroup) Main() *Goroutine { return t.main }
67
68func (t *TestGroup) Panic(err error) { t.Main().Panic(err) }
69
70func (t *TestGroup) Go(name string, f func(*Goroutine)) *Goroutine {
71 g := &Goroutine{t, name, false}
72 t.Lock()
73 t.WaitGroup.Add(1)
74 t.running = append(t.running, g)
75 t.Unlock()
76 go f(g)
77 return g
78}
79
80func (t *TestGroup) Wait(procs... *Run) {
81 t.Main().OK()
82 t.WaitGroup.Wait()
83 for _, p := range procs {
84 if err := p.Wait(); err != nil {
85 t.errors = append(t.errors, err)
86 }
87 }
88 for _, err := range t.errors {
89 fmt.Println(":ERROR:", err)
90 }
91 for _, err := range t.nonerrors {
92 fmt.Println("(ERROR)", err)
93 }
94 if len(t.errors) != 0 {
95 t.Fail("Test failed with", len(t.errors), "errors")
96 }
97}