Repository: genjidb/genji
Pull request #400 (2021-05-11 16:13:59)

Use go-cmp to improve the output of the generated sql tests
Here what it outputs now, when there is a type difference between what is want and what we got :) 

I had to resort to using basic structure to represent the data because if we did not, we'd get a diff with both documents in their entirety, which defeats the purpose of having pretty diffs. 

I think we can do **much** better, but it's a fairly acceptable start :) 


        --- FAIL: TestGenInsertStatements/insert_with_types_constraints/CREATE_TABLE_test_tc( (0.00s)
            gen_insert_statements_test.go:766: 
                	Error Trace:	gen.go:118
                	            				gen_insert_statements_test.go:766
                	Error:      	mismatched documents, (-want, +got)
                	Test:       	TestGenInsertStatements/insert_with_types_constraints/CREATE_TABLE_test_tc(
                	Messages:   	  []*testutil.Val{
                	            	  	&{
                	            	  		Type: "document",
                	            	  		V: []testutil.Field{
                	            	  			... // 4 identical elements
                	            	  			{Name: "byt", V: {Type: "blob", V: string("[98 121 116 101 115 86 97 108 117 101]")}},
                	            	  			{Name: "t", V: {Type: "text", V: string(`"text"`)}},
                	            	  			{
                	            	  				Name: "a",
                	            	  				V: testutil.Val{
                	            	  					Type: "array",
                	            	  					V: []testutil.Val{
                	            	  						{
                	            	- 							Type: "integer",
                	            	+ 							Type: "double",
                	            	  							V:    string("1"),
                	            	  						},
                	            	  						{Type: "text", V: string(`"foo"`)},
                	            	  						{Type: "bool", V: string("true")},
                	            	  					},
                	            	  				},
                	            	  			},
                	            	  			{Name: "d", V: {Type: "document", V: []testutil.Field{{Name: "foo", V: {Type: "text", V: string(`"bar"`)}}}}},
                	            	  		},
                	            	  	},
                	            	  }




Patch:
diff --git a/cmd/genji/go.sum b/cmd/genji/go.sum
index e6fee4ca..2f2a5aaa 100644
--- a/cmd/genji/go.sum
+++ b/cmd/genji/go.sum
@@ -54,6 +54,8 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
 github.com/google/flatbuffers v1.12.0 h1:/PtAHvnBY4Kqnx/xCQ3OIV9uYcSFGScBsWI3Oogeh6w=
 github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-dap v0.2.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@@ -192,6 +194,7 @@ golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
diff --git a/engine/badgerengine/go.sum b/engine/badgerengine/go.sum
index 00481494..53644204 100644
--- a/engine/badgerengine/go.sum
+++ b/engine/badgerengine/go.sum
@@ -43,6 +43,8 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
 github.com/google/flatbuffers v1.12.0 h1:/PtAHvnBY4Kqnx/xCQ3OIV9uYcSFGScBsWI3Oogeh6w=
 github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-dap v0.2.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
 github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
@@ -145,6 +147,7 @@ golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
diff --git a/fuzz/go.sum b/fuzz/go.sum
index 08782e61..ee0d45af 100644
--- a/fuzz/go.sum
+++ b/fuzz/go.sum
@@ -9,6 +9,8 @@ github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE
 github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
 github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s=
@@ -52,6 +54,7 @@ golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
diff --git a/go.mod b/go.mod
index 63bd5c08..d48c7a05 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.16
 require (
 	github.com/buger/jsonparser v1.1.1
 	github.com/google/btree v1.0.0
+	github.com/google/go-cmp v0.5.5 // indirect
 	github.com/stretchr/testify v1.7.0
 	github.com/vmihailenco/msgpack/v5 v5.1.4
 	go.etcd.io/bbolt v1.3.5
diff --git a/go.sum b/go.sum
index 07271749..503cf490 100644
--- a/go.sum
+++ b/go.sum
@@ -4,6 +4,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -41,6 +43,7 @@ golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
 golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=


Test patch:
diff --git a/query/gen_insert_statements_test.go b/query/gen_insert_statements_test.go
index cadb2ac8..4854516b 100644
--- a/query/gen_insert_statements_test.go
+++ b/query/gen_insert_statements_test.go
@@ -162,7 +162,7 @@ SELECT pk(), * FROM test;
   "pk()": 1,
   "a": "a",
   "b":"b",
-  "c": [1 , 2, 3]
+  "c": [1.0, 2.0, 3.0]
 }
 `
 			testutil.RequireStreamEq(t, raw, res)
@@ -192,8 +192,8 @@ SELECT pk(), * FROM test;
   "a": "a",
   "b": "b",
   "c": {
-    "c": 1,
-    "d": 2
+    "c": 1.0,
+    "d": 2.0
   }
 }
 `
@@ -251,10 +251,9 @@ SELECT pk(), * FROM test;
 {
   "pk()": 1,
   "a": [
-    1,
-    2
-,
-    3
+    1.0,
+    2.0,
+    3.0
   ]
 }
 `
@@ -334,7 +333,7 @@ SELECT pk(), * FROM test;
 			require.NoError(t, err)
 			defer res.Close()
 			raw := `
-{"pk()":1,"a":400,"b":1600}
+{"pk()":1,"a":400.0,"b":1600.0}
 `
 			testutil.RequireStreamEq(t, raw, res)
 		})
@@ -380,7 +379,7 @@ SELECT pk(), * FROM test_idx;
   "pk()": 1,
   "a": "a",
   "b": "b",
-  "c":"c"
+  "c": "c"
 }
 `
 			testutil.RequireStreamEq(t, raw, res)
@@ -475,7 +474,7 @@ SELECT pk(), * FROM test_idx;
   "pk()": 1,
   "a": "a",
   "b":"b",
-  "c": [1 , 2, 3]
+  "c": [1.0, 2.0, 3.0]
 }
 `
 			testutil.RequireStreamEq(t, raw, res)
@@ -505,8 +504,8 @@ SELECT pk(), * FROM test_idx;
   "a": "a",
   "b": "b",
   "c": {
-    "c": 1,
-    "d": 2
+    "c": 1.0,
+    "d": 2.0
   }
 }
 `
@@ -564,10 +563,9 @@ SELECT pk(), * FROM test_idx;
 {
   "pk()": 1,
   "a": [
-    1,
-    2
-,
-    3
+    1.0,
+    2.0,
+    3.0
   ]
 }
 `
@@ -647,7 +645,7 @@ SELECT pk(), * FROM test_idx;
 			require.NoError(t, err)
 			defer res.Close()
 			raw := `
-{"pk()":1,"a":400,"b":1600}
+{"pk()":1,"a":400.0,"b":1600.0}
 `
 			testutil.RequireStreamEq(t, raw, res)
 		})
@@ -756,7 +754,7 @@ SELECT * FROM test_tc;
   "byt": CAST("Ynl0ZXNWYWx1ZQ==" AS BYTES),
   "t": "text",
   "a": [
-    1,
+    1.0,
     "foo",
     true
   ],
diff --git a/query/gen_insert_statements_test.sql b/query/gen_insert_statements_test.sql
index f2081e69..8e049d3e 100644
--- a/query/gen_insert_statements_test.sql
+++ b/query/gen_insert_statements_test.sql
@@ -49,7 +49,7 @@ SELECT pk(), * FROM test;
   "pk()": 1,
   "a": "a",
   "b":"b",
-  "c": [1 , 2, 3]
+  "c": [1.0, 2.0, 3.0]
 }
 */
 
@@ -62,8 +62,8 @@ SELECT pk(), * FROM test;
   "a": "a",
   "b": "b",
   "c": {
-    "c": 1,
-    "d": 2
+    "c": 1.0,
+    "d": 2.0
   }
 }
 */
@@ -87,10 +87,9 @@ SELECT pk(), * FROM test;
 {
   "pk()": 1,
   "a": [
-    1,
-    2
-,
-    3
+    1.0,
+    2.0,
+    3.0
   ]
 }
 */
@@ -120,7 +119,7 @@ SELECT pk(), * FROM test;
 INSERT INTO test VALUES {a: 400, b: a * 4};
 SELECT pk(), * FROM test;
 /* result:
-{"pk()":1,"a":400,"b":1600}
+{"pk()":1,"a":400.0,"b":1600.0}
 */
 
 -- with indexes
@@ -136,7 +135,7 @@ SELECT pk(), * FROM test_idx;
   "pk()": 1,
   "a": "a",
   "b": "b",
-  "c":"c"
+  "c": "c"
 }
 */
 
@@ -167,7 +166,7 @@ SELECT pk(), * FROM test_idx;
   "pk()": 1,
   "a": "a",
   "b":"b",
-  "c": [1 , 2, 3]
+  "c": [1.0, 2.0, 3.0]
 }
 */
 
@@ -180,8 +179,8 @@ SELECT pk(), * FROM test_idx;
   "a": "a",
   "b": "b",
   "c": {
-    "c": 1,
-    "d": 2
+    "c": 1.0,
+    "d": 2.0
   }
 }
 */
@@ -205,10 +204,9 @@ SELECT pk(), * FROM test_idx;
 {
   "pk()": 1,
   "a": [
-    1,
-    2
-,
-    3
+    1.0,
+    2.0,
+    3.0
   ]
 }
 */
@@ -238,7 +236,7 @@ SELECT pk(), * FROM test_idx;
 INSERT INTO test_idx VALUES {a: 400, b: a * 4};
 SELECT pk(), * FROM test_idx;
 /* result:
-{"pk()":1,"a":400,"b":1600}
+{"pk()":1,"a":400.0,"b":1600.0}
 */
 
 -- test: read-only tables
@@ -280,7 +278,7 @@ SELECT * FROM test_tc;
   "byt": CAST("Ynl0ZXNWYWx1ZQ==" AS BYTES),
   "t": "text",
   "a": [
-    1,
+    1.0,
     "foo",
     true
   ],
diff --git a/query/gen_insert_with_select_test.go b/query/gen_insert_with_select_test.go
index 49df458c..228c99f8 100644
--- a/query/gen_insert_with_select_test.go
+++ b/query/gen_insert_with_select_test.go
@@ -60,7 +60,7 @@ SELECT pk(), * FROM foo;
 			require.NoError(t, err)
 			defer res.Close()
 			raw := `
-{"pk()":1, "a":1, "b":10}
+{"pk()":1, "a":1.0, "b":10.0}
 `
 			testutil.RequireStreamEq(t, raw, res)
 		})
@@ -84,7 +84,7 @@ SELECT pk(), * FROM foo;
 			require.NoError(t, err)
 			defer res.Close()
 			raw := `
-{"pk()":1, "a":1}
+{"pk()":1, "a":1.0}
 `
 			testutil.RequireStreamEq(t, raw, res)
 		})
@@ -108,7 +108,7 @@ SELECT pk(), * FROM foo;
 			require.NoError(t, err)
 			defer res.Close()
 			raw := `
-{"pk()":1, "a":1, "b":10}
+{"pk()":1, "a":1.0, "b":10.0}
 `
 			testutil.RequireStreamEq(t, raw, res)
 		})
@@ -132,7 +132,7 @@ SELECT pk(), * FROM foo;
 			require.NoError(t, err)
 			defer res.Close()
 			raw := `
-{"pk()":1, "c":1, "d":10}
+{"pk()":1, "c":1.0, "d":10.0}
 `
 			testutil.RequireStreamEq(t, raw, res)
 		})
diff --git a/query/gen_insert_with_select_test.sql b/query/gen_insert_with_select_test.sql
index 0deb49c1..8ddcef11 100644
--- a/query/gen_insert_with_select_test.sql
+++ b/query/gen_insert_with_select_test.sql
@@ -11,28 +11,28 @@ INSERT INTO foo SELECT * FROM foo;
 INSERT INTO foo SELECT * FROM bar;
 SELECT pk(), * FROM foo;
 /* result:
-{"pk()":1, "a":1, "b":10}
+{"pk()":1, "a":1.0, "b":10.0}
 */
 
 -- test: No fields / Projection
 INSERT INTO foo SELECT a FROM bar;
 SELECT pk(), * FROM foo;
 /* result:
-{"pk()":1, "a":1}
+{"pk()":1, "a":1.0}
 */
 
 -- test: With fields / No Projection
 INSERT INTO foo (a, b) SELECT * FROM bar;
 SELECT pk(), * FROM foo;
 /* result:
-{"pk()":1, "a":1, "b":10}
+{"pk()":1, "a":1.0, "b":10.0}
 */
 
 -- test: With fields / Projection
 INSERT INTO foo (c, d) SELECT a, b FROM bar;
 SELECT pk(), * FROM foo;
 /* result:
-{"pk()":1, "c":1, "d":10}
+{"pk()":1, "c":1.0, "d":10.0}
 */
 
 -- test: Too many fields / No Projection
diff --git a/testutil/gen.go b/testutil/gen.go
index e357c543..df03498f 100644
--- a/testutil/gen.go
+++ b/testutil/gen.go
@@ -8,15 +8,16 @@ import (
 	"github.com/genjidb/genji/expr"
 	"github.com/genjidb/genji/query"
 	"github.com/genjidb/genji/sql/parser"
+	"github.com/google/go-cmp/cmp"
 	"github.com/stretchr/testify/require"
 )
 
-type DocsStream struct {
+type ResultStream struct {
 	*parser.Parser
 	env *expr.Environment
 }
 
-func (ds *DocsStream) Next() (*document.Value, error) {
+func (ds *ResultStream) Next() (*document.Value, error) {
 	exp, err := ds.Parser.ParseDocument()
 	if err != nil {
 		return nil, err
@@ -30,42 +31,89 @@ func (ds *DocsStream) Next() (*document.Value, error) {
 	return &v, nil
 }
 
-func ParseDocsStream(stream string) *DocsStream {
+func ParseResultStream(stream string) *ResultStream {
 	p := parser.NewParser(strings.NewReader(stream))
 	env := expr.NewEnvironment(document.NewFieldBuffer())
 
-	return &DocsStream{p, env}
+	return &ResultStream{p, env}
 }
 
-func RequireStreamEq(t *testing.T, raw string, res *query.Result) {
-	t.Helper()
-	var count int
-	docs := ParseDocsStream(raw)
-	err := res.Iterate(func(d document.Document) error {
-		count++
+// val is a fully realized representation of a document.Value, suitable for
+// comparison with go-cmp.
+type val struct {
+	Type string
+	V    interface{}
+}
 
-		want, err := docs.Next()
-		require.NoError(t, err)
-		got := document.NewDocumentValue(d)
+func transformV(v document.Value) val {
+	var vi interface{}
 
-		eq, err := want.IsEqual(got)
+	if v.Type == document.DocumentValue {
+		vi = transformDoc(v.V.(document.Document))
+	} else if v.Type == document.ArrayValue {
+		vi = transformArray(v.V.(document.Array))
+	} else {
+		vi = v.String()
+	}
 
-		require.NoError(t, err, "comparing %s and %s yielded an error: %e", want, got, err)
-		require.Truef(t, eq, "expected values to be equal\nwant %s to eq got %s", want.String(), got.String())
-		return err
+	return val{
+		Type: v.Type.String(),
+		V:    vi,
+	}
+}
+
+type field struct {
+	Field string
+	V     val
+}
+
+// doc is a fully realized representation of a document.Document, suitable for
+// comparison with go-cmp.
+type doc []field
+
+func transformDoc(d document.Document) doc {
+	fields := make([]field, 0)
+	_ = d.Iterate(func(name string, v document.Value) error {
+		fields = append(fields, field{Field: name, V: transformV(v)})
+		return nil
+	})
+
+	return fields
+}
+
+func transformArray(a document.Array) []val {
+	fields := make([]val, 0)
+	_ = a.Iterate(func(i int, v document.Value) error {
+		fields = append(fields, transformV(v))
+		return nil
 	})
-	require.NoError(t, err)
 
-	// there should not be any document left
-	total := count
-	var missing []string
+	return fields
+}
+
+func RequireStreamEq(t *testing.T, raw string, res *query.Result) {
+	t.Helper()
+	docs := ParseResultStream(raw)
+	var want []*val
+
 	for v, err := docs.Next(); err == nil; v, err = docs.Next() {
-		missing = append(missing, v.String())
-		total++
+		val := transformV(*v)
+		want = append(want, &val)
 	}
 
-	require.Equalf(t, total, count, "want %d documents but got %d instead.\nMissing documents:\n%s",
-		total,
-		count,
-		strings.Join(missing, "\n"))
+	var got []*val
+	err := res.Iterate(func(d document.Document) error {
+		val := transformV(document.NewDocumentValue(d))
+		got = append(got, &val)
+		return nil
+	})
+	require.NoError(t, err)
+
+	// Working with simple structs rather than providing an equality function to go-cmp
+	// allows to get much better diffs, which only show where the difference is rater than
+	// fully displaying both documents.
+	diff := cmp.Diff(want, got)
+	if diff != "" {
+		require.Failf(t, "mismatched documents, (-want, +got)", "%s", diff)
+	}
 }