diff options
Diffstat (limited to 'xdelta3')
-rw-r--r-- | xdelta3/go/src/regtest.go | 171 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/test.go | 21 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/tgroup.go | 11 |
3 files changed, 155 insertions, 48 deletions
diff --git a/xdelta3/go/src/regtest.go b/xdelta3/go/src/regtest.go index d762235..233e005 100644 --- a/xdelta3/go/src/regtest.go +++ b/xdelta3/go/src/regtest.go | |||
@@ -1,72 +1,158 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "errors" | ||
5 | "fmt" | 4 | "fmt" |
6 | "io" | 5 | "io" |
6 | "os" | ||
7 | 7 | ||
8 | "xdelta" | 8 | "xdelta" |
9 | ) | 9 | ) |
10 | 10 | ||
11 | const ( | 11 | const ( |
12 | blocksize = 1<<16 | 12 | xdataset = "/Users/jmacd/src/testdata" |
13 | winsize = 1<<22 | 13 | xcompare = "/Users/jmacd/src/xdelta3-3.0.10/xdelta3" |
14 | xdelta3 = "/Users/jmacd/src/xdelta-devel/xdelta3/xdelta3" | 14 | xdelta3 = "/Users/jmacd/src/xdelta-devel/xdelta3/xdelta3" |
15 | seed = 1422253499919909358 | 15 | seed = 1422253499919909358 |
16 | ) | 16 | ) |
17 | 17 | ||
18 | func smokeTest(t *xdelta.TestGroup, p *xdelta.Program) { | 18 | type Config struct { |
19 | g := t.Main() | 19 | srcbuf_size int64 |
20 | window_size int64 | ||
21 | blocksize int | ||
22 | } | ||
23 | |||
24 | func NewC() Config { | ||
25 | // TODO make these (and above) flags | ||
26 | return Config{1<<26, 1<<22, 1<<16} | ||
27 | } | ||
28 | |||
29 | func (c Config) smokeTest(t *xdelta.TestGroup, p xdelta.Program) { | ||
20 | target := "Hello world!" | 30 | target := "Hello world!" |
21 | source := "Hello world, nice to meet you!" | 31 | source := "Hello world, nice to meet you!" |
22 | 32 | ||
23 | enc, err := t.Exec("encode", p, true, []string{"-evv"}) | 33 | enc, err := t.Exec("encode", p, true, []string{"-e"}) |
34 | if err != nil { | ||
35 | t.Panic(err) | ||
36 | } | ||
37 | dec, err := t.Exec("decode", p, true, []string{"-d"}) | ||
24 | if err != nil { | 38 | if err != nil { |
25 | g.Panic(err) | 39 | t.Panic(err) |
26 | } | 40 | } |
41 | |||
27 | encodeout := t.Drain(enc.Stdout, "encode.stdout") | 42 | encodeout := t.Drain(enc.Stdout, "encode.stdout") |
43 | decodeout := t.Drain(dec.Stdout, "decode.stdout") | ||
44 | |||
28 | t.Empty(enc.Stderr, "encode") | 45 | t.Empty(enc.Stderr, "encode") |
46 | t.Empty(dec.Stderr, "decode") | ||
29 | 47 | ||
30 | if err := xdelta.TestWrite("encode.stdin", enc.Stdin, []byte(target)); err != nil { | 48 | t.TestWrite("encode.stdin", enc.Stdin, []byte(target)) |
31 | g.Panic(err) | 49 | t.TestWrite("encode.srcin", enc.Srcin, []byte(source)) |
32 | } | 50 | |
33 | if err := xdelta.TestWrite("encode.srcin", enc.Srcin, []byte(source)); err != nil { | 51 | t.TestWrite("decode.stdin", dec.Stdin, <-encodeout) |
34 | g.Panic(err) | 52 | t.TestWrite("decode.srcin", dec.Srcin, []byte(source)) |
53 | |||
54 | if do := string(<-decodeout); do != target { | ||
55 | t.Panic(fmt.Errorf("It's not working! %s\n!=\n%s\n", do, target)) | ||
35 | } | 56 | } |
57 | t.Wait(enc, dec) | ||
58 | } | ||
59 | |||
60 | type PairTest struct { | ||
61 | // Input | ||
62 | Config | ||
63 | program xdelta.Program | ||
64 | source, target string | ||
36 | 65 | ||
37 | dec, err := t.Exec("decode", p, true, []string{"-dvv"}) | 66 | // Output |
67 | encoded int64 | ||
68 | } | ||
69 | |||
70 | // P is the test program, Q is the reference version. | ||
71 | func (cfg Config) datasetTest(t *xdelta.TestGroup, p, q xdelta.Program) { | ||
72 | dir, err := os.Open(xdataset) | ||
73 | if err != nil { | ||
74 | t.Panic(err) | ||
75 | } | ||
76 | dents, err := dir.Readdir(-1) | ||
38 | if err != nil { | 77 | if err != nil { |
39 | g.Panic(err) | 78 | t.Panic(err) |
40 | } | 79 | } |
80 | paths := make([]string, len(dents)) | ||
81 | var total int64 | ||
82 | for i, d := range dents { | ||
83 | if !d.Mode().IsRegular() { | ||
84 | continue | ||
85 | } | ||
86 | paths[i] = fmt.Sprint(xdataset, "/", d.Name()) | ||
87 | total += d.Size() | ||
88 | } | ||
89 | meansize := total / int64(len(dents)) | ||
90 | for _, in1 := range paths { | ||
91 | for _, in2 := range paths { | ||
92 | if in1 == in2 { continue } | ||
93 | |||
94 | largest := uint(20) | ||
95 | for ; largest <= 31 && 1<<largest < meansize; largest++ {} | ||
96 | |||
97 | // 1/8, 1/4, 1/2, and 1/1 of the power-of-2 rounded-up mean size | ||
98 | for b := largest /* - 3*/; b <= largest; b++ { | ||
99 | c1 := cfg | ||
100 | c1.srcbuf_size = 1<<b | ||
101 | ptest := &PairTest{c1, p, in1, in2, -1} | ||
102 | ptest.datasetPairTest(t, 1<<b); | ||
103 | qtest := &PairTest{c1, q, in1, in2, -1} | ||
104 | qtest.datasetPairTest(t, 1<<b) | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | } | ||
41 | 109 | ||
42 | decodeout := t.Drain(dec.Stdout, "decode.stdout") | 110 | func (pt *PairTest) datasetPairTest(t *xdelta.TestGroup, meanSize int64) { |
43 | t.Empty(dec.Stderr, "decode") | 111 | cfg := pt.Config |
112 | eargs := []string{"-e", fmt.Sprint("-B", cfg.srcbuf_size), "-q", | ||
113 | fmt.Sprint("-W", cfg.window_size), "-s", pt.source, pt.target} | ||
114 | enc, err := t.Exec("encode", pt.program, false, eargs) | ||
115 | if err != nil { | ||
116 | t.Panic(err) | ||
117 | } | ||
44 | 118 | ||
45 | if err := xdelta.TestWrite("decode.stdin", dec.Stdin, <-encodeout); err != nil { | 119 | dargs := []string{"-dc", fmt.Sprint("-B", cfg.srcbuf_size), "-q", |
46 | g.Panic(err) | 120 | fmt.Sprint("-W", cfg.window_size), "-s", pt.source} |
121 | dec, err := t.Exec("decode", pt.program, false, dargs) | ||
122 | if err != nil { | ||
123 | t.Panic(err) | ||
47 | } | 124 | } |
48 | if err := xdelta.TestWrite("decode.srcin", dec.Srcin, []byte(source)); err != nil { | 125 | tgt_check, err := os.Open(pt.target) |
49 | g.Panic(err) | 126 | if err != nil { |
127 | t.Panic(err) | ||
50 | } | 128 | } |
51 | decoded := string(<-decodeout) | 129 | tgt_info, err := tgt_check.Stat() |
52 | if decoded != target { | 130 | if err != nil { |
53 | g.Panic(errors.New("It's not working!!!")) | 131 | t.Panic(err) |
54 | } | 132 | } |
55 | t.Wait(g, enc, dec) | 133 | t.Empty(enc.Stderr, "encode") |
134 | t.Empty(dec.Stderr, "decode") | ||
135 | t.CopyStreams(enc.Stdout, dec.Stdin, &pt.encoded) | ||
136 | t.CompareStreams(dec.Stdout, tgt_check, tgt_info.Size()) | ||
137 | |||
138 | t.Wait(enc, dec) | ||
139 | |||
140 | fmt.Println("PairTest", pt, "success") | ||
56 | } | 141 | } |
57 | 142 | ||
58 | func offsetTest(t *xdelta.TestGroup, p *xdelta.Program, offset, bufsize, length int64) { | 143 | func (cfg Config) offsetTest(t *xdelta.TestGroup, p xdelta.Program, offset, length int64) { |
59 | g := t.Main() | 144 | eargs := []string{"-e", "-0", fmt.Sprint("-B", cfg.srcbuf_size), "-q", |
60 | eargs := []string{"-e", "-0", fmt.Sprint("-B", bufsize), "-q", fmt.Sprint("-W", winsize)} | 145 | fmt.Sprint("-W", cfg.window_size)} |
61 | enc, err := t.Exec("encode", p, true, eargs) | 146 | enc, err := t.Exec("encode", p, true, eargs) |
62 | if err != nil { | 147 | if err != nil { |
63 | g.Panic(err) | 148 | t.Panic(err) |
64 | } | 149 | } |
65 | 150 | ||
66 | dargs := []string{"-d", fmt.Sprint("-B", bufsize), "-q", fmt.Sprint("-W", winsize)} | 151 | dargs := []string{"-d", fmt.Sprint("-B", cfg.srcbuf_size), "-q", |
152 | fmt.Sprint("-W", cfg.window_size)} | ||
67 | dec, err := t.Exec("decode", p, true, dargs) | 153 | dec, err := t.Exec("decode", p, true, dargs) |
68 | if err != nil { | 154 | if err != nil { |
69 | g.Panic(err) | 155 | t.Panic(err) |
70 | } | 156 | } |
71 | 157 | ||
72 | // The pipe used to read the decoder output and compare | 158 | // The pipe used to read the decoder output and compare |
@@ -85,9 +171,9 @@ func offsetTest(t *xdelta.TestGroup, p *xdelta.Program, offset, bufsize, length | |||
85 | // generates the input and output twice. | 171 | // generates the input and output twice. |
86 | t.WriteRstreams("encode", seed, offset, length, enc.Srcin, enc.Stdin) | 172 | t.WriteRstreams("encode", seed, offset, length, enc.Srcin, enc.Stdin) |
87 | t.WriteRstreams("decode", seed, offset, length, dec.Srcin, write) | 173 | t.WriteRstreams("decode", seed, offset, length, dec.Srcin, write) |
88 | t.Wait(g, enc, dec) | 174 | t.Wait(enc, dec) |
89 | 175 | ||
90 | expect := bufsize - offset | 176 | expect := cfg.srcbuf_size - offset |
91 | if float64(encoded_size) < (0.95 * float64(expect)) || | 177 | if float64(encoded_size) < (0.95 * float64(expect)) || |
92 | float64(encoded_size) > (1.05 * float64(expect)) { | 178 | float64(encoded_size) > (1.05 * float64(expect)) { |
93 | t.Fail("encoded size should be ~=", expect, ", actual ", encoded_size) | 179 | t.Fail("encoded size should be ~=", expect, ", actual ", encoded_size) |
@@ -101,12 +187,25 @@ func main() { | |||
101 | } | 187 | } |
102 | defer r.Cleanup() | 188 | defer r.Cleanup() |
103 | 189 | ||
104 | prog := &xdelta.Program{xdelta3} | 190 | cfg := NewC() |
105 | 191 | ||
106 | r.RunTest("smoketest", func(tg *xdelta.TestGroup) { smokeTest(tg, prog) }) | 192 | prog := xdelta.Program{xdelta3} |
107 | 193 | ||
108 | for i := uint(20); i <= 30; i += 1 { | 194 | r.RunTest("smoketest", func(t *xdelta.TestGroup) { cfg.smokeTest(t, prog) }) |
195 | |||
196 | comp := xdelta.Program{xcompare} | ||
197 | |||
198 | r.RunTest("dataset", func(t *xdelta.TestGroup) { cfg.datasetTest(t, prog, comp) }) | ||
199 | |||
200 | for i := uint(19); i <= 30; i += 1 { | ||
201 | // The arguments to offsetTest are offset, source | ||
202 | // window size, and file size. The source window size | ||
203 | // is (2 << i) and (in the 3.0x release branch) is | ||
204 | // limited to 2^31, so the the greatest value of i is | ||
205 | // 30. | ||
206 | cfg.srcbuf_size = 2 << i | ||
109 | r.RunTest(fmt.Sprint("offset", i), func(t *xdelta.TestGroup) { | 207 | r.RunTest(fmt.Sprint("offset", i), func(t *xdelta.TestGroup) { |
110 | offsetTest(t, prog, 1 << i, 2 << i, 3 << i) }) | 208 | cfg.offsetTest(t, prog, 1 << i, 3 << i) }) |
111 | } | 209 | } |
210 | |||
112 | } | 211 | } |
diff --git a/xdelta3/go/src/xdelta/test.go b/xdelta3/go/src/xdelta/test.go index bab66f3..7210698 100644 --- a/xdelta3/go/src/xdelta/test.go +++ b/xdelta3/go/src/xdelta/test.go | |||
@@ -47,14 +47,16 @@ func (t *TestGroup) Empty(f io.ReadCloser, desc string) *Goroutine { | |||
47 | }) | 47 | }) |
48 | } | 48 | } |
49 | 49 | ||
50 | func TestWrite(what string, f io.WriteCloser, b []byte) error { | 50 | func (t *TestGroup) TestWrite(what string, f io.WriteCloser, b []byte) *Goroutine { |
51 | if _, err := f.Write(b); err != nil { | 51 | return t.Go("write", func(g *Goroutine) { |
52 | return errors.New(fmt.Sprint(what, ":", err)) | 52 | if _, err := f.Write(b); err != nil { |
53 | } | 53 | g.Panic(err) |
54 | if err := f.Close(); err != nil { | 54 | } |
55 | return errors.New(fmt.Sprint(what, ":", err)) | 55 | if err := f.Close(); err != nil { |
56 | } | 56 | g.Panic(err) |
57 | return nil | 57 | } |
58 | g.OK() | ||
59 | }) | ||
58 | } | 60 | } |
59 | 61 | ||
60 | func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser, written *int64) *Goroutine { | 62 | func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser, written *int64) *Goroutine { |
@@ -104,7 +106,7 @@ func (t *TestGroup) CompareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length in | |||
104 | }) | 106 | }) |
105 | } | 107 | } |
106 | 108 | ||
107 | func (t *TestGroup) Exec(desc string, p *Program, srcfifo bool, flags []string) (*Run, error) { | 109 | func (t *TestGroup) Exec(desc string, p Program, srcfifo bool, flags []string) (*Run, error) { |
108 | var err error | 110 | var err error |
109 | run := &Run{} | 111 | run := &Run{} |
110 | args := []string{p.Path} | 112 | args := []string{p.Path} |
@@ -133,7 +135,6 @@ func (t *TestGroup) Exec(desc string, p *Program, srcfifo bool, flags []string) | |||
133 | run.Cmd.Path = p.Path | 135 | run.Cmd.Path = p.Path |
134 | run.Cmd.Args = append(args, flags...) | 136 | run.Cmd.Args = append(args, flags...) |
135 | run.Cmd.Dir = t.Runner.Testdir | 137 | run.Cmd.Dir = t.Runner.Testdir |
136 | fmt.Println("Start command", run.Cmd.Args) | ||
137 | if serr := run.Cmd.Start(); serr != nil { | 138 | if serr := run.Cmd.Start(); serr != nil { |
138 | return nil, serr | 139 | return nil, serr |
139 | } | 140 | } |
diff --git a/xdelta3/go/src/xdelta/tgroup.go b/xdelta3/go/src/xdelta/tgroup.go index 0a3b41b..b1b04ec 100644 --- a/xdelta3/go/src/xdelta/tgroup.go +++ b/xdelta3/go/src/xdelta/tgroup.go | |||
@@ -29,6 +29,11 @@ func (g *Goroutine) String() string { | |||
29 | func (g *Goroutine) finish(err error) { | 29 | func (g *Goroutine) finish(err error) { |
30 | wait := false | 30 | wait := false |
31 | tg := g.TestGroup | 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 | } | ||
32 | tg.Lock() | 37 | tg.Lock() |
33 | if g.done { | 38 | if g.done { |
34 | if err != nil { | 39 | if err != nil { |
@@ -58,6 +63,8 @@ func (g *Goroutine) Panic(err error) { | |||
58 | 63 | ||
59 | func (t *TestGroup) Main() *Goroutine { return t.main } | 64 | func (t *TestGroup) Main() *Goroutine { return t.main } |
60 | 65 | ||
66 | func (t *TestGroup) Panic(err error) { t.Main().Panic(err) } | ||
67 | |||
61 | func (t *TestGroup) Go(name string, f func(*Goroutine)) *Goroutine { | 68 | func (t *TestGroup) Go(name string, f func(*Goroutine)) *Goroutine { |
62 | g := &Goroutine{t, name, false} | 69 | g := &Goroutine{t, name, false} |
63 | t.Lock() | 70 | t.Lock() |
@@ -68,8 +75,8 @@ func (t *TestGroup) Go(name string, f func(*Goroutine)) *Goroutine { | |||
68 | return g | 75 | return g |
69 | } | 76 | } |
70 | 77 | ||
71 | func (t *TestGroup) Wait(self *Goroutine, procs... *Run) { | 78 | func (t *TestGroup) Wait(procs... *Run) { |
72 | self.OK() | 79 | t.Main().OK() |
73 | t.WaitGroup.Wait() | 80 | t.WaitGroup.Wait() |
74 | for _, p := range procs { | 81 | for _, p := range procs { |
75 | if err := p.Wait(); err != nil { | 82 | if err := p.Wait(); err != nil { |