summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua MacDonald <josh.macdonald@gmail.com>2015-01-25 23:17:17 -0800
committerJoshua MacDonald <josh.macdonald@gmail.com>2015-01-25 23:17:17 -0800
commitb55fcf3dc4c775ef35dce116ab23d35a5f9ff326 (patch)
tree47a160fb2855434f17689a9028081b29bff8f1d8
parent57c7df665788bbb524c544ce5dea66b1aade63d3 (diff)
regtest.go tests a random stream and an offset copy
-rw-r--r--.gitignore1
-rw-r--r--xdelta3/go/src/regtest.go100
-rw-r--r--xdelta3/go/src/xdelta/rstream.go56
-rw-r--r--xdelta3/go/src/xdelta/test.go63
4 files changed, 190 insertions, 30 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5761abc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
*.o
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 @@
1package main 1package main
2 2
3import ( 3import (
4 "bytes"
5 "fmt"
4 "io" 6 "io"
5 "io/ioutil" 7 "io/ioutil"
6 "xdelta" 8 "xdelta"
7) 9)
8 10
9const ( 11const (
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
13func drain(f io.ReadCloser) <-chan []byte { 17func drain(f io.ReadCloser) <-chan []byte {
@@ -39,16 +43,11 @@ func write(f io.WriteCloser, b []byte) {
39 } 43 }
40} 44}
41 45
42func main() { 46func smokeTest(r *xdelta.Runner, p *xdelta.Program) {
43 x := xdelta.Program{prog}
44 smokeTest(x)
45}
46
47func 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
84func 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
99func 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
124func 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
155func 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 @@
1package xdelta
2
3
4import (
5 "io"
6 "math/rand"
7)
8
9const (
10 blocksize = 16380 // A factor of 7
11)
12
13func 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
19func 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
32func 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
47func 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 @@
1package xdelta 1package xdelta
2 2
3import ( 3import (
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
12var ( 15var (
13 tmpDir = "/tmp" 16 tmpDir = "/tmp"
17 srcSeq int64
14) 18)
15 19
16type Program struct { 20type Program struct {
17 Path string 21 Path string
18} 22}
19 23
24type Runner struct {
25 Testdir string
26}
27
20type Run struct { 28type 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
30func (b *Program) Exec(srcfifo bool, flags []string) (*Run, error) { 37func 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
45func (r *Runner) Cleanup() {
46 os.RemoveAll(r.Testdir)
47}
48
49func (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
86func 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}