diff options
Diffstat (limited to 'xdelta3')
-rw-r--r-- | xdelta3/go/src/regtest.go | 10 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/rstream.go | 12 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/test.go | 21 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/tgroup.go | 119 |
4 files changed, 65 insertions, 97 deletions
diff --git a/xdelta3/go/src/regtest.go b/xdelta3/go/src/regtest.go index 194761a..adb4ae4 100644 --- a/xdelta3/go/src/regtest.go +++ b/xdelta3/go/src/regtest.go | |||
@@ -53,7 +53,6 @@ func smokeTest(r *xdelta.Runner, p *xdelta.Program) { | |||
53 | g.Panic(errors.New("It's not working!!!")) | 53 | g.Panic(errors.New("It's not working!!!")) |
54 | } | 54 | } |
55 | t.Wait(g, enc, dec) | 55 | t.Wait(g, enc, dec) |
56 | fmt.Println("Smoketest pass") | ||
57 | } | 56 | } |
58 | 57 | ||
59 | func offsetTest(r *xdelta.Runner, p *xdelta.Program, bufsize, offset, length int64) { | 58 | func offsetTest(r *xdelta.Runner, p *xdelta.Program, bufsize, offset, length int64) { |
@@ -64,13 +63,13 @@ func offsetTest(r *xdelta.Runner, p *xdelta.Program, bufsize, offset, length int | |||
64 | // (c) open on a fifo blocks until a reader opens | 63 | // (c) open on a fifo blocks until a reader opens |
65 | // (d) sub-process Wait can invalidate busy file descriptors | 64 | // (d) sub-process Wait can invalidate busy file descriptors |
66 | t, g := xdelta.NewTestGroup(r) | 65 | t, g := xdelta.NewTestGroup(r) |
67 | eargs := []string{"-e", "-0", fmt.Sprint("-B", bufsize), "-vvvvvvv", fmt.Sprint("-W", winsize)} | 66 | eargs := []string{"-e", "-0", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)} |
68 | enc, err := t.Exec("encode", p, true, eargs) | 67 | enc, err := t.Exec("encode", p, true, eargs) |
69 | if err != nil { | 68 | if err != nil { |
70 | g.Panic(err) | 69 | g.Panic(err) |
71 | } | 70 | } |
72 | 71 | ||
73 | dargs := []string{"-d", fmt.Sprint("-B", bufsize), "-vvvvvvv", fmt.Sprint("-W", winsize)} | 72 | dargs := []string{"-d", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)} |
74 | dec, err := t.Exec("decode", p, true, dargs) | 73 | dec, err := t.Exec("decode", p, true, dargs) |
75 | if err != nil { | 74 | if err != nil { |
76 | g.Panic(err) | 75 | g.Panic(err) |
@@ -101,8 +100,11 @@ func main() { | |||
101 | 100 | ||
102 | prog := &xdelta.Program{xdelta3} | 101 | prog := &xdelta.Program{xdelta3} |
103 | 102 | ||
104 | //smokeTest(r, prog) | 103 | smokeTest(r, prog) |
104 | fmt.Println("Smoke-test pass") | ||
105 | |||
105 | offsetTest(r, prog, 4 << 20, 3 << 20, 5 << 20) | 106 | offsetTest(r, prog, 4 << 20, 3 << 20, 5 << 20) |
107 | fmt.Println("Offset-test pass") | ||
106 | 108 | ||
107 | //offsetTest(r, xdelta.NewTestGroup(), prog, 1 << 31, 1 << 32, 1 << 33) | 109 | //offsetTest(r, xdelta.NewTestGroup(), prog, 1 << 31, 1 << 32, 1 << 33) |
108 | } | 110 | } |
diff --git a/xdelta3/go/src/xdelta/rstream.go b/xdelta3/go/src/xdelta/rstream.go index 7d205c6..9481f22 100644 --- a/xdelta3/go/src/xdelta/rstream.go +++ b/xdelta3/go/src/xdelta/rstream.go | |||
@@ -13,15 +13,15 @@ const ( | |||
13 | 13 | ||
14 | func (t *TestGroup) WriteRstreams(desc string, seed, offset, len int64, | 14 | func (t *TestGroup) WriteRstreams(desc string, seed, offset, len int64, |
15 | src, tgt io.WriteCloser) { | 15 | src, tgt io.WriteCloser) { |
16 | t.Go("src-write:"+desc, func (g Goroutine) { | 16 | t.Go("src-write:"+desc, func (g *Goroutine) { |
17 | writeOne(g, seed, 0, len, src, false) | 17 | writeOne(g, seed, 0, len, src, false) |
18 | }) | 18 | }) |
19 | t.Go("tgt-write:"+desc, func (g Goroutine) { | 19 | t.Go("tgt-write:"+desc, func (g *Goroutine) { |
20 | writeOne(g, seed, offset, len, tgt, true) | 20 | writeOne(g, seed, offset, len, tgt, true) |
21 | }) | 21 | }) |
22 | } | 22 | } |
23 | 23 | ||
24 | func writeOne(g Goroutine, seed, offset, len int64, stream io.WriteCloser, readall bool) { | 24 | func writeOne(g *Goroutine, seed, offset, len int64, stream io.WriteCloser, readall bool) { |
25 | if !readall { | 25 | if !readall { |
26 | // Allow the source-read to fail or block until the process terminates. | 26 | // Allow the source-read to fail or block until the process terminates. |
27 | // This behavior is reserved for the decoder, which is not required to | 27 | // This behavior is reserved for the decoder, which is not required to |
@@ -40,27 +40,23 @@ func writeOne(g Goroutine, seed, offset, len int64, stream io.WriteCloser, reada | |||
40 | len - offset, stream); err != nil { | 40 | len - offset, stream); err != nil { |
41 | g.Panic(err) | 41 | g.Panic(err) |
42 | } | 42 | } |
43 | fmt.Println(g, "closing", len) | ||
44 | if err := stream.Close(); err != nil { | 43 | if err := stream.Close(); err != nil { |
45 | g.Panic(err) | 44 | g.Panic(err) |
46 | } | 45 | } |
47 | g.OK() | 46 | g.OK() |
48 | } | 47 | } |
49 | 48 | ||
50 | func writeRand(g Goroutine, r *rand.Rand, len int64, s io.Writer) error { | 49 | func writeRand(g *Goroutine, r *rand.Rand, len int64, s io.Writer) error { |
51 | blk := make([]byte, blocksize) | 50 | blk := make([]byte, blocksize) |
52 | fmt.Println(g, "rstream", len) | ||
53 | for len > 0 { | 51 | for len > 0 { |
54 | fillRand(r, blk) | 52 | fillRand(r, blk) |
55 | c := blocksize | 53 | c := blocksize |
56 | if len < blocksize { | 54 | if len < blocksize { |
57 | c = int(len) | 55 | c = int(len) |
58 | } | 56 | } |
59 | fmt.Println(g, "writing...", c, s) | ||
60 | if _, err := s.Write(blk[0:c]); err != nil { | 57 | if _, err := s.Write(blk[0:c]); err != nil { |
61 | return err | 58 | return err |
62 | } | 59 | } |
63 | fmt.Println(g, "...written", c) | ||
64 | len -= int64(c) | 60 | len -= int64(c) |
65 | } | 61 | } |
66 | return nil | 62 | return nil |
diff --git a/xdelta3/go/src/xdelta/test.go b/xdelta3/go/src/xdelta/test.go index 427e4c7..00f3dd7 100644 --- a/xdelta3/go/src/xdelta/test.go +++ b/xdelta3/go/src/xdelta/test.go | |||
@@ -35,9 +35,8 @@ type Run struct { | |||
35 | 35 | ||
36 | func (t *TestGroup) Drain(f io.ReadCloser, desc string) <-chan []byte { | 36 | func (t *TestGroup) Drain(f io.ReadCloser, desc string) <-chan []byte { |
37 | c := make(chan []byte) | 37 | c := make(chan []byte) |
38 | t.Go(desc, func(g Goroutine) { | 38 | t.Go(desc, func(g *Goroutine) { |
39 | if b, err := ioutil.ReadAll(f); err != nil { | 39 | if b, err := ioutil.ReadAll(f); err != nil { |
40 | fmt.Println("Drain", err) | ||
41 | g.Panic(err) | 40 | g.Panic(err) |
42 | } else { | 41 | } else { |
43 | c <- b | 42 | c <- b |
@@ -47,8 +46,8 @@ func (t *TestGroup) Drain(f io.ReadCloser, desc string) <-chan []byte { | |||
47 | return c | 46 | return c |
48 | } | 47 | } |
49 | 48 | ||
50 | func (t *TestGroup) Empty(f io.ReadCloser, desc string) Goroutine { | 49 | func (t *TestGroup) Empty(f io.ReadCloser, desc string) *Goroutine { |
51 | return t.Go("empty:"+desc, func (g Goroutine) { | 50 | return t.Go("empty:"+desc, func (g *Goroutine) { |
52 | s := bufio.NewScanner(f) | 51 | s := bufio.NewScanner(f) |
53 | for s.Scan() { | 52 | for s.Scan() { |
54 | os.Stderr.Write([]byte(fmt.Sprint(desc, ": ", s.Text(), "\n"))) | 53 | os.Stderr.Write([]byte(fmt.Sprint(desc, ": ", s.Text(), "\n"))) |
@@ -64,18 +63,16 @@ func (t *TestGroup) Empty(f io.ReadCloser, desc string) Goroutine { | |||
64 | 63 | ||
65 | func TestWrite(what string, f io.WriteCloser, b []byte) error { | 64 | func TestWrite(what string, f io.WriteCloser, b []byte) error { |
66 | if _, err := f.Write(b); err != nil { | 65 | if _, err := f.Write(b); err != nil { |
67 | fmt.Println("Write", err) | ||
68 | return errors.New(fmt.Sprint(what, ":", err)) | 66 | return errors.New(fmt.Sprint(what, ":", err)) |
69 | } | 67 | } |
70 | if err := f.Close(); err != nil { | 68 | if err := f.Close(); err != nil { |
71 | fmt.Println("Close", err) | ||
72 | return errors.New(fmt.Sprint(what, ":", err)) | 69 | return errors.New(fmt.Sprint(what, ":", err)) |
73 | } | 70 | } |
74 | return nil | 71 | return nil |
75 | } | 72 | } |
76 | 73 | ||
77 | func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser) Goroutine { | 74 | func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser) *Goroutine { |
78 | return t.Go("copy", func(g Goroutine) { | 75 | return t.Go("copy", func(g *Goroutine) { |
79 | _, err := io.Copy(w, r) | 76 | _, err := io.Copy(w, r) |
80 | if err != nil { | 77 | if err != nil { |
81 | g.Panic(err) | 78 | g.Panic(err) |
@@ -92,8 +89,8 @@ func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser) Goroutine { | |||
92 | }) | 89 | }) |
93 | } | 90 | } |
94 | 91 | ||
95 | func (t *TestGroup) CompareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length int64) Goroutine { | 92 | func (t *TestGroup) CompareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length int64) *Goroutine { |
96 | return t.Go("compare", func(g Goroutine) { | 93 | return t.Go("compare", func(g *Goroutine) { |
97 | b1 := make([]byte, blocksize) | 94 | b1 := make([]byte, blocksize) |
98 | b2 := make([]byte, blocksize) | 95 | b2 := make([]byte, blocksize) |
99 | var idx int64 | 96 | var idx int64 |
@@ -103,11 +100,9 @@ func (t *TestGroup) CompareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length in | |||
103 | c = int(length) | 100 | c = int(length) |
104 | } | 101 | } |
105 | if _, err := io.ReadFull(r1, b1[0:c]); err != nil { | 102 | if _, err := io.ReadFull(r1, b1[0:c]); err != nil { |
106 | fmt.Println("ReadFull1", err) | ||
107 | g.Panic(err) | 103 | g.Panic(err) |
108 | } | 104 | } |
109 | if _, err := io.ReadFull(r2, b2[0:c]); err != nil { | 105 | if _, err := io.ReadFull(r2, b2[0:c]); err != nil { |
110 | fmt.Println("ReadFull2", err) | ||
111 | g.Panic(err) | 106 | g.Panic(err) |
112 | } | 107 | } |
113 | if bytes.Compare(b1[0:c], b2[0:c]) != 0 { | 108 | if bytes.Compare(b1[0:c], b2[0:c]) != 0 { |
@@ -166,9 +161,7 @@ func (r *Run) Wait() error { | |||
166 | } | 161 | } |
167 | 162 | ||
168 | func writeFifo(srcfile string, read io.Reader) error { | 163 | func writeFifo(srcfile string, read io.Reader) error { |
169 | fmt.Println("About to open", srcfile) | ||
170 | fifo, err := os.OpenFile(srcfile, os.O_WRONLY, 0600) | 164 | fifo, err := os.OpenFile(srcfile, os.O_WRONLY, 0600) |
171 | fmt.Println("Opened!!!", srcfile) | ||
172 | if err != nil { | 165 | if err != nil { |
173 | fifo.Close() | 166 | fifo.Close() |
174 | return err | 167 | return err |
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 | |||
3 | import ( | 3 | import ( |
4 | "fmt" | 4 | "fmt" |
5 | "sync" | 5 | "sync" |
6 | "time" | ||
7 | ) | 6 | ) |
8 | 7 | ||
9 | type TestGroup struct { | 8 | type 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 | ||
17 | type Goroutine struct { | 17 | type Goroutine struct { |
18 | *TestGroup | ||
18 | name string | 19 | name string |
19 | errChan chan error | 20 | done bool |
20 | } | 21 | } |
21 | 22 | ||
22 | func NewTestGroup(r *Runner) (*TestGroup, Goroutine) { | 23 | func 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 | ||
30 | func (g *Goroutine) String() string { | 31 | func (g *Goroutine) String() string { |
31 | return fmt.Sprint("[", g.name, "]") | 32 | return fmt.Sprint("[", g.name, "]") |
32 | } | 33 | } |
33 | 34 | ||
34 | func (g *Goroutine) OK() { | 35 | func (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 | ||
56 | func (g *Goroutine) OK() { | ||
57 | g.finish(nil) | ||
58 | } | ||
59 | |||
43 | func (g *Goroutine) Panic(err error) { | 60 | func (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 | ||
52 | func (t *TestGroup) Go(name string, f func(Goroutine)) Goroutine { | 65 | func (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 | ||
61 | func (t *TestGroup) Wait(self Goroutine, procs... *Run) { | 75 | func (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) | |
84 | func 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 | |||