| Index: common/cmpbin/string_test.go
|
| diff --git a/common/cmpbin/string_test.go b/common/cmpbin/string_test.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b39d9116a814054c265fadea664b492f39f11b61
|
| --- /dev/null
|
| +++ b/common/cmpbin/string_test.go
|
| @@ -0,0 +1,262 @@
|
| +// Copyright 2015 The Chromium 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 cmpbin
|
| +
|
| +import (
|
| + "bytes"
|
| + "io"
|
| + "math/rand"
|
| + "sort"
|
| + "testing"
|
| +
|
| + . "github.com/smartystreets/goconvey/convey"
|
| +)
|
| +
|
| +func TestBytes(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + Convey("bytes", t, func() {
|
| + b := &bytes.Buffer{}
|
| + t := []byte("this is a test")
|
| +
|
| + Convey("good", func() {
|
| + _, err := WriteBytes(b, t)
|
| + So(err, ShouldBeNil)
|
| + exn := b.Len()
|
| + r, n, err := ReadBytes(b)
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, exn)
|
| + So(r, ShouldResemble, t)
|
| + })
|
| +
|
| + Convey("bad (truncated buffer)", func() {
|
| + _, err := WriteBytes(b, t)
|
| + So(err, ShouldBeNil)
|
| + bs := b.Bytes()[:b.Len()-4]
|
| + _, n, err := ReadBytes(bytes.NewBuffer(bs))
|
| + So(err, ShouldEqual, io.EOF)
|
| + So(n, ShouldEqual, len(bs))
|
| + })
|
| +
|
| + Convey("bad (bad varint)", func() {
|
| + _, n, err := ReadBytes(bytes.NewBuffer([]byte{b10001111}))
|
| + So(err, ShouldEqual, io.EOF)
|
| + So(n, ShouldEqual, 1)
|
| + })
|
| +
|
| + Convey("bad (huge data)", func() {
|
| + n, err := WriteBytes(b, make([]byte, 2*1024*1024+1))
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, ReadByteLimit+2)
|
| + _, n, err = ReadBytes(b)
|
| + So(err.Error(), ShouldContainSubstring, "too big!")
|
| + So(n, ShouldEqual, ReadByteLimit)
|
| + })
|
| +
|
| + Convey("bad (write errors)", func() {
|
| + _, err := WriteBytes(&fakeWriter{1}, t)
|
| + So(err.Error(), ShouldContainSubstring, "nope")
|
| +
|
| + // transition boundary
|
| + _, err = WriteBytes(&fakeWriter{7}, t)
|
| + So(err.Error(), ShouldContainSubstring, "nope")
|
| + })
|
| + })
|
| +}
|
| +
|
| +func TestStrings(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + Convey("strings", t, func() {
|
| + b := &bytes.Buffer{}
|
| + t := "this is a test"
|
| +
|
| + Convey("empty", func() {
|
| + n, err := WriteString(b, "")
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, 1)
|
| + So(b.Bytes(), ShouldResemble, []byte{0})
|
| + r, n, err := ReadString(b)
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, 1)
|
| + So(r, ShouldEqual, "")
|
| + })
|
| +
|
| + Convey("nulls", func() {
|
| + t := "\x00\x00\x00\x00\x00"
|
| + n, err := WriteString(b, t)
|
| + So(n, ShouldEqual, 6)
|
| + So(err, ShouldBeNil)
|
| + exn := b.Len()
|
| + r, n, err := ReadString(b)
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, exn)
|
| + So(r, ShouldEqual, t)
|
| + })
|
| +
|
| + Convey("bad (truncated buffer)", func() {
|
| + n, err := WriteString(b, t)
|
| + So(n, ShouldEqual, (len(t)*8)/7+1)
|
| + So(err, ShouldBeNil)
|
| + bs := b.Bytes()[:b.Len()-1]
|
| + _, n, err = ReadString(bytes.NewBuffer(bs))
|
| + So(err, ShouldEqual, io.EOF)
|
| + So(n, ShouldEqual, len(bs))
|
| + })
|
| +
|
| + Convey("single", func() {
|
| + n, err := WriteString(b, "1")
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, 2)
|
| + So(b.Bytes(), ShouldResemble, []byte{b00110001, b10000000})
|
| + r, n, err := ReadString(b)
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, 2)
|
| + So(r, ShouldEqual, "1")
|
| + })
|
| +
|
| + Convey("good", func() {
|
| + n, err := WriteString(b, t)
|
| + So(err, ShouldBeNil)
|
| + So(n, ShouldEqual, (len(t)*8)/7+1)
|
| + So(b.Bytes()[:8], ShouldResemble, []byte{
|
| + b01110101, b00110101, b00011011, b00101111, b00110011, b00000011,
|
| + b10100101, b11100111,
|
| + })
|
| + exn := b.Len()
|
| + r, n, err := ReadString(b)
|
| + So(err, ShouldBeNil)
|
| + So(len(r), ShouldEqual, len(t))
|
| + So(n, ShouldEqual, exn)
|
| + So(r, ShouldEqual, t)
|
| + })
|
| +
|
| + })
|
| +}
|
| +
|
| +// TODO(riannucci): make it [][]string instead
|
| +
|
| +func TestStringSortability(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + Convey("strings maintain sort order", t, func() {
|
| + special := []string{
|
| + "",
|
| + "\x00",
|
| + "\x00\x00",
|
| + "\x00\x00\x00",
|
| + "\x00\x00\x00\x00",
|
| + "\x00\x00\x00\x00\x00",
|
| + "\x00\x00\x00\x00\x01",
|
| + "\x00\x00\x00\x00\xFF",
|
| + "1234567",
|
| + "12345678",
|
| + "123456789",
|
| + string(make([]byte, 7*8)),
|
| + }
|
| + orig := make(sort.StringSlice, randomTestSize, randomTestSize+len(special))
|
| +
|
| + r := rand.New(rand.NewSource(*seed))
|
| + for i := range orig {
|
| + buf := make([]byte, r.Intn(100))
|
| + for j := range buf {
|
| + buf[j] = byte(r.Uint32()) // watch me not care!
|
| + }
|
| + orig[i] = string(buf)
|
| + }
|
| + orig = append(orig, special...)
|
| +
|
| + enc := make(sort.StringSlice, len(orig))
|
| + b := &bytes.Buffer{}
|
| + for i := range enc {
|
| + b.Reset()
|
| + _, err := WriteString(b, orig[i])
|
| + So(err, ShouldBeNil)
|
| + enc[i] = b.String()
|
| + }
|
| +
|
| + orig.Sort()
|
| + enc.Sort()
|
| +
|
| + for i := range orig {
|
| + decoded, _, err := ReadString(bytes.NewBufferString(enc[i]))
|
| + So(err, ShouldBeNil)
|
| + So(decoded, ShouldResemble, orig[i])
|
| + }
|
| + })
|
| +}
|
| +
|
| +type StringSliceSlice [][]string
|
| +
|
| +func (s StringSliceSlice) Len() int { return len(s) }
|
| +func (s StringSliceSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
| +func (s StringSliceSlice) Less(i, j int) bool {
|
| + a, b := s[i], s[j]
|
| + lim := len(a)
|
| + if len(b) < lim {
|
| + lim = len(b)
|
| + }
|
| + for k := 0; k < lim; k++ {
|
| + if a[k] > b[k] {
|
| + return false
|
| + } else if a[k] < b[k] {
|
| + return true
|
| + }
|
| + }
|
| + return len(a) < len(b)
|
| +}
|
| +
|
| +func TestConcatenatedStringSortability(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + Convey("concatenated strings maintain sort order", t, func() {
|
| + orig := make(StringSliceSlice, randomTestSize)
|
| +
|
| + r := rand.New(rand.NewSource(*seed))
|
| + for i := range orig {
|
| + count := r.Intn(10)
|
| + for j := 0; j < count; j++ {
|
| + buf := make([]byte, r.Intn(100))
|
| + for j := range buf {
|
| + buf[j] = byte(r.Uint32()) // watch me not care!
|
| + }
|
| + orig[i] = append(orig[i], string(buf))
|
| + }
|
| + }
|
| + orig = append(orig, [][]string{
|
| + nil,
|
| + {"", "aaa"},
|
| + {"a", "aa"},
|
| + {"aa", "a"},
|
| + }...)
|
| +
|
| + enc := make(sort.StringSlice, len(orig))
|
| + b := &bytes.Buffer{}
|
| + for i, slice := range orig {
|
| + b.Reset()
|
| + for _, s := range slice {
|
| + _, err := WriteString(b, s)
|
| + So(err, ShouldBeNil)
|
| + }
|
| + enc[i] = b.String()
|
| + }
|
| +
|
| + sort.Sort(orig)
|
| + enc.Sort()
|
| +
|
| + for i := range orig {
|
| + decoded := []string(nil)
|
| + buf := bytes.NewBufferString(enc[i])
|
| + for {
|
| + dec, _, err := ReadString(buf)
|
| + if err != nil {
|
| + break
|
| + }
|
| + decoded = append(decoded, dec)
|
| + }
|
| + So(decoded, ShouldResemble, orig[i])
|
| + }
|
| + })
|
| +}
|
|
|