summaryrefslogtreecommitdiff
path: root/xdelta3
diff options
context:
space:
mode:
Diffstat (limited to 'xdelta3')
-rw-r--r--xdelta3/go/src/regtest.go171
-rw-r--r--xdelta3/go/src/xdelta/test.go21
-rw-r--r--xdelta3/go/src/xdelta/tgroup.go11
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 @@
1package main 1package main
2 2
3import ( 3import (
4 "errors"
5 "fmt" 4 "fmt"
6 "io" 5 "io"
6 "os"
7 7
8 "xdelta" 8 "xdelta"
9) 9)
10 10
11const ( 11const (
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
18func smokeTest(t *xdelta.TestGroup, p *xdelta.Program) { 18type Config struct {
19 g := t.Main() 19 srcbuf_size int64
20 window_size int64
21 blocksize int
22}
23
24func NewC() Config {
25 // TODO make these (and above) flags
26 return Config{1<<26, 1<<22, 1<<16}
27}
28
29func (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
60type 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.
71func (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") 110func (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
58func offsetTest(t *xdelta.TestGroup, p *xdelta.Program, offset, bufsize, length int64) { 143func (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
50func TestWrite(what string, f io.WriteCloser, b []byte) error { 50func (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
60func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser, written *int64) *Goroutine { 62func (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
107func (t *TestGroup) Exec(desc string, p *Program, srcfifo bool, flags []string) (*Run, error) { 109func (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 {
29func (g *Goroutine) finish(err error) { 29func (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
59func (t *TestGroup) Main() *Goroutine { return t.main } 64func (t *TestGroup) Main() *Goroutine { return t.main }
60 65
66func (t *TestGroup) Panic(err error) { t.Main().Panic(err) }
67
61func (t *TestGroup) Go(name string, f func(*Goroutine)) *Goroutine { 68func (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
71func (t *TestGroup) Wait(self *Goroutine, procs... *Run) { 78func (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 {