🏗 Add xdelta3 dependency
This commit is contained in:
parent
80f2439239
commit
ae59ce2256
97 changed files with 45332 additions and 1 deletions
71
lib/xdelta3/go/src/xdelta/rstream.go
Normal file
71
lib/xdelta3/go/src/xdelta/rstream.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package xdelta
|
||||
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
const (
|
||||
blocksize = 1<<17
|
||||
)
|
||||
|
||||
func (t *TestGroup) WriteRstreams(desc string, seed, offset, len int64,
|
||||
src, tgt io.WriteCloser) {
|
||||
t.Go("src-write:"+desc, func (g *Goroutine) {
|
||||
writeOne(g, seed, 0, len, tgt, false)
|
||||
})
|
||||
t.Go("tgt-write:"+desc, func (g *Goroutine) {
|
||||
writeOne(g, seed, offset, len, src, true)
|
||||
})
|
||||
}
|
||||
|
||||
func writeOne(g *Goroutine, seed, offset, len int64, stream io.WriteCloser, readall bool) {
|
||||
if !readall {
|
||||
// Allow the source-read to fail or block until the process terminates.
|
||||
// This behavior is reserved for the decoder, which is not required to
|
||||
// read the entire source.
|
||||
g.OK()
|
||||
}
|
||||
if offset != 0 {
|
||||
// Fill with other random data until the offset
|
||||
if err := writeRand(g, rand.New(rand.NewSource(^seed)), offset, stream); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
}
|
||||
if err := writeRand(g, rand.New(rand.NewSource(seed)),
|
||||
len - offset, stream); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
if err := stream.Close(); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
g.OK()
|
||||
}
|
||||
|
||||
func writeRand(g *Goroutine, r *rand.Rand, len int64, s io.Writer) error {
|
||||
blk := make([]byte, blocksize)
|
||||
for len > 0 {
|
||||
fillRand(r, blk)
|
||||
c := blocksize
|
||||
if len < blocksize {
|
||||
c = int(len)
|
||||
}
|
||||
if _, err := s.Write(blk[0:c]); err != nil {
|
||||
return err
|
||||
}
|
||||
len -= int64(c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fillRand(r *rand.Rand, blk []byte) {
|
||||
for p := 0; p < len(blk); {
|
||||
v := r.Int63()
|
||||
for i := 7; i != 0 && p < len(blk); i-- {
|
||||
blk[p] = byte(v)
|
||||
p++
|
||||
v >>= 8
|
||||
}
|
||||
}
|
||||
}
|
71
lib/xdelta3/go/src/xdelta/run.go
Normal file
71
lib/xdelta3/go/src/xdelta/run.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package xdelta
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
type Program struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
type Run struct {
|
||||
Cmd exec.Cmd
|
||||
Srcfile string
|
||||
Stdin io.WriteCloser
|
||||
Srcin io.WriteCloser
|
||||
Stdout io.ReadCloser
|
||||
Stderr io.ReadCloser
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
Testdir string
|
||||
}
|
||||
|
||||
func (r *Run) Wait() error {
|
||||
return r.Cmd.Wait()
|
||||
}
|
||||
|
||||
func NewRunner() (*Runner, error) {
|
||||
if dir, err := ioutil.TempDir(tmpDir, "xrt"); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return &Runner{dir}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runner) newTestGroup(name string) (*TestGroup) {
|
||||
tg := &TestGroup{Runner: r}
|
||||
tg.WaitGroup.Add(1)
|
||||
g0 := &Goroutine{tg, name, false}
|
||||
tg.running = append(tg.running, g0)
|
||||
tg.main = g0
|
||||
return tg
|
||||
}
|
||||
|
||||
func (r *Runner) Cleanup() {
|
||||
os.RemoveAll(r.Testdir)
|
||||
}
|
||||
|
||||
func (r *Runner) RunTest(name string, f func (t *TestGroup)) {
|
||||
t := r.newTestGroup(name)
|
||||
c := make(chan interface{})
|
||||
go func() {
|
||||
defer func() {
|
||||
rec := recover()
|
||||
c <- rec
|
||||
}()
|
||||
fmt.Println("Testing", name, "...")
|
||||
f(t)
|
||||
c <- nil
|
||||
}()
|
||||
rec := <- c
|
||||
if t.errors == nil && rec == nil {
|
||||
fmt.Println("Success:", name)
|
||||
} else {
|
||||
fmt.Println("FAILED:", name, t.errors, rec)
|
||||
}
|
||||
}
|
164
lib/xdelta3/go/src/xdelta/test.go
Normal file
164
lib/xdelta3/go/src/xdelta/test.go
Normal file
|
@ -0,0 +1,164 @@
|
|||
package xdelta
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
tmpDir = "/tmp"
|
||||
srcSeq int64
|
||||
)
|
||||
|
||||
func (t *TestGroup) Drain(f io.ReadCloser, desc string) <-chan []byte {
|
||||
c := make(chan []byte)
|
||||
t.Go(desc, func(g *Goroutine) {
|
||||
if b, err := ioutil.ReadAll(f); err != nil {
|
||||
g.Panic(err)
|
||||
} else {
|
||||
c <- b
|
||||
}
|
||||
g.OK()
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
func (t *TestGroup) Empty(f io.ReadCloser, desc string) *Goroutine {
|
||||
return t.Go("empty:"+desc, func (g *Goroutine) {
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
os.Stderr.Write([]byte(fmt.Sprint(desc, ": ", s.Text(), "\n")))
|
||||
}
|
||||
err := s.Err()
|
||||
f.Close()
|
||||
if err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
g.OK()
|
||||
})
|
||||
}
|
||||
|
||||
func (t *TestGroup) TestWrite(what string, f io.WriteCloser, b []byte) *Goroutine {
|
||||
return t.Go("write", func(g *Goroutine) {
|
||||
if _, err := f.Write(b); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
g.OK()
|
||||
})
|
||||
}
|
||||
|
||||
func (t *TestGroup) CopyStreams(r io.ReadCloser, w io.WriteCloser, written *int64) *Goroutine {
|
||||
return t.Go("copy", func(g *Goroutine) {
|
||||
nwrite, err := io.Copy(w, r)
|
||||
if err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
err = r.Close()
|
||||
if err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
g.OK()
|
||||
*written = nwrite
|
||||
})
|
||||
}
|
||||
|
||||
func (t *TestGroup) CompareStreams(r1 io.ReadCloser, r2 io.ReadCloser, length int64) *Goroutine {
|
||||
return t.Go("compare", func(g *Goroutine) {
|
||||
b1 := make([]byte, blocksize)
|
||||
b2 := make([]byte, blocksize)
|
||||
var idx int64
|
||||
for length > 0 {
|
||||
c := blocksize
|
||||
if length < blocksize {
|
||||
c = int(length)
|
||||
}
|
||||
if _, err := io.ReadFull(r1, b1[0:c]); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
if _, err := io.ReadFull(r2, b2[0:c]); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
if bytes.Compare(b1[0:c], b2[0:c]) != 0 {
|
||||
fmt.Println("B1 is", string(b1[0:c]))
|
||||
fmt.Println("B2 is", string(b2[0:c]))
|
||||
g.Panic(errors.New(fmt.Sprint("Bytes do not compare at ", idx)))
|
||||
}
|
||||
length -= int64(c)
|
||||
idx += int64(c)
|
||||
}
|
||||
g.OK()
|
||||
})
|
||||
}
|
||||
|
||||
func (t *TestGroup) Exec(desc string, p Program, srcfifo bool, flags []string) (*Run, error) {
|
||||
var err error
|
||||
run := &Run{}
|
||||
args := []string{p.Path}
|
||||
if srcfifo {
|
||||
num := atomic.AddInt64(&srcSeq, 1)
|
||||
run.Srcfile = path.Join(t.Runner.Testdir, fmt.Sprint("source", num))
|
||||
if err = unix.Mkfifo(run.Srcfile, 0600); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
read, write := io.Pipe()
|
||||
t.writeFifo(run.Srcfile, read)
|
||||
run.Srcin = write
|
||||
args = append(args, "-s")
|
||||
args = append(args, run.Srcfile)
|
||||
}
|
||||
if run.Stdin, err = run.Cmd.StdinPipe(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if run.Stdout, err = run.Cmd.StdoutPipe(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if run.Stderr, err = run.Cmd.StderrPipe(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
run.Cmd.Path = p.Path
|
||||
run.Cmd.Args = append(args, flags...)
|
||||
run.Cmd.Dir = t.Runner.Testdir
|
||||
if serr := run.Cmd.Start(); serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
return run, nil
|
||||
}
|
||||
|
||||
func (t *TestGroup) Fail(v ...interface{}) {
|
||||
panic(fmt.Sprintln(v...))
|
||||
}
|
||||
|
||||
func (t *TestGroup) writeFifo(srcfile string, read io.Reader) *Goroutine {
|
||||
return t.Go("compare", func(g *Goroutine) {
|
||||
fifo, err := os.OpenFile(srcfile, os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
fifo.Close()
|
||||
g.Panic(err)
|
||||
}
|
||||
if _, err := io.Copy(fifo, read); err != nil {
|
||||
fifo.Close()
|
||||
g.Panic(err)
|
||||
}
|
||||
if err := fifo.Close(); err != nil {
|
||||
g.Panic(err)
|
||||
}
|
||||
g.OK()
|
||||
})
|
||||
}
|
97
lib/xdelta3/go/src/xdelta/tgroup.go
Normal file
97
lib/xdelta3/go/src/xdelta/tgroup.go
Normal file
|
@ -0,0 +1,97 @@
|
|||
package xdelta
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type TestGroup struct {
|
||||
*Runner
|
||||
main *Goroutine
|
||||
sync.Mutex
|
||||
sync.WaitGroup
|
||||
running []*Goroutine
|
||||
errors []error
|
||||
nonerrors []error // For tolerated / expected conditions
|
||||
}
|
||||
|
||||
type Goroutine struct {
|
||||
*TestGroup
|
||||
name string
|
||||
done bool
|
||||
}
|
||||
|
||||
func (g *Goroutine) String() string {
|
||||
return fmt.Sprint("[", g.name, "]")
|
||||
}
|
||||
|
||||
func (g *Goroutine) finish(err error) {
|
||||
wait := false
|
||||
tg := g.TestGroup
|
||||
sbuf := make([]byte, 4096)
|
||||
sbuf = sbuf[0:runtime.Stack(sbuf, false)]
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%v:%v:%v", g.name, err, string(sbuf))
|
||||
}
|
||||
tg.Lock()
|
||||
if g.done {
|
||||
if err != nil {
|
||||
tg.nonerrors = append(tg.nonerrors, err)
|
||||
}
|
||||
} else {
|
||||
wait = true
|
||||
g.done = true
|
||||
if err != nil {
|
||||
tg.errors = append(tg.errors, err)
|
||||
}
|
||||
}
|
||||
tg.Unlock()
|
||||
if wait {
|
||||
tg.WaitGroup.Done()
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Goroutine) OK() {
|
||||
g.finish(nil)
|
||||
}
|
||||
|
||||
func (g *Goroutine) Panic(err error) {
|
||||
g.finish(err)
|
||||
if g != g.TestGroup.main {
|
||||
runtime.Goexit()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TestGroup) Main() *Goroutine { return t.main }
|
||||
|
||||
func (t *TestGroup) Panic(err error) { t.Main().Panic(err) }
|
||||
|
||||
func (t *TestGroup) Go(name string, f func(*Goroutine)) *Goroutine {
|
||||
g := &Goroutine{t, name, false}
|
||||
t.Lock()
|
||||
t.WaitGroup.Add(1)
|
||||
t.running = append(t.running, g)
|
||||
t.Unlock()
|
||||
go f(g)
|
||||
return g
|
||||
}
|
||||
|
||||
func (t *TestGroup) Wait(procs... *Run) {
|
||||
t.Main().OK()
|
||||
t.WaitGroup.Wait()
|
||||
for _, p := range procs {
|
||||
if err := p.Wait(); err != nil {
|
||||
t.errors = append(t.errors, err)
|
||||
}
|
||||
}
|
||||
for _, err := range t.errors {
|
||||
fmt.Println(":ERROR:", err)
|
||||
}
|
||||
for _, err := range t.nonerrors {
|
||||
fmt.Println("(ERROR)", err)
|
||||
}
|
||||
if len(t.errors) != 0 {
|
||||
t.Fail("Test failed with", len(t.errors), "errors")
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue