mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-20 03:51:00 +00:00
65aaa607ab
Change made by: - running "gvt fetch" on each of the packages mentioned in Godeps/Godeps.json - `rm -rf Godeps` - tweaking the build scripts to not mention Godeps - tweaking the build scripts to test `./lib/...`, `./cmd/...` explicitly (to avoid testing vendor) - tweaking the build scripts to not juggle GOPATH for Godeps and instead set GO15VENDOREXPERIMENT. This also results in some updated packages at the same time I bet. Building with Go 1.3 and 1.4 still *works* but won't use our vendored dependencies - the user needs to have the actual packages in their GOPATH then, which they'll get with a normal "go get". Building with Go 1.6+ will get our vendored dependencies by default even when not using our build script, which is nice. By doing this we gain some freedom in that we can pick and choose manually what to include in vendor, as it's not based on just dependency analysis of our own code. This is also a risk as we might pick up dependencies we are unaware of, as the build may work locally with those packages present in GOPATH. On the other hand the build server will detect this as it has no packages in it's GOPATH beyond what is included in the repo. Recommended tool to manage dependencies is github.com/FiloSottile/gvt.
370 lines
9.3 KiB
Go
370 lines
9.3 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package util
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"math/rand"
|
|
"runtime"
|
|
"testing"
|
|
)
|
|
|
|
const N = 10000 // make this bigger for a larger (and slower) test
|
|
var data string // test data for write tests
|
|
var testBytes []byte // test data; same as data but as a slice.
|
|
|
|
func init() {
|
|
testBytes = make([]byte, N)
|
|
for i := 0; i < N; i++ {
|
|
testBytes[i] = 'a' + byte(i%26)
|
|
}
|
|
data = string(testBytes)
|
|
}
|
|
|
|
// Verify that contents of buf match the string s.
|
|
func check(t *testing.T, testname string, buf *Buffer, s string) {
|
|
bytes := buf.Bytes()
|
|
str := buf.String()
|
|
if buf.Len() != len(bytes) {
|
|
t.Errorf("%s: buf.Len() == %d, len(buf.Bytes()) == %d", testname, buf.Len(), len(bytes))
|
|
}
|
|
|
|
if buf.Len() != len(str) {
|
|
t.Errorf("%s: buf.Len() == %d, len(buf.String()) == %d", testname, buf.Len(), len(str))
|
|
}
|
|
|
|
if buf.Len() != len(s) {
|
|
t.Errorf("%s: buf.Len() == %d, len(s) == %d", testname, buf.Len(), len(s))
|
|
}
|
|
|
|
if string(bytes) != s {
|
|
t.Errorf("%s: string(buf.Bytes()) == %q, s == %q", testname, string(bytes), s)
|
|
}
|
|
}
|
|
|
|
// Fill buf through n writes of byte slice fub.
|
|
// The initial contents of buf corresponds to the string s;
|
|
// the result is the final contents of buf returned as a string.
|
|
func fillBytes(t *testing.T, testname string, buf *Buffer, s string, n int, fub []byte) string {
|
|
check(t, testname+" (fill 1)", buf, s)
|
|
for ; n > 0; n-- {
|
|
m, err := buf.Write(fub)
|
|
if m != len(fub) {
|
|
t.Errorf(testname+" (fill 2): m == %d, expected %d", m, len(fub))
|
|
}
|
|
if err != nil {
|
|
t.Errorf(testname+" (fill 3): err should always be nil, found err == %s", err)
|
|
}
|
|
s += string(fub)
|
|
check(t, testname+" (fill 4)", buf, s)
|
|
}
|
|
return s
|
|
}
|
|
|
|
func TestNewBuffer(t *testing.T) {
|
|
buf := NewBuffer(testBytes)
|
|
check(t, "NewBuffer", buf, data)
|
|
}
|
|
|
|
// Empty buf through repeated reads into fub.
|
|
// The initial contents of buf corresponds to the string s.
|
|
func empty(t *testing.T, testname string, buf *Buffer, s string, fub []byte) {
|
|
check(t, testname+" (empty 1)", buf, s)
|
|
|
|
for {
|
|
n, err := buf.Read(fub)
|
|
if n == 0 {
|
|
break
|
|
}
|
|
if err != nil {
|
|
t.Errorf(testname+" (empty 2): err should always be nil, found err == %s", err)
|
|
}
|
|
s = s[n:]
|
|
check(t, testname+" (empty 3)", buf, s)
|
|
}
|
|
|
|
check(t, testname+" (empty 4)", buf, "")
|
|
}
|
|
|
|
func TestBasicOperations(t *testing.T) {
|
|
var buf Buffer
|
|
|
|
for i := 0; i < 5; i++ {
|
|
check(t, "TestBasicOperations (1)", &buf, "")
|
|
|
|
buf.Reset()
|
|
check(t, "TestBasicOperations (2)", &buf, "")
|
|
|
|
buf.Truncate(0)
|
|
check(t, "TestBasicOperations (3)", &buf, "")
|
|
|
|
n, err := buf.Write([]byte(data[0:1]))
|
|
if n != 1 {
|
|
t.Errorf("wrote 1 byte, but n == %d", n)
|
|
}
|
|
if err != nil {
|
|
t.Errorf("err should always be nil, but err == %s", err)
|
|
}
|
|
check(t, "TestBasicOperations (4)", &buf, "a")
|
|
|
|
buf.WriteByte(data[1])
|
|
check(t, "TestBasicOperations (5)", &buf, "ab")
|
|
|
|
n, err = buf.Write([]byte(data[2:26]))
|
|
if n != 24 {
|
|
t.Errorf("wrote 25 bytes, but n == %d", n)
|
|
}
|
|
check(t, "TestBasicOperations (6)", &buf, string(data[0:26]))
|
|
|
|
buf.Truncate(26)
|
|
check(t, "TestBasicOperations (7)", &buf, string(data[0:26]))
|
|
|
|
buf.Truncate(20)
|
|
check(t, "TestBasicOperations (8)", &buf, string(data[0:20]))
|
|
|
|
empty(t, "TestBasicOperations (9)", &buf, string(data[0:20]), make([]byte, 5))
|
|
empty(t, "TestBasicOperations (10)", &buf, "", make([]byte, 100))
|
|
|
|
buf.WriteByte(data[1])
|
|
c, err := buf.ReadByte()
|
|
if err != nil {
|
|
t.Error("ReadByte unexpected eof")
|
|
}
|
|
if c != data[1] {
|
|
t.Errorf("ReadByte wrong value c=%v", c)
|
|
}
|
|
c, err = buf.ReadByte()
|
|
if err == nil {
|
|
t.Error("ReadByte unexpected not eof")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLargeByteWrites(t *testing.T) {
|
|
var buf Buffer
|
|
limit := 30
|
|
if testing.Short() {
|
|
limit = 9
|
|
}
|
|
for i := 3; i < limit; i += 3 {
|
|
s := fillBytes(t, "TestLargeWrites (1)", &buf, "", 5, testBytes)
|
|
empty(t, "TestLargeByteWrites (2)", &buf, s, make([]byte, len(data)/i))
|
|
}
|
|
check(t, "TestLargeByteWrites (3)", &buf, "")
|
|
}
|
|
|
|
func TestLargeByteReads(t *testing.T) {
|
|
var buf Buffer
|
|
for i := 3; i < 30; i += 3 {
|
|
s := fillBytes(t, "TestLargeReads (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
|
|
empty(t, "TestLargeReads (2)", &buf, s, make([]byte, len(data)))
|
|
}
|
|
check(t, "TestLargeByteReads (3)", &buf, "")
|
|
}
|
|
|
|
func TestMixedReadsAndWrites(t *testing.T) {
|
|
var buf Buffer
|
|
s := ""
|
|
for i := 0; i < 50; i++ {
|
|
wlen := rand.Intn(len(data))
|
|
s = fillBytes(t, "TestMixedReadsAndWrites (1)", &buf, s, 1, testBytes[0:wlen])
|
|
rlen := rand.Intn(len(data))
|
|
fub := make([]byte, rlen)
|
|
n, _ := buf.Read(fub)
|
|
s = s[n:]
|
|
}
|
|
empty(t, "TestMixedReadsAndWrites (2)", &buf, s, make([]byte, buf.Len()))
|
|
}
|
|
|
|
func TestNil(t *testing.T) {
|
|
var b *Buffer
|
|
if b.String() != "<nil>" {
|
|
t.Errorf("expected <nil>; got %q", b.String())
|
|
}
|
|
}
|
|
|
|
func TestReadFrom(t *testing.T) {
|
|
var buf Buffer
|
|
for i := 3; i < 30; i += 3 {
|
|
s := fillBytes(t, "TestReadFrom (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
|
|
var b Buffer
|
|
b.ReadFrom(&buf)
|
|
empty(t, "TestReadFrom (2)", &b, s, make([]byte, len(data)))
|
|
}
|
|
}
|
|
|
|
func TestWriteTo(t *testing.T) {
|
|
var buf Buffer
|
|
for i := 3; i < 30; i += 3 {
|
|
s := fillBytes(t, "TestWriteTo (1)", &buf, "", 5, testBytes[0:len(testBytes)/i])
|
|
var b Buffer
|
|
buf.WriteTo(&b)
|
|
empty(t, "TestWriteTo (2)", &b, s, make([]byte, len(data)))
|
|
}
|
|
}
|
|
|
|
func TestNext(t *testing.T) {
|
|
b := []byte{0, 1, 2, 3, 4}
|
|
tmp := make([]byte, 5)
|
|
for i := 0; i <= 5; i++ {
|
|
for j := i; j <= 5; j++ {
|
|
for k := 0; k <= 6; k++ {
|
|
// 0 <= i <= j <= 5; 0 <= k <= 6
|
|
// Check that if we start with a buffer
|
|
// of length j at offset i and ask for
|
|
// Next(k), we get the right bytes.
|
|
buf := NewBuffer(b[0:j])
|
|
n, _ := buf.Read(tmp[0:i])
|
|
if n != i {
|
|
t.Fatalf("Read %d returned %d", i, n)
|
|
}
|
|
bb := buf.Next(k)
|
|
want := k
|
|
if want > j-i {
|
|
want = j - i
|
|
}
|
|
if len(bb) != want {
|
|
t.Fatalf("in %d,%d: len(Next(%d)) == %d", i, j, k, len(bb))
|
|
}
|
|
for l, v := range bb {
|
|
if v != byte(l+i) {
|
|
t.Fatalf("in %d,%d: Next(%d)[%d] = %d, want %d", i, j, k, l, v, l+i)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var readBytesTests = []struct {
|
|
buffer string
|
|
delim byte
|
|
expected []string
|
|
err error
|
|
}{
|
|
{"", 0, []string{""}, io.EOF},
|
|
{"a\x00", 0, []string{"a\x00"}, nil},
|
|
{"abbbaaaba", 'b', []string{"ab", "b", "b", "aaab"}, nil},
|
|
{"hello\x01world", 1, []string{"hello\x01"}, nil},
|
|
{"foo\nbar", 0, []string{"foo\nbar"}, io.EOF},
|
|
{"alpha\nbeta\ngamma\n", '\n', []string{"alpha\n", "beta\n", "gamma\n"}, nil},
|
|
{"alpha\nbeta\ngamma", '\n', []string{"alpha\n", "beta\n", "gamma"}, io.EOF},
|
|
}
|
|
|
|
func TestReadBytes(t *testing.T) {
|
|
for _, test := range readBytesTests {
|
|
buf := NewBuffer([]byte(test.buffer))
|
|
var err error
|
|
for _, expected := range test.expected {
|
|
var bytes []byte
|
|
bytes, err = buf.ReadBytes(test.delim)
|
|
if string(bytes) != expected {
|
|
t.Errorf("expected %q, got %q", expected, bytes)
|
|
}
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
if err != test.err {
|
|
t.Errorf("expected error %v, got %v", test.err, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGrow(t *testing.T) {
|
|
x := []byte{'x'}
|
|
y := []byte{'y'}
|
|
tmp := make([]byte, 72)
|
|
for _, startLen := range []int{0, 100, 1000, 10000, 100000} {
|
|
xBytes := bytes.Repeat(x, startLen)
|
|
for _, growLen := range []int{0, 100, 1000, 10000, 100000} {
|
|
buf := NewBuffer(xBytes)
|
|
// If we read, this affects buf.off, which is good to test.
|
|
readBytes, _ := buf.Read(tmp)
|
|
buf.Grow(growLen)
|
|
yBytes := bytes.Repeat(y, growLen)
|
|
// Check no allocation occurs in write, as long as we're single-threaded.
|
|
var m1, m2 runtime.MemStats
|
|
runtime.ReadMemStats(&m1)
|
|
buf.Write(yBytes)
|
|
runtime.ReadMemStats(&m2)
|
|
if runtime.GOMAXPROCS(-1) == 1 && m1.Mallocs != m2.Mallocs {
|
|
t.Errorf("allocation occurred during write")
|
|
}
|
|
// Check that buffer has correct data.
|
|
if !bytes.Equal(buf.Bytes()[0:startLen-readBytes], xBytes[readBytes:]) {
|
|
t.Errorf("bad initial data at %d %d", startLen, growLen)
|
|
}
|
|
if !bytes.Equal(buf.Bytes()[startLen-readBytes:startLen-readBytes+growLen], yBytes) {
|
|
t.Errorf("bad written data at %d %d", startLen, growLen)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Was a bug: used to give EOF reading empty slice at EOF.
|
|
func TestReadEmptyAtEOF(t *testing.T) {
|
|
b := new(Buffer)
|
|
slice := make([]byte, 0)
|
|
n, err := b.Read(slice)
|
|
if err != nil {
|
|
t.Errorf("read error: %v", err)
|
|
}
|
|
if n != 0 {
|
|
t.Errorf("wrong count; got %d want 0", n)
|
|
}
|
|
}
|
|
|
|
// Tests that we occasionally compact. Issue 5154.
|
|
func TestBufferGrowth(t *testing.T) {
|
|
var b Buffer
|
|
buf := make([]byte, 1024)
|
|
b.Write(buf[0:1])
|
|
var cap0 int
|
|
for i := 0; i < 5<<10; i++ {
|
|
b.Write(buf)
|
|
b.Read(buf)
|
|
if i == 0 {
|
|
cap0 = cap(b.buf)
|
|
}
|
|
}
|
|
cap1 := cap(b.buf)
|
|
// (*Buffer).grow allows for 2x capacity slop before sliding,
|
|
// so set our error threshold at 3x.
|
|
if cap1 > cap0*3 {
|
|
t.Errorf("buffer cap = %d; too big (grew from %d)", cap1, cap0)
|
|
}
|
|
}
|
|
|
|
// From Issue 5154.
|
|
func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
|
|
buf := make([]byte, 1024)
|
|
for i := 0; i < b.N; i++ {
|
|
var b Buffer
|
|
b.Write(buf[0:1])
|
|
for i := 0; i < 5<<10; i++ {
|
|
b.Write(buf)
|
|
b.Read(buf)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check that we don't compact too often. From Issue 5154.
|
|
func BenchmarkBufferFullSmallReads(b *testing.B) {
|
|
buf := make([]byte, 1024)
|
|
for i := 0; i < b.N; i++ {
|
|
var b Buffer
|
|
b.Write(buf)
|
|
for b.Len()+20 < cap(b.buf) {
|
|
b.Write(buf[:10])
|
|
}
|
|
for i := 0; i < 5<<10; i++ {
|
|
b.Read(buf[:1])
|
|
b.Write(buf[:1])
|
|
}
|
|
}
|
|
}
|