summaryrefslogtreecommitdiff
path: root/xdelta3
diff options
context:
space:
mode:
authorJoshua MacDonald <josh.macdonald@gmail.com>2015-11-23 20:28:05 -0800
committerJoshua MacDonald <josh.macdonald@gmail.com>2015-11-23 20:28:05 -0800
commitb24969720ac9c92f3d7327250b3ee8e86acc6def (patch)
tree1e2401ee0b0cfa0f9d382fbc33f3445a3947fb49 /xdelta3
parentede482d8f3398262adcfb23095b6caad5872d8ba (diff)
Improve error handling; allow two routines to have errors in a successful test (Empty, which can get bad file descriptor after the process exits, and the Decode-Source writer, since the decoder is not required to read the full source)
Diffstat (limited to 'xdelta3')
-rw-r--r--xdelta3/go/src/regtest.go18
-rw-r--r--xdelta3/go/src/xdelta/rstream.go15
-rw-r--r--xdelta3/go/src/xdelta/test.go6
-rw-r--r--xdelta3/go/src/xdelta/tgroup.go41
4 files changed, 49 insertions, 31 deletions
diff --git a/xdelta3/go/src/regtest.go b/xdelta3/go/src/regtest.go
index 793c9fc..385c936 100644
--- a/xdelta3/go/src/regtest.go
+++ b/xdelta3/go/src/regtest.go
@@ -20,7 +20,7 @@ func smokeTest(r *xdelta.Runner, p *xdelta.Program) {
20 target := "Hello world!" 20 target := "Hello world!"
21 source := "Hello world, nice to meet you!" 21 source := "Hello world, nice to meet you!"
22 22
23 enc, err := t.Exec(p, true, []string{"-evv"}) 23 enc, err := t.Exec("encode", p, true, []string{"-evv"})
24 if err != nil { 24 if err != nil {
25 g.Panic(err) 25 g.Panic(err)
26 } 26 }
@@ -34,7 +34,7 @@ func smokeTest(r *xdelta.Runner, p *xdelta.Program) {
34 g.Panic(err) 34 g.Panic(err)
35 } 35 }
36 36
37 dec, err := t.Exec(p, true, []string{"-dvv"}) 37 dec, err := t.Exec("decode", p, true, []string{"-dvv"})
38 if err != nil { 38 if err != nil {
39 g.Panic(err) 39 g.Panic(err)
40 } 40 }
@@ -59,13 +59,13 @@ func smokeTest(r *xdelta.Runner, p *xdelta.Program) {
59func offsetTest(r *xdelta.Runner, p *xdelta.Program, bufsize, offset, length int64) { 59func offsetTest(r *xdelta.Runner, p *xdelta.Program, bufsize, offset, length int64) {
60 t, g := xdelta.NewTestGroup(r) 60 t, g := xdelta.NewTestGroup(r)
61 eargs := []string{"-e", "-0", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)} 61 eargs := []string{"-e", "-0", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)}
62 enc, err := t.Exec(p, true, eargs) 62 enc, err := t.Exec("encode", p, true, eargs)
63 if err != nil { 63 if err != nil {
64 g.Panic(err) 64 g.Panic(err)
65 } 65 }
66 66
67 dargs := []string{"-d", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)} 67 dargs := []string{"-d", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)}
68 dec, err := t.Exec(p, true, dargs) 68 dec, err := t.Exec("decode", p, true, dargs)
69 if err != nil { 69 if err != nil {
70 g.Panic(err) 70 g.Panic(err)
71 } 71 }
@@ -78,10 +78,8 @@ func offsetTest(r *xdelta.Runner, p *xdelta.Program, bufsize, offset, length int
78 t.CopyStreams(enc.Stdout, dec.Stdin) 78 t.CopyStreams(enc.Stdout, dec.Stdin)
79 t.CompareStreams(dec.Stdout, read, length) 79 t.CompareStreams(dec.Stdout, read, length)
80 80
81 // TODO: seems possible to use one WriteRstreams call to generate 81 xdelta.WriteRstreams(t, "encode", seed, offset, length, enc.Srcin, enc.Stdin)
82 // the source and target for both encoder and decoder. Why not? 82 xdelta.WriteRstreams(t, "decode", seed, offset, length, dec.Srcin, write)
83 xdelta.WriteRstreams(t, seed, offset, length, enc.Srcin, enc.Stdin)
84 xdelta.WriteRstreams(t, seed, offset, length, dec.Srcin, write)
85 83
86 t.Wait(g) 84 t.Wait(g)
87} 85}
@@ -96,7 +94,9 @@ func main() {
96 prog := &xdelta.Program{xdelta3} 94 prog := &xdelta.Program{xdelta3}
97 95
98 smokeTest(r, prog) 96 smokeTest(r, prog)
99 offsetTest(r, prog, 4 << 20, 3 << 20, 5 << 20) 97 for {
98 offsetTest(r, prog, 4 << 20, 3 << 20, 5 << 20)
99 }
100 100
101 //offsetTest(r, xdelta.NewTestGroup(), prog, 1 << 31, 1 << 32, 1 << 33) 101 //offsetTest(r, xdelta.NewTestGroup(), prog, 1 << 31, 1 << 32, 1 << 33)
102} 102}
diff --git a/xdelta3/go/src/xdelta/rstream.go b/xdelta3/go/src/xdelta/rstream.go
index 3f520d7..e31b0b0 100644
--- a/xdelta3/go/src/xdelta/rstream.go
+++ b/xdelta3/go/src/xdelta/rstream.go
@@ -10,17 +10,20 @@ const (
10 blocksize = 16380 10 blocksize = 16380
11) 11)
12 12
13func WriteRstreams(t *TestGroup, seed, offset, len int64, 13func WriteRstreams(t *TestGroup, desc string, seed, offset, len int64,
14 src, tgt io.WriteCloser) { 14 src, tgt io.WriteCloser) {
15 t.Go("src", func (g Goroutine) { 15 t.Go("src-write:"+desc, func (g Goroutine) {
16 go writeOne(g, seed, 0, len, src) 16 writeOne(g, seed, 0, len, src, false)
17 }) 17 })
18 t.Go("tgt", func (g Goroutine) { 18 t.Go("tgt-write:"+desc, func (g Goroutine) {
19 go writeOne(g, seed, offset, len, tgt) 19 writeOne(g, seed, offset, len, tgt, true)
20 }) 20 })
21} 21}
22 22
23func writeOne(g Goroutine, seed, offset, len int64, stream io.WriteCloser) { 23func writeOne(g Goroutine, seed, offset, len int64, stream io.WriteCloser, readall bool) {
24 if !readall {
25 g.OK()
26 }
24 if offset != 0 { 27 if offset != 0 {
25 // Fill with other random data until the offset 28 // Fill with other random data until the offset
26 if err := writeRand(rand.New(rand.NewSource(^seed)), offset, stream); err != nil { 29 if err := writeRand(rand.New(rand.NewSource(^seed)), offset, stream); err != nil {
diff --git a/xdelta3/go/src/xdelta/test.go b/xdelta3/go/src/xdelta/test.go
index d11ec29..ab4137c 100644
--- a/xdelta3/go/src/xdelta/test.go
+++ b/xdelta3/go/src/xdelta/test.go
@@ -49,6 +49,7 @@ func (t *TestGroup) Drain(f io.ReadCloser, desc string) <-chan []byte {
49 49
50func (t *TestGroup) Empty(f io.ReadCloser, desc string) { 50func (t *TestGroup) Empty(f io.ReadCloser, desc string) {
51 t.Go(desc, func (g Goroutine) { 51 t.Go(desc, func (g Goroutine) {
52 g.OK()
52 s := bufio.NewScanner(f) 53 s := bufio.NewScanner(f)
53 for s.Scan() { 54 for s.Scan() {
54 os.Stderr.Write([]byte(fmt.Sprint(desc, ": ", s.Text(), "\n"))) 55 os.Stderr.Write([]byte(fmt.Sprint(desc, ": ", s.Text(), "\n")))
@@ -59,7 +60,6 @@ func (t *TestGroup) Empty(f io.ReadCloser, desc string) {
59 fmt.Println("Empty", desc, err) 60 fmt.Println("Empty", desc, err)
60 g.Panic(err) 61 g.Panic(err)
61 } 62 }
62 g.OK()
63 }) 63 })
64} 64}
65 65
@@ -126,7 +126,7 @@ func (t *TestGroup) CompareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length in
126 }) 126 })
127} 127}
128 128
129func (t *TestGroup) Exec(p *Program, srcfifo bool, flags []string) (*Run, error) { 129func (t *TestGroup) Exec(desc string, p *Program, srcfifo bool, flags []string) (*Run, error) {
130 var err error 130 var err error
131 run := &Run{} 131 run := &Run{}
132 args := []string{p.Path} 132 args := []string{p.Path}
@@ -162,7 +162,7 @@ func (t *TestGroup) Exec(p *Program, srcfifo bool, flags []string) (*Run, error)
162 if serr := run.Cmd.Start(); serr != nil { 162 if serr := run.Cmd.Start(); serr != nil {
163 return nil, serr 163 return nil, serr
164 } 164 }
165 t.Go("exec-wait", func (g Goroutine) { 165 t.Go("exec-wait:" + desc, func (g Goroutine) {
166 if err := run.Cmd.Wait(); err != nil { 166 if err := run.Cmd.Wait(); err != nil {
167 g.Panic(err) 167 g.Panic(err)
168 } 168 }
diff --git a/xdelta3/go/src/xdelta/tgroup.go b/xdelta3/go/src/xdelta/tgroup.go
index bb34258..b64827c 100644
--- a/xdelta3/go/src/xdelta/tgroup.go
+++ b/xdelta3/go/src/xdelta/tgroup.go
@@ -10,6 +10,7 @@ type TestGroup struct {
10 *Runner 10 *Runner
11 sync.Mutex 11 sync.Mutex
12 running []Goroutine 12 running []Goroutine
13 errors []error
13 waitChan <-chan bool 14 waitChan <-chan bool
14} 15}
15 16
@@ -31,13 +32,19 @@ func (g *Goroutine) String() string {
31} 32}
32 33
33func (g *Goroutine) OK() { 34func (g *Goroutine) OK() {
34 g.errChan <- nil 35 if g.errChan != nil {
35 _ = <- g.errChan 36 g.errChan <- nil
37 _ = <- g.errChan
38 g.errChan = nil
39 }
36} 40}
37 41
38func (g *Goroutine) Panic(err error) { 42func (g *Goroutine) Panic(err error) {
39 g.errChan <- err 43 fmt.Print("[", g.name, "] ", err, "\n")
40 _ = <- g.errChan 44 if g.errChan != nil {
45 g.errChan <- err
46 _ = <- g.errChan
47 }
41 select {} 48 select {}
42} 49}
43 50
@@ -52,15 +59,24 @@ func (t *TestGroup) Go(name string, f func(Goroutine)) {
52func (t *TestGroup) Wait(g Goroutine) { 59func (t *TestGroup) Wait(g Goroutine) {
53 g.OK() 60 g.OK()
54 t.Lock() 61 t.Lock()
55 t.waitChan = nil
56 wc := t.waitChan 62 wc := t.waitChan
63 t.waitChan = nil
57 t.Unlock() 64 t.Unlock()
58 _ = <- wc 65 _ = <- wc
66 t.Lock()
67 errs := t.errors
68 t.Unlock()
69 if len(errs) != 0 {
70 panic(fmt.Sprintln(len(errs), "errors in test"))
71 }
59} 72}
60 73
61func waitAll(t *TestGroup, wc chan bool) { 74func waitAll(t *TestGroup, wc chan bool) {
62 for { 75 for {
63 t.Lock() 76 t.Lock()
77 // for _, x := range t.running {
78 // fmt.Println("RUNNING", x.name)
79 // }
64 if len(t.running) == 0 { 80 if len(t.running) == 0 {
65 t.Unlock() 81 t.Unlock()
66 break 82 break
@@ -69,19 +85,18 @@ func waitAll(t *TestGroup, wc chan bool) {
69 t.running = t.running[1:] 85 t.running = t.running[1:]
70 t.Unlock() 86 t.Unlock()
71 87
72 timeout := make(chan bool, 1) 88 timeout := time.After(time.Second)
73 go func() { 89 // fmt.Println("Waiting on", runner)
74 time.Sleep(1 * time.Second)
75 timeout <- true
76 }()
77 fmt.Println("Waiting on", runner)
78 select { 90 select {
79 case err := <- runner.errChan: 91 case err := <- runner.errChan:
80 runner.errChan <- err 92 runner.errChan <- err
81 if err != nil { 93 if err != nil {
82 fmt.Println("[G]", runner, err) 94 // fmt.Println("[G]", runner, err)
95 t.Lock()
96 t.errors = append(t.errors, err)
97 t.Unlock()
83 } else { 98 } else {
84 fmt.Println("[G]", runner, "OK") 99 // fmt.Println("[G]", runner, "OK")
85 } 100 }
86 case <- timeout: 101 case <- timeout:
87 t.Lock() 102 t.Lock()