diff options
Diffstat (limited to 'xdelta3/go')
-rw-r--r-- | xdelta3/go/src/regtest.go | 148 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/rstream.go | 12 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/test.go | 99 |
3 files changed, 146 insertions, 113 deletions
diff --git a/xdelta3/go/src/regtest.go b/xdelta3/go/src/regtest.go index 52547e1..1798f40 100644 --- a/xdelta3/go/src/regtest.go +++ b/xdelta3/go/src/regtest.go | |||
@@ -1,12 +1,9 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "bufio" | 4 | "errors" |
5 | "bytes" | ||
6 | "fmt" | 5 | "fmt" |
7 | "io" | 6 | "io" |
8 | "io/ioutil" | ||
9 | "os" | ||
10 | 7 | ||
11 | "xdelta" | 8 | "xdelta" |
12 | ) | 9 | ) |
@@ -14,150 +11,83 @@ import ( | |||
14 | const ( | 11 | const ( |
15 | blocksize = 1<<16 | 12 | blocksize = 1<<16 |
16 | winsize = 1<<26 | 13 | winsize = 1<<26 |
17 | prog = "/Users/jmacd/src/xdelta/xdelta3/build/m64/64size-64off/xdelta3" | 14 | xdelta3 = "/volume/home/jmacd/src/xdelta-64bithash/xdelta3/build/x86_64-pc-linux-gnu-m64/usize64/xoff64/xdelta3" |
18 | seed = 1422253499919909358 | 15 | seed = 1422253499919909358 |
19 | ) | 16 | ) |
20 | 17 | ||
21 | func drain(f io.ReadCloser) <-chan []byte { | 18 | func smokeTest(r *xdelta.Runner, t *xdelta.TestGroup, p *xdelta.Program) { |
22 | c := make(chan []byte) | 19 | t.Add(1) |
23 | go func() { | ||
24 | if b, err := ioutil.ReadAll(f); err != nil { | ||
25 | panic(err) | ||
26 | } else { | ||
27 | c <- b | ||
28 | } | ||
29 | }() | ||
30 | return c | ||
31 | } | ||
32 | |||
33 | func empty(f io.ReadCloser, desc string) { | ||
34 | go func() { | ||
35 | s := bufio.NewScanner(f) | ||
36 | for s.Scan() { | ||
37 | os.Stderr.Write([]byte(fmt.Sprint(desc, ": ", s.Text(), "\n"))) | ||
38 | } | ||
39 | if err := s.Err(); err != nil { | ||
40 | fmt.Println("error reading input:", err) | ||
41 | } | ||
42 | }() | ||
43 | } | ||
44 | |||
45 | func write(f io.WriteCloser, b []byte) { | ||
46 | if _, err := f.Write(b); err != nil { | ||
47 | panic(err) | ||
48 | } | ||
49 | if err := f.Close(); err != nil { | ||
50 | panic(err) | ||
51 | } | ||
52 | } | ||
53 | |||
54 | func smokeTest(r *xdelta.Runner, p *xdelta.Program) { | ||
55 | target := "Hello world!" | 20 | target := "Hello world!" |
56 | source := "Hello world, nice to meet you!" | 21 | source := "Hello world, nice to meet you!" |
57 | 22 | ||
58 | run, err := r.Exec(p, true, []string{"-e"}) | 23 | run, err := r.Exec(p, true, []string{"-e"}) |
59 | if err != nil { | 24 | if err != nil { |
60 | panic(err) | 25 | t.Panic(err) |
61 | } | 26 | } |
62 | encodeout := drain(run.Stdout) | 27 | encodeout := t.Drain(run.Stdout) |
63 | empty(run.Stderr, "encode") | 28 | t.Empty(run.Stderr, "encode") |
64 | 29 | ||
65 | write(run.Stdin, []byte(target)) | 30 | t.Write("encode.stdin", run.Stdin, []byte(target)) |
66 | write(run.Srcin, []byte(source)) | 31 | t.Write("encode.stdout", run.Srcin, []byte(source)) |
67 | 32 | ||
68 | if err := run.Cmd.Wait(); err != nil { | 33 | if err := run.Cmd.Wait(); err != nil { |
69 | panic(err) | 34 | t.Panic(err) |
70 | } | 35 | } |
71 | 36 | ||
72 | run, err = r.Exec(p, true, []string{"-d"}) | 37 | run, err = r.Exec(p, true, []string{"-d"}) |
73 | if err != nil { | 38 | if err != nil { |
74 | panic(err) | 39 | t.Panic(err) |
75 | } | 40 | } |
76 | 41 | ||
77 | decodeout := drain(run.Stdout) | 42 | decodeout := t.Drain(run.Stdout) |
78 | empty(run.Stderr, "decode") | 43 | t.Empty(run.Stderr, "decode") |
79 | 44 | ||
80 | write(run.Stdin, <-encodeout) | 45 | t.Write("decode.stdin", run.Stdin, <-encodeout) |
81 | write(run.Srcin, []byte(source)) | 46 | t.Write("decode.stdout", run.Srcin, []byte(source)) |
82 | 47 | ||
83 | if err := run.Cmd.Wait(); err != nil { | 48 | if err := run.Cmd.Wait(); err != nil { |
84 | panic(err) | 49 | t.Panic(err) |
85 | } | 50 | } |
86 | 51 | ||
87 | if string(<-decodeout) != target { | 52 | if string(<-decodeout) != target { |
88 | panic("It's not working!!!") | 53 | t.Panic(errors.New("It's not working!!!")) |
89 | } | 54 | } |
55 | t.Done() | ||
90 | } | 56 | } |
91 | 57 | ||
92 | func copyStreams(r io.ReadCloser, w io.WriteCloser) { | 58 | func offsetTest(r *xdelta.Runner, t *xdelta.TestGroup, p *xdelta.Program, offset, bufsize, length int64) { |
93 | _, err := io.Copy(w, r) | 59 | t.Add(1) |
60 | eargs := []string{"-e", "-1", "-n", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)} | ||
61 | enc, err := r.Exec(p, true, eargs) | ||
94 | if err != nil { | 62 | if err != nil { |
95 | panic(err) | 63 | t.Panic(err) |
96 | } | 64 | } |
97 | err = r.Close() | 65 | dargs := []string{"-d", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)} |
66 | dec, err := r.Exec(p, true, dargs) | ||
98 | if err != nil { | 67 | if err != nil { |
99 | panic(err) | 68 | t.Panic(err) |
100 | } | ||
101 | err = w.Close() | ||
102 | if err != nil { | ||
103 | panic(err) | ||
104 | } | ||
105 | } | ||
106 | |||
107 | func compareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length int64) { | ||
108 | b1 := make([]byte, blocksize) | ||
109 | b2 := make([]byte, blocksize) | ||
110 | var idx int64 | ||
111 | for length > 0 { | ||
112 | c := blocksize | ||
113 | if length < blocksize { | ||
114 | c = int(length) | ||
115 | } | ||
116 | if _, err := io.ReadFull(r1, b1[0:c]); err != nil { | ||
117 | panic(err) | ||
118 | } | ||
119 | if _, err := io.ReadFull(r2, b2[0:c]); err != nil { | ||
120 | panic(err) | ||
121 | } | ||
122 | if bytes.Compare(b1[0:c], b2[0:c]) != 0 { | ||
123 | fmt.Println("B1 is", string(b1[0:c])) | ||
124 | fmt.Println("B2 is", string(b2[0:c])) | ||
125 | panic(fmt.Sprint("Bytes do not compare at ", idx)) | ||
126 | } | ||
127 | length -= int64(c) | ||
128 | idx += int64(c) | ||
129 | } | ||
130 | } | ||
131 | |||
132 | func offsetTest(r *xdelta.Runner, p *xdelta.Program, offset, bufsize, length int64) { | ||
133 | enc, err := r.Exec(p, true, []string{"-e", "-1", "-n", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)}) | ||
134 | if err != nil { | ||
135 | panic(err) | ||
136 | } | ||
137 | dec, err := r.Exec(p, true, []string{"-d", fmt.Sprint("-B", bufsize), "-vv", fmt.Sprint("-W", winsize)}) | ||
138 | if err != nil { | ||
139 | panic(err) | ||
140 | } | 69 | } |
141 | 70 | ||
142 | read, write := io.Pipe() | 71 | read, write := io.Pipe() |
143 | 72 | ||
144 | go copyStreams(enc.Stdout, dec.Stdin) | 73 | t.CopyStreams(enc.Stdout, dec.Stdin) |
145 | go compareStreams(dec.Stdout, read, length) | 74 | t.CompareStreams(dec.Stdout, read, length) |
146 | 75 | ||
147 | empty(enc.Stderr, "encode") | 76 | t.Empty(enc.Stderr, "encode") |
148 | empty(dec.Stderr, "decode") | 77 | t.Empty(dec.Stderr, "decode") |
149 | 78 | ||
150 | // TODO: seems possible to use one WriteRstreams call to generate | 79 | // TODO: seems possible to use one WriteRstreams call to generate |
151 | // the source and target for both encoder and decoder. Why not? | 80 | // the source and target for both encoder and decoder. Why not? |
152 | xdelta.WriteRstreams(seed, offset, length, enc.Srcin, enc.Stdin) | 81 | xdelta.WriteRstreams(t, seed, offset, length, enc.Srcin, enc. Stdin) |
153 | xdelta.WriteRstreams(seed, offset, length, dec.Srcin, write) | 82 | xdelta.WriteRstreams(t, seed, offset, length, dec.Srcin, write) |
154 | 83 | ||
155 | if err := enc.Cmd.Wait(); err != nil { | 84 | if err := enc.Cmd.Wait(); err != nil { |
156 | panic(err) | 85 | t.Panic(err) |
157 | } | 86 | } |
158 | if err := dec.Cmd.Wait(); err != nil { | 87 | if err := dec.Cmd.Wait(); err != nil { |
159 | panic(err) | 88 | t.Panic(err) |
160 | } | 89 | } |
90 | t.Done() | ||
161 | } | 91 | } |
162 | 92 | ||
163 | func main() { | 93 | func main() { |
@@ -167,9 +97,11 @@ func main() { | |||
167 | } | 97 | } |
168 | defer r.Cleanup() | 98 | defer r.Cleanup() |
169 | 99 | ||
170 | prog := &xdelta.Program{prog} | 100 | prog := &xdelta.Program{xdelta3} |
101 | |||
102 | smokeTest(r, xdelta.NewTestGroup(), prog) | ||
171 | 103 | ||
172 | smokeTest(r, prog) | 104 | offsetTest(r, xdelta.NewTestGroup(), prog, 1 << 8, 1 << 9, 1 << 10) |
173 | 105 | ||
174 | offsetTest(r, prog, 1 << 31, 1 << 32, 1 << 33) | 106 | //offsetTest(r, prog, 1 << 31, 1 << 32, 1 << 33) |
175 | } | 107 | } |
diff --git a/xdelta3/go/src/xdelta/rstream.go b/xdelta3/go/src/xdelta/rstream.go index 1d56031..3e7265f 100644 --- a/xdelta3/go/src/xdelta/rstream.go +++ b/xdelta3/go/src/xdelta/rstream.go | |||
@@ -7,16 +7,17 @@ import ( | |||
7 | ) | 7 | ) |
8 | 8 | ||
9 | const ( | 9 | const ( |
10 | blocksize = 16380 // A factor of 7 | 10 | blocksize = 16380 |
11 | ) | 11 | ) |
12 | 12 | ||
13 | func WriteRstreams(seed, offset, len int64, | 13 | func WriteRstreams(t *TestGroup, seed, offset, len int64, |
14 | first, second io.WriteCloser) { | 14 | first, second io.WriteCloser) { |
15 | go writeOne(seed, 0, len, first) | 15 | go writeOne(t, seed, 0, len, first) |
16 | go writeOne(seed, offset, len, second) | 16 | go writeOne(t, seed, offset, len, second) |
17 | } | 17 | } |
18 | 18 | ||
19 | func writeOne(seed, offset, len int64, stream io.WriteCloser) error { | 19 | func writeOne(t *TestGroup, seed, offset, len int64, stream io.WriteCloser) error { |
20 | t.WaitGroup.Add(1) | ||
20 | if offset != 0 { | 21 | if offset != 0 { |
21 | // Fill with other random data until the offset | 22 | // Fill with other random data until the offset |
22 | if err := writeRand(rand.New(rand.NewSource(^seed)), offset, stream); err != nil { | 23 | if err := writeRand(rand.New(rand.NewSource(^seed)), offset, stream); err != nil { |
@@ -27,6 +28,7 @@ func writeOne(seed, offset, len int64, stream io.WriteCloser) error { | |||
27 | len - offset, stream); err != nil { | 28 | len - offset, stream); err != nil { |
28 | return err | 29 | return err |
29 | } | 30 | } |
31 | t.WaitGroup.Done() | ||
30 | return stream.Close() | 32 | return stream.Close() |
31 | } | 33 | } |
32 | 34 | ||
diff --git a/xdelta3/go/src/xdelta/test.go b/xdelta3/go/src/xdelta/test.go index 3143dfa..50ddeae 100644 --- a/xdelta3/go/src/xdelta/test.go +++ b/xdelta3/go/src/xdelta/test.go | |||
@@ -1,6 +1,9 @@ | |||
1 | package xdelta | 1 | package xdelta |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "bufio" | ||
5 | "bytes" | ||
6 | "errors" | ||
4 | "fmt" | 7 | "fmt" |
5 | "io" | 8 | "io" |
6 | "io/ioutil" | 9 | "io/ioutil" |
@@ -8,6 +11,7 @@ import ( | |||
8 | "os/exec" | 11 | "os/exec" |
9 | "path" | 12 | "path" |
10 | "sync/atomic" | 13 | "sync/atomic" |
14 | "sync" | ||
11 | 15 | ||
12 | "golang.org/x/sys/unix" | 16 | "golang.org/x/sys/unix" |
13 | ) | 17 | ) |
@@ -25,6 +29,10 @@ type Runner struct { | |||
25 | Testdir string | 29 | Testdir string |
26 | } | 30 | } |
27 | 31 | ||
32 | type TestGroup struct { | ||
33 | sync.WaitGroup | ||
34 | } | ||
35 | |||
28 | type Run struct { | 36 | type Run struct { |
29 | Cmd exec.Cmd | 37 | Cmd exec.Cmd |
30 | Srcfile string | 38 | Srcfile string |
@@ -34,6 +42,97 @@ type Run struct { | |||
34 | Stderr io.ReadCloser | 42 | Stderr io.ReadCloser |
35 | } | 43 | } |
36 | 44 | ||
45 | func (t *TestGroup) Panic(err error) { | ||
46 | t.WaitGroup.Done() // For the caller | ||
47 | t.WaitGroup.Wait() | ||
48 | panic(err) | ||
49 | } | ||
50 | |||
51 | func NewTestGroup() *TestGroup { | ||
52 | return &TestGroup{} | ||
53 | } | ||
54 | |||
55 | func (t *TestGroup) Drain(f io.ReadCloser) <-chan []byte { | ||
56 | c := make(chan []byte) | ||
57 | go func() { | ||
58 | t.WaitGroup.Add(1) | ||
59 | if b, err := ioutil.ReadAll(f); err != nil { | ||
60 | t.Panic(err) | ||
61 | } else { | ||
62 | c <- b | ||
63 | } | ||
64 | t.WaitGroup.Done() | ||
65 | }() | ||
66 | return c | ||
67 | } | ||
68 | |||
69 | func (t *TestGroup) Empty(f io.ReadCloser, desc string) { | ||
70 | go func() { | ||
71 | t.WaitGroup.Add(1) | ||
72 | s := bufio.NewScanner(f) | ||
73 | for s.Scan() { | ||
74 | os.Stderr.Write([]byte(fmt.Sprint(desc, ": ", s.Text(), "\n"))) | ||
75 | } | ||
76 | if err := s.Err(); err != nil { | ||
77 | t.Panic(err) | ||
78 | } | ||
79 | t.WaitGroup.Done() | ||
80 | }() | ||
81 | } | ||
82 | |||
83 | func (t *TestGroup) Write(what string, f io.WriteCloser, b []byte) { | ||
84 | if _, err := f.Write(b); err != nil { | ||
85 | t.Panic(errors.New(fmt.Sprint(what, ":", err))) | ||
86 | } | ||
87 | if err := f.Close(); err != nil { | ||
88 | t.Panic(errors.New(fmt.Sprint(what, ":", err))) | ||
89 | } | ||
90 | } | ||
91 | |||
92 | func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser) { | ||
93 | t.Add(1) | ||
94 | _, err := io.Copy(w, r) | ||
95 | if err != nil { | ||
96 | t.Panic(err) | ||
97 | } | ||
98 | err = r.Close() | ||
99 | if err != nil { | ||
100 | t.Panic(err) | ||
101 | } | ||
102 | err = w.Close() | ||
103 | if err != nil { | ||
104 | t.Panic(err) | ||
105 | } | ||
106 | t.Done() | ||
107 | } | ||
108 | |||
109 | func (t *TestGroup) CompareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length int64) { | ||
110 | t.Add(1) | ||
111 | b1 := make([]byte, blocksize) | ||
112 | b2 := make([]byte, blocksize) | ||
113 | var idx int64 | ||
114 | for length > 0 { | ||
115 | c := blocksize | ||
116 | if length < blocksize { | ||
117 | c = int(length) | ||
118 | } | ||
119 | if _, err := io.ReadFull(r1, b1[0:c]); err != nil { | ||
120 | t.Panic(err) | ||
121 | } | ||
122 | if _, err := io.ReadFull(r2, b2[0:c]); err != nil { | ||
123 | t.Panic(err) | ||
124 | } | ||
125 | if bytes.Compare(b1[0:c], b2[0:c]) != 0 { | ||
126 | fmt.Println("B1 is", string(b1[0:c])) | ||
127 | fmt.Println("B2 is", string(b2[0:c])) | ||
128 | t.Panic(errors.New(fmt.Sprint("Bytes do not compare at ", idx))) | ||
129 | } | ||
130 | length -= int64(c) | ||
131 | idx += int64(c) | ||
132 | } | ||
133 | t.Done() | ||
134 | } | ||
135 | |||
37 | func NewRunner() (*Runner, error) { | 136 | func NewRunner() (*Runner, error) { |
38 | if dir, err := ioutil.TempDir(tmpDir, "xrt"); err != nil { | 137 | if dir, err := ioutil.TempDir(tmpDir, "xrt"); err != nil { |
39 | return nil, err | 138 | return nil, err |