1
2
3
4
5
6
7 package bsonrw
8
9 import (
10 "errors"
11 "fmt"
12 "io"
13 "strings"
14 "testing"
15
16 "github.com/google/go-cmp/cmp"
17 "go.mongodb.org/mongo-driver/bson/bsontype"
18 )
19
20 func TestExtJSONReader(t *testing.T) {
21 t.Run("ReadDocument", func(t *testing.T) {
22 t.Run("EmbeddedDocument", func(t *testing.T) {
23 ejvr := &extJSONValueReader{
24 stack: []ejvrState{
25 {mode: mTopLevel},
26 {mode: mElement, vType: bsontype.Boolean},
27 },
28 frame: 1,
29 }
30
31 ejvr.stack[1].mode = mArray
32 wanterr := ejvr.invalidTransitionErr(mDocument, "ReadDocument", []mode{mTopLevel, mElement, mValue})
33 _, err := ejvr.ReadDocument()
34 if err == nil || err.Error() != wanterr.Error() {
35 t.Errorf("Incorrect returned error. got %v; want %v", err, wanterr)
36 }
37
38 })
39 })
40
41 t.Run("invalid transition", func(t *testing.T) {
42 t.Run("Skip", func(t *testing.T) {
43 ejvr := &extJSONValueReader{stack: []ejvrState{{mode: mTopLevel}}}
44 wanterr := (&extJSONValueReader{stack: []ejvrState{{mode: mTopLevel}}}).invalidTransitionErr(0, "Skip", []mode{mElement, mValue})
45 goterr := ejvr.Skip()
46 if !cmp.Equal(goterr, wanterr, cmp.Comparer(compareErrors)) {
47 t.Errorf("Expected correct invalid transition error. got %v; want %v", goterr, wanterr)
48 }
49 })
50 })
51 }
52
53 func TestReadMultipleTopLevelDocuments(t *testing.T) {
54 testCases := []struct {
55 name string
56 input string
57 expected [][]byte
58 }{
59 {
60 "single top-level document",
61 "{\"foo\":1}",
62 [][]byte{
63 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
64 },
65 },
66 {
67 "single top-level document with leading and trailing whitespace",
68 "\n\n {\"foo\":1} \n",
69 [][]byte{
70 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
71 },
72 },
73 {
74 "two top-level documents",
75 "{\"foo\":1}{\"foo\":2}",
76 [][]byte{
77 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
78 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x02, 0x00, 0x00, 0x00, 0x00},
79 },
80 },
81 {
82 "two top-level documents with leading and trailing whitespace and whitespace separation ",
83 "\n\n {\"foo\":1}\n{\"foo\":2}\n ",
84 [][]byte{
85 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
86 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x02, 0x00, 0x00, 0x00, 0x00},
87 },
88 },
89 {
90 "top-level array with single document",
91 "[{\"foo\":1}]",
92 [][]byte{
93 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
94 },
95 },
96 {
97 "top-level array with 2 documents",
98 "[{\"foo\":1},{\"foo\":2}]",
99 [][]byte{
100 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x01, 0x00, 0x00, 0x00, 0x00},
101 {0x0E, 0x00, 0x00, 0x00, 0x10, 'f', 'o', 'o', 0x00, 0x02, 0x00, 0x00, 0x00, 0x00},
102 },
103 },
104 }
105
106 for _, tc := range testCases {
107 t.Run(tc.name, func(t *testing.T) {
108 r := strings.NewReader(tc.input)
109 vr, err := NewExtJSONValueReader(r, false)
110 if err != nil {
111 t.Fatalf("expected no error, but got %v", err)
112 }
113
114 actual, err := readAllDocuments(vr)
115 if err != nil {
116 t.Fatalf("expected no error, but got %v", err)
117 }
118
119 if diff := cmp.Diff(tc.expected, actual); diff != "" {
120 t.Fatalf("expected does not match actual: %v", diff)
121 }
122 })
123 }
124 }
125
126 func readAllDocuments(vr ValueReader) ([][]byte, error) {
127 c := NewCopier()
128 var actual [][]byte
129
130 switch vr.Type() {
131 case bsontype.EmbeddedDocument:
132 for {
133 result, err := c.CopyDocumentToBytes(vr)
134 if err != nil {
135 if errors.Is(err, io.EOF) {
136 break
137 }
138 return nil, err
139 }
140
141 actual = append(actual, result)
142 }
143 case bsontype.Array:
144 ar, err := vr.ReadArray()
145 if err != nil {
146 return nil, err
147 }
148 for {
149 evr, err := ar.ReadValue()
150 if err != nil {
151 if errors.Is(err, ErrEOA) {
152 break
153 }
154 return nil, err
155 }
156
157 result, err := c.CopyDocumentToBytes(evr)
158 if err != nil {
159 return nil, err
160 }
161
162 actual = append(actual, result)
163 }
164 default:
165 return nil, fmt.Errorf("expected an array or a document, but got %s", vr.Type())
166 }
167
168 return actual, nil
169 }
170
View as plain text