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.go119
1 files changed, 48 insertions, 71 deletions
diff --git a/xdelta3/go/src/xdelta/tgroup.go b/xdelta3/go/src/xdelta/tgroup.go
index f94c03e..7f6c875 100644
--- a/xdelta3/go/src/xdelta/tgroup.go
+++ b/xdelta3/go/src/xdelta/tgroup.go
@@ -3,114 +3,91 @@ package xdelta
3import ( 3import (
4 "fmt" 4 "fmt"
5 "sync" 5 "sync"
6 "time"
7) 6)
8 7
9type TestGroup struct { 8type TestGroup struct {
10 *Runner 9 *Runner
11 sync.Mutex 10 sync.Mutex
12 running []Goroutine 11 sync.WaitGroup
12 running []*Goroutine
13 errors []error 13 errors []error
14 waitChan <-chan bool 14 nonerrors []error // For tolerated / expected conditions
15} 15}
16 16
17type Goroutine struct { 17type Goroutine struct {
18 *TestGroup
18 name string 19 name string
19 errChan chan error 20 done bool
20} 21}
21 22
22func NewTestGroup(r *Runner) (*TestGroup, Goroutine) { 23func NewTestGroup(r *Runner) (*TestGroup, *Goroutine) {
23 g := Goroutine{"main", make(chan error, 1)} 24 tg := &TestGroup{Runner: r}
24 wc := make(chan bool) 25 tg.WaitGroup.Add(1)
25 tg := &TestGroup{Runner: r, running: []Goroutine{g}, waitChan: wc} 26 g0 := &Goroutine{tg, "main", false}
26 go waitAll(tg, wc) 27 tg.running = append(tg.running, g0)
27 return tg, g 28 return tg, g0
28} 29}
29 30
30func (g *Goroutine) String() string { 31func (g *Goroutine) String() string {
31 return fmt.Sprint("[", g.name, "]") 32 return fmt.Sprint("[", g.name, "]")
32} 33}
33 34
34func (g *Goroutine) OK() { 35func (g *Goroutine) finish(err error) {
35 fmt.Println("OK", g) 36 wait := false
36 if g.errChan != nil { 37 tg := g.TestGroup
37 g.errChan <- nil 38 tg.Lock()
38 _ = <- g.errChan 39 if g.done {
39 g.errChan = nil 40 if err != nil {
41 tg.nonerrors = append(tg.nonerrors, err)
42 }
43 } else {
44 wait = true
45 g.done = true
46 if err != nil {
47 tg.errors = append(tg.errors, err)
48 }
49 }
50 tg.Unlock()
51 if wait {
52 tg.WaitGroup.Done()
40 } 53 }
41} 54}
42 55
56func (g *Goroutine) OK() {
57 g.finish(nil)
58}
59
43func (g *Goroutine) Panic(err error) { 60func (g *Goroutine) Panic(err error) {
44 fmt.Println("PANIC", g, err) 61 g.finish(err)
45 if g.errChan != nil {
46 g.errChan <- err
47 _ = <- g.errChan
48 }
49 select {} 62 select {}
50} 63}
51 64
52func (t *TestGroup) Go(name string, f func(Goroutine)) Goroutine { 65func (t *TestGroup) Go(name string, f func(*Goroutine)) *Goroutine {
53 g := Goroutine{name, make(chan error, 1)} 66 g := &Goroutine{t, name, false}
54 t.Lock() 67 t.Lock()
68 t.WaitGroup.Add(1)
55 t.running = append(t.running, g) 69 t.running = append(t.running, g)
56 t.Unlock() 70 t.Unlock()
57 go f(g) 71 go f(g)
58 return g 72 return g
59} 73}
60 74
61func (t *TestGroup) Wait(self Goroutine, procs... *Run) { 75func (t *TestGroup) Wait(self *Goroutine, procs... *Run) {
62 self.OK() 76 self.OK()
63 t.Lock() 77 t.WaitGroup.Wait()
64 wc := t.waitChan
65 t.waitChan = nil
66 t.Unlock()
67 _ = <- wc
68 t.Lock()
69 errs := t.errors
70 t.Unlock()
71 for _, p := range procs { 78 for _, p := range procs {
72 if err := p.Wait(); err != nil { 79 if err := p.Wait(); err != nil {
73 errs = append(errs, err) 80 t.errors = append(t.errors, err)
74 } 81 }
75 } 82 }
76 if len(errs) != 0 { 83 for _, err := range t.errors {
77 for _, err := range errs { 84 fmt.Println(":ERROR:", err)
78 fmt.Println(err)
79 }
80 panic(fmt.Sprint(len(errs), " errors"))
81 } 85 }
82} 86 for _, err := range t.nonerrors {
83 87 fmt.Println("(ERROR)", err)
84func waitAll(t *TestGroup, wc chan bool) { 88 }
85 for { 89 if len(t.errors) != 0 {
86 t.Lock() 90 panic(fmt.Sprintf("Test failed with", len(t.errors), "errors"))
87 if len(t.running) == 0 {
88 t.Unlock()
89 break
90 }
91 // fmt.Println("----------------------------------------------------------------------")
92 // for _, r := range t.running {
93 // fmt.Println("Waiting for", r)
94 // }
95 runner := t.running[0]
96 t.running = t.running[1:]
97 t.Unlock()
98
99 timeout := time.After(time.Second)
100
101 select {
102 case err := <- runner.errChan:
103 runner.errChan <- err
104 if err != nil {
105 t.Lock()
106 t.errors = append(t.errors, err)
107 t.Unlock()
108 }
109 case <- timeout:
110 t.Lock()
111 t.running = append(t.running, runner)
112 t.Unlock()
113 }
114 } 91 }
115 wc <- true
116} 92}
93