diff options
Diffstat (limited to 'xdelta3')
-rw-r--r-- | xdelta3/go/src/regtest.go | 100 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/rstream.go | 56 | ||||
-rw-r--r-- | xdelta3/go/src/xdelta/test.go | 63 |
3 files changed, 189 insertions, 30 deletions
diff --git a/xdelta3/go/src/regtest.go b/xdelta3/go/src/regtest.go index aee419d..d31e905 100644 --- a/xdelta3/go/src/regtest.go +++ b/xdelta3/go/src/regtest.go | |||
@@ -1,13 +1,17 @@ | |||
1 | package main | 1 | package main |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "bytes" | ||
5 | "fmt" | ||
4 | "io" | 6 | "io" |
5 | "io/ioutil" | 7 | "io/ioutil" |
6 | "xdelta" | 8 | "xdelta" |
7 | ) | 9 | ) |
8 | 10 | ||
9 | const ( | 11 | const ( |
12 | blocksize = 1<<20 | ||
10 | prog = "/Users/jmacd/src/xdelta/xdelta3/xdelta3" | 13 | prog = "/Users/jmacd/src/xdelta/xdelta3/xdelta3" |
14 | seed = 1422253499919909358 | ||
11 | ) | 15 | ) |
12 | 16 | ||
13 | func drain(f io.ReadCloser) <-chan []byte { | 17 | func drain(f io.ReadCloser) <-chan []byte { |
@@ -39,16 +43,11 @@ func write(f io.WriteCloser, b []byte) { | |||
39 | } | 43 | } |
40 | } | 44 | } |
41 | 45 | ||
42 | func main() { | 46 | func smokeTest(r *xdelta.Runner, p *xdelta.Program) { |
43 | x := xdelta.Program{prog} | ||
44 | smokeTest(x) | ||
45 | } | ||
46 | |||
47 | func smokeTest(p xdelta.Program) { | ||
48 | target := "Hello world!" | 47 | target := "Hello world!" |
49 | source := "Hello world, nice to meet you!" | 48 | source := "Hello world, nice to meet you!" |
50 | 49 | ||
51 | run, err := p.Exec(true, []string{"-e"}) | 50 | run, err := r.Exec(p, true, []string{"-e"}) |
52 | if err != nil { | 51 | if err != nil { |
53 | panic(err) | 52 | panic(err) |
54 | } | 53 | } |
@@ -62,7 +61,7 @@ func smokeTest(p xdelta.Program) { | |||
62 | panic(err) | 61 | panic(err) |
63 | } | 62 | } |
64 | 63 | ||
65 | run, err = p.Exec(true, []string{"-d"}) | 64 | run, err = r.Exec(p, true, []string{"-d"}) |
66 | if err != nil { | 65 | if err != nil { |
67 | panic(err) | 66 | panic(err) |
68 | } | 67 | } |
@@ -81,3 +80,88 @@ func smokeTest(p xdelta.Program) { | |||
81 | panic("It's not working!!!") | 80 | panic("It's not working!!!") |
82 | } | 81 | } |
83 | } | 82 | } |
83 | |||
84 | func copyStreams(r io.ReadCloser, w io.WriteCloser) { | ||
85 | _, err := io.Copy(w, r) | ||
86 | if err != nil { | ||
87 | panic(err) | ||
88 | } | ||
89 | err = r.Close() | ||
90 | if err != nil { | ||
91 | panic(err) | ||
92 | } | ||
93 | err = w.Close() | ||
94 | if err != nil { | ||
95 | panic(err) | ||
96 | } | ||
97 | } | ||
98 | |||
99 | func compareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length int64) { | ||
100 | b1 := make([]byte, blocksize) | ||
101 | b2 := make([]byte, blocksize) | ||
102 | var idx int64 | ||
103 | for length > 0 { | ||
104 | c := blocksize | ||
105 | if length < blocksize { | ||
106 | c = int(length) | ||
107 | } | ||
108 | if _, err := io.ReadFull(r1, b1[0:c]); err != nil { | ||
109 | panic(err) | ||
110 | } | ||
111 | if _, err := io.ReadFull(r2, b2[0:c]); err != nil { | ||
112 | panic(err) | ||
113 | } | ||
114 | if bytes.Compare(b1[0:c], b2[0:c]) != 0 { | ||
115 | fmt.Println("B1 is", string(b1[0:c])) | ||
116 | fmt.Println("B2 is", string(b2[0:c])) | ||
117 | panic(fmt.Sprint("Bytes do not compare at ", idx)) | ||
118 | } | ||
119 | length -= int64(c) | ||
120 | idx += int64(c) | ||
121 | } | ||
122 | } | ||
123 | |||
124 | func offsetTest(r *xdelta.Runner, p *xdelta.Program, offset, length int64) { | ||
125 | enc, err := r.Exec(p, true, []string{"-e"}) | ||
126 | if err != nil { | ||
127 | panic(err) | ||
128 | } | ||
129 | dec, err := r.Exec(p, true, []string{"-d"}) | ||
130 | if err != nil { | ||
131 | panic(err) | ||
132 | } | ||
133 | |||
134 | read, write := io.Pipe() | ||
135 | |||
136 | go copyStreams(enc.Stdout, dec.Stdin) | ||
137 | go compareStreams(dec.Stdout, read, length) | ||
138 | |||
139 | empty(enc.Stderr) // Use these? | ||
140 | empty(dec.Stderr) | ||
141 | |||
142 | // TODO: seems possible to use one WriteRstreams call to generate | ||
143 | // the source and target for both encoder and decoder. Why not? | ||
144 | xdelta.WriteRstreams(seed, offset, length, enc.Srcin, enc.Stdin) | ||
145 | xdelta.WriteRstreams(seed, offset, length, dec.Srcin, write) | ||
146 | |||
147 | if err := enc.Cmd.Wait(); err != nil { | ||
148 | panic(err) | ||
149 | } | ||
150 | if err := dec.Cmd.Wait(); err != nil { | ||
151 | panic(err) | ||
152 | } | ||
153 | } | ||
154 | |||
155 | func main() { | ||
156 | r, err := xdelta.NewRunner() | ||
157 | if err != nil { | ||
158 | panic(err) | ||
159 | } | ||
160 | defer r.Cleanup() | ||
161 | |||
162 | prog := &xdelta.Program{prog} | ||
163 | |||
164 | smokeTest(r, prog) | ||
165 | |||
166 | offsetTest(r, prog, 0, 1024 << 20) | ||
167 | } | ||
diff --git a/xdelta3/go/src/xdelta/rstream.go b/xdelta3/go/src/xdelta/rstream.go new file mode 100644 index 0000000..1666934 --- /dev/null +++ b/xdelta3/go/src/xdelta/rstream.go | |||
@@ -0,0 +1,56 @@ | |||
1 | package xdelta | ||
2 | |||
3 | |||
4 | import ( | ||
5 | "io" | ||
6 | "math/rand" | ||
7 | ) | ||
8 | |||
9 | const ( | ||
10 | blocksize = 16380 // A factor of 7 | ||
11 | ) | ||
12 | |||
13 | func WriteRstreams(seed, offset, len int64, | ||
14 | first, second io.WriteCloser) { | ||
15 | go writeOne(seed, 0, len, first) | ||
16 | go writeOne(seed, offset, len, second) | ||
17 | } | ||
18 | |||
19 | func writeOne(seed, offset, len int64, stream io.WriteCloser) { | ||
20 | if offset != 0 { | ||
21 | // Fill with other random data until the offset | ||
22 | writeRand(rand.New(rand.NewSource(^seed)), | ||
23 | offset, stream) | ||
24 | } | ||
25 | writeRand(rand.New(rand.NewSource(seed)), | ||
26 | len - offset, stream) | ||
27 | if err := stream.Close(); err != nil { | ||
28 | panic(err) | ||
29 | } | ||
30 | } | ||
31 | |||
32 | func writeRand(r *rand.Rand, len int64, s io.Writer) { | ||
33 | blk := make([]byte, blocksize) | ||
34 | for len > 0 { | ||
35 | fillRand(r, blk) | ||
36 | c := blocksize | ||
37 | if len < blocksize { | ||
38 | c = int(len) | ||
39 | } | ||
40 | if _, err := s.Write(blk[0:c]); err != nil { | ||
41 | panic(err) | ||
42 | } | ||
43 | len -= int64(c) | ||
44 | } | ||
45 | } | ||
46 | |||
47 | func fillRand(r *rand.Rand, blk []byte) { | ||
48 | for p := 0; p < blocksize; { | ||
49 | v := r.Int63() | ||
50 | for i := 7; i != 0; i-- { | ||
51 | blk[p] = byte(v) | ||
52 | p++ | ||
53 | v >>= 8 | ||
54 | } | ||
55 | } | ||
56 | } | ||
diff --git a/xdelta3/go/src/xdelta/test.go b/xdelta3/go/src/xdelta/test.go index d586538..292f133 100644 --- a/xdelta3/go/src/xdelta/test.go +++ b/xdelta3/go/src/xdelta/test.go | |||
@@ -1,41 +1,58 @@ | |||
1 | package xdelta | 1 | package xdelta |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "fmt" | ||
4 | "io" | 5 | "io" |
5 | "io/ioutil" | 6 | "io/ioutil" |
6 | "os" | 7 | "os" |
7 | "os/exec" | 8 | "os/exec" |
8 | "path" | 9 | "path" |
10 | "sync/atomic" | ||
11 | |||
9 | "golang.org/x/sys/unix" | 12 | "golang.org/x/sys/unix" |
10 | ) | 13 | ) |
11 | 14 | ||
12 | var ( | 15 | var ( |
13 | tmpDir = "/tmp" | 16 | tmpDir = "/tmp" |
17 | srcSeq int64 | ||
14 | ) | 18 | ) |
15 | 19 | ||
16 | type Program struct { | 20 | type Program struct { |
17 | Path string | 21 | Path string |
18 | } | 22 | } |
19 | 23 | ||
24 | type Runner struct { | ||
25 | Testdir string | ||
26 | } | ||
27 | |||
20 | type Run struct { | 28 | type Run struct { |
21 | Cmd exec.Cmd | 29 | Cmd exec.Cmd |
22 | Testdir string | ||
23 | Srcfile string | 30 | Srcfile string |
24 | Stdin io.WriteCloser | 31 | Stdin io.WriteCloser |
25 | Srcin io.WriteCloser | 32 | Srcin io.WriteCloser |
26 | Stdout io.ReadCloser | 33 | Stdout io.ReadCloser |
27 | Stderr io.ReadCloser | 34 | Stderr io.ReadCloser |
28 | } | 35 | } |
29 | 36 | ||
30 | func (b *Program) Exec(srcfifo bool, flags []string) (*Run, error) { | 37 | func NewRunner() (*Runner, error) { |
31 | var err error | 38 | if dir, err := ioutil.TempDir(tmpDir, "xrt"); err != nil { |
32 | run := &Run{} | ||
33 | if run.Testdir, err = ioutil.TempDir(tmpDir, "xrt"); err != nil { | ||
34 | return nil, err | 39 | return nil, err |
40 | } else { | ||
41 | return &Runner{dir}, nil | ||
35 | } | 42 | } |
36 | args := []string{b.Path} | 43 | } |
44 | |||
45 | func (r *Runner) Cleanup() { | ||
46 | os.RemoveAll(r.Testdir) | ||
47 | } | ||
48 | |||
49 | func (r *Runner) Exec(p *Program, srcfifo bool, flags []string) (*Run, error) { | ||
50 | var err error | ||
51 | run := &Run{} | ||
52 | args := []string{p.Path} | ||
37 | if srcfifo { | 53 | if srcfifo { |
38 | run.Srcfile = path.Join(run.Testdir, "source") | 54 | num := atomic.AddInt64(&srcSeq, 1) |
55 | run.Srcfile = path.Join(r.Testdir, fmt.Sprint("source", num)) | ||
39 | if err = unix.Mkfifo(run.Srcfile, 0600); err != nil { | 56 | if err = unix.Mkfifo(run.Srcfile, 0600); err != nil { |
40 | return nil, err | 57 | return nil, err |
41 | } | 58 | } |
@@ -44,18 +61,7 @@ func (b *Program) Exec(srcfifo bool, flags []string) (*Run, error) { | |||
44 | read, write := io.Pipe() | 61 | read, write := io.Pipe() |
45 | run.Srcin = write | 62 | run.Srcin = write |
46 | 63 | ||
47 | go func() { | 64 | go writeFifo(run.Srcfile, read) |
48 | fifo, err := os.OpenFile(run.Srcfile, os.O_WRONLY, 0600) | ||
49 | if err != nil { | ||
50 | panic(err) | ||
51 | } | ||
52 | if _, err := io.Copy(fifo, read); err != nil { | ||
53 | panic(err) | ||
54 | } | ||
55 | if err := fifo.Close(); err != nil { | ||
56 | panic(err) | ||
57 | } | ||
58 | }() | ||
59 | args = append(args, "-s") | 65 | args = append(args, "-s") |
60 | args = append(args, run.Srcfile) | 66 | args = append(args, run.Srcfile) |
61 | } | 67 | } |
@@ -69,10 +75,23 @@ func (b *Program) Exec(srcfifo bool, flags []string) (*Run, error) { | |||
69 | return nil, err | 75 | return nil, err |
70 | } | 76 | } |
71 | 77 | ||
72 | run.Cmd.Path = b.Path | 78 | run.Cmd.Path = p.Path |
73 | run.Cmd.Args = append(args, flags...) | 79 | run.Cmd.Args = append(args, flags...) |
74 | run.Cmd.Dir = run.Testdir | 80 | run.Cmd.Dir = r.Testdir |
75 | run.Cmd.Start() | 81 | run.Cmd.Start() |
76 | 82 | ||
77 | return run, nil | 83 | return run, nil |
78 | } | 84 | } |
85 | |||
86 | func writeFifo(srcfile string, read io.Reader) { | ||
87 | fifo, err := os.OpenFile(srcfile, os.O_WRONLY, 0600) | ||
88 | if err != nil { | ||
89 | panic(err) | ||
90 | } | ||
91 | if _, err := io.Copy(fifo, read); err != nil { | ||
92 | panic(err) | ||
93 | } | ||
94 | if err := fifo.Close(); err != nil { | ||
95 | panic(err) | ||
96 | } | ||
97 | } | ||