summaryrefslogtreecommitdiff
path: root/src/mongo/gotools/common/archive/parser_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/gotools/common/archive/parser_test.go')
-rw-r--r--src/mongo/gotools/common/archive/parser_test.go150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/mongo/gotools/common/archive/parser_test.go b/src/mongo/gotools/common/archive/parser_test.go
new file mode 100644
index 00000000000..dba7e1d0263
--- /dev/null
+++ b/src/mongo/gotools/common/archive/parser_test.go
@@ -0,0 +1,150 @@
+package archive
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "testing"
+
+ . "github.com/smartystreets/goconvey/convey"
+ "gopkg.in/mgo.v2/bson"
+)
+
+type testConsumer struct {
+ headers []string // header data
+ bodies []string // body data
+ eof bool
+}
+
+func (tc *testConsumer) HeaderBSON(b []byte) error {
+ ss := strStruct{}
+ err := bson.Unmarshal(b, &ss)
+ tc.headers = append(tc.headers, ss.Str)
+ return err
+}
+
+func (tc *testConsumer) BodyBSON(b []byte) error {
+ ss := strStruct{}
+ err := bson.Unmarshal(b, &ss)
+ tc.bodies = append(tc.bodies, ss.Str)
+ return err
+}
+
+func (tc *testConsumer) End() (err error) {
+ if tc.eof {
+ err = fmt.Errorf("double end")
+ }
+ tc.eof = true
+ return err
+}
+
+type strStruct struct {
+ Str string
+}
+
+var term = []byte{0xFF, 0xFF, 0xFF, 0xFF}
+var notTerm = []byte{0xFF, 0xFF, 0xFF, 0xFE}
+
+func TestParsing(t *testing.T) {
+
+ Convey("With a parser with a simple parser consumer", t, func() {
+ tc := &testConsumer{}
+ parser := Parser{}
+ Convey("a well formed header and body data parse correctly", func() {
+ buf := bytes.Buffer{}
+ b, _ := bson.Marshal(strStruct{"header"})
+ buf.Write(b)
+ b, _ = bson.Marshal(strStruct{"body"})
+ buf.Write(b)
+ buf.Write(term)
+ parser.In = &buf
+ err := parser.ReadBlock(tc)
+ So(err, ShouldBeNil)
+ So(tc.eof, ShouldBeFalse)
+ So(tc.headers[0], ShouldEqual, "header")
+ So(tc.bodies[0], ShouldEqual, "body")
+
+ err = parser.ReadBlock(tc)
+ So(err, ShouldEqual, io.EOF)
+ So(tc.eof, ShouldBeTrue)
+ })
+ Convey("a well formed header and multiple body datas parse correctly", func() {
+ buf := bytes.Buffer{}
+ b, _ := bson.Marshal(strStruct{"header"})
+ buf.Write(b)
+ b, _ = bson.Marshal(strStruct{"body0"})
+ buf.Write(b)
+ b, _ = bson.Marshal(strStruct{"body1"})
+ buf.Write(b)
+ b, _ = bson.Marshal(strStruct{"body2"})
+ buf.Write(b)
+ buf.Write(term)
+ parser.In = &buf
+ err := parser.ReadBlock(tc)
+ So(err, ShouldBeNil)
+ So(tc.eof, ShouldBeFalse)
+ So(tc.headers[0], ShouldEqual, "header")
+ So(tc.bodies[0], ShouldEqual, "body0")
+ So(tc.bodies[1], ShouldEqual, "body1")
+ So(tc.bodies[2], ShouldEqual, "body2")
+
+ err = parser.ReadBlock(tc)
+ So(err, ShouldEqual, io.EOF)
+ So(tc.eof, ShouldBeTrue)
+ })
+ Convey("an incorrect terminator should cause an error", func() {
+ buf := bytes.Buffer{}
+ b, _ := bson.Marshal(strStruct{"header"})
+ buf.Write(b)
+ b, _ = bson.Marshal(strStruct{"body"})
+ buf.Write(b)
+ buf.Write(notTerm)
+ parser.In = &buf
+ err := parser.ReadBlock(tc)
+ So(err, ShouldNotBeNil)
+ })
+ Convey("an empty block should result in EOF", func() {
+ buf := bytes.Buffer{}
+ parser.In = &buf
+ err := parser.ReadBlock(tc)
+ So(err, ShouldEqual, io.EOF)
+ So(tc.eof, ShouldBeTrue)
+ })
+ Convey("an error comming from the consumer should propigate through the parser", func() {
+ tc.eof = true
+ buf := bytes.Buffer{}
+ parser.In = &buf
+ err := parser.ReadBlock(tc)
+ So(err.Error(), ShouldContainSubstring, "double end")
+ })
+ Convey("a partial block should result in a non-EOF error", func() {
+ buf := bytes.Buffer{}
+ b, _ := bson.Marshal(strStruct{"header"})
+ buf.Write(b)
+ b, _ = bson.Marshal(strStruct{"body"})
+ buf.Write(b)
+ parser.In = &buf
+ err := parser.ReadBlock(tc)
+ So(err, ShouldNotBeNil)
+ So(tc.eof, ShouldBeFalse)
+ So(tc.headers[0], ShouldEqual, "header")
+ So(tc.bodies[0], ShouldEqual, "body")
+ })
+ Convey("a block with a missing terminator shoud result in a non-EOF error", func() {
+ buf := bytes.Buffer{}
+ b, _ := bson.Marshal(strStruct{"header"})
+ buf.Write(b)
+ b, _ = bson.Marshal(strStruct{"body"})
+ buf.Write(b[:len(b)-1])
+ buf.Write([]byte{0x01})
+ buf.Write(notTerm)
+ parser.In = &buf
+ err := parser.ReadBlock(tc)
+ So(err, ShouldNotBeNil)
+ So(tc.eof, ShouldBeFalse)
+ So(tc.headers[0], ShouldEqual, "header")
+ So(tc.bodies, ShouldBeNil)
+ })
+ })
+ return
+}