github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/go/ngql/query_test.go (about) 1 // Copyright 2017 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package ngql 6 7 import ( 8 "bytes" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "testing" 13 14 "github.com/attic-labs/graphql" 15 "github.com/attic-labs/noms/go/chunks" 16 "github.com/attic-labs/noms/go/marshal" 17 "github.com/attic-labs/noms/go/types" 18 "github.com/attic-labs/noms/go/util/test" 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/suite" 21 ) 22 23 type QueryGraphQLSuite struct { 24 suite.Suite 25 vs *types.ValueStore 26 } 27 28 func TestQueryGraphQL(t *testing.T) { 29 suite.Run(t, &QueryGraphQLSuite{}) 30 } 31 32 func newTestValueStore() *types.ValueStore { 33 storage := &chunks.MemoryStorage{} 34 return types.NewValueStore(storage.NewView()) 35 } 36 37 func (suite *QueryGraphQLSuite) SetupTest() { 38 suite.vs = newTestValueStore() 39 } 40 41 func (suite *QueryGraphQLSuite) assertQueryResult(v types.Value, q, expect string) { 42 buf := &bytes.Buffer{} 43 Query(v, q, suite.vs, buf) 44 suite.JSONEq(test.RemoveHashes(expect), test.RemoveHashes(buf.String())) 45 } 46 47 func (suite *QueryGraphQLSuite) TestScalars() { 48 suite.assertQueryResult(types.String("aaa"), "{root}", `{"data":{"root":"aaa"}}`) 49 suite.assertQueryResult(types.String(""), "{root}", `{"data":{"root":""}}`) 50 51 suite.assertQueryResult(types.Number(0), "{root}", `{"data":{"root":0}}`) 52 suite.assertQueryResult(types.Number(1), "{root}", `{"data":{"root":1}}`) 53 suite.assertQueryResult(types.Number(-1), "{root}", `{"data":{"root":-1}}`) 54 suite.assertQueryResult(types.Number(1<<31), "{root}", `{"data":{"root":2.147483648e+09}}`) 55 suite.assertQueryResult(types.Number(-(1 << 31)), "{root}", `{"data":{"root":-2.147483648e+09}}`) 56 suite.assertQueryResult(types.Number(0.001), "{root}", `{"data":{"root":0.001}}`) 57 suite.assertQueryResult(types.Number(0.00000001), "{root}", `{"data":{"root":1e-08}}`) 58 59 suite.assertQueryResult(types.Bool(false), "{root}", `{"data":{"root":false}}`) 60 suite.assertQueryResult(types.Bool(true), "{root}", `{"data":{"root":true}}`) 61 } 62 63 func (suite *QueryGraphQLSuite) TestStructBasic() { 64 s1 := types.NewStruct("Foo", types.StructData{ 65 "a": types.String("aaa"), 66 "b": types.Bool(true), 67 "c": types.Number(0.1), 68 }) 69 70 suite.assertQueryResult(s1, "{root{a}}", `{"data":{"root":{"a":"aaa"}}}`) 71 suite.assertQueryResult(s1, "{root{a b}}", `{"data":{"root":{"a":"aaa","b":true}}}`) 72 suite.assertQueryResult(s1, "{root{a b c}}", `{"data":{"root":{"a":"aaa","b":true,"c":0.1}}}`) 73 suite.assertQueryResult(s1, "{root{a c}}", `{"data":{"root":{"a":"aaa","c":0.1}}}`) 74 } 75 76 func (suite *QueryGraphQLSuite) TestEmptyStruct() { 77 s1 := types.NewStruct("", types.StructData{}) 78 79 suite.assertQueryResult(s1, "{root{hash}}", `{"data":{"root":{"hash":"0123456789abcdefghijklmnopqrstuv"}}}`) 80 } 81 82 func (suite *QueryGraphQLSuite) TestEmbeddedStruct() { 83 s1 := types.NewStruct("Foo", types.StructData{ 84 "a": types.String("aaa"), 85 "b": types.NewStruct("Bar", types.StructData{ 86 "c": types.Bool(true), 87 "d": types.Number(0.1), 88 }), 89 }) 90 91 suite.assertQueryResult(s1, "{root{a}}", `{"data":{"root":{"a":"aaa"}}}`) 92 suite.assertQueryResult(s1, "{root{a b {c}}}", `{"data":{"root":{"a":"aaa","b":{"c":true}}}}`) 93 suite.assertQueryResult(s1, "{root{a b {c d}}}", `{"data":{"root":{"a":"aaa","b":{"c":true,"d":0.1}}}}`) 94 } 95 96 func (suite *QueryGraphQLSuite) TestListBasic() { 97 for _, valuesKey := range []string{"elements", "values"} { 98 list := types.NewList(suite.vs) 99 suite.assertQueryResult(list, "{root{size}}", `{"data":{"root":{"size":0}}}`) 100 suite.assertQueryResult(list, "{root{"+valuesKey+"}}", `{"data":{"root":{}}}`) 101 102 list = types.NewList(suite.vs, types.String("foo"), types.String("bar"), types.String("baz")) 103 104 suite.assertQueryResult(list, "{root{"+valuesKey+"}}", `{"data":{"root":{"`+valuesKey+`":["foo","bar","baz"]}}}`) 105 suite.assertQueryResult(list, "{root{size}}", `{"data":{"root":{"size":3}}}`) 106 suite.assertQueryResult(list, "{root{"+valuesKey+"(at:1,count:2)}}", `{"data":{"root":{"`+valuesKey+`":["bar","baz"]}}}`) 107 108 list = types.NewList(suite.vs, types.Bool(true), types.Bool(false), types.Bool(false)) 109 110 suite.assertQueryResult(list, "{root{"+valuesKey+"}}", `{"data":{"root":{"`+valuesKey+`":[true,false,false]}}}`) 111 suite.assertQueryResult(list, "{root{"+valuesKey+"(at:1,count:2)}}", `{"data":{"root":{"`+valuesKey+`":[false,false]}}}`) 112 113 list = types.NewList(suite.vs, types.Number(1), types.Number(1.1), types.Number(-100)) 114 115 suite.assertQueryResult(list, "{root{"+valuesKey+"}}", `{"data":{"root":{"`+valuesKey+`":[1,1.1,-100]}}}`) 116 suite.assertQueryResult(list, "{root{"+valuesKey+"(at:1,count:2)}}", `{"data":{"root":{"`+valuesKey+`":[1.1,-100]}}}`) 117 118 list = types.NewList(suite.vs, types.String("a"), types.String("b"), types.String("c")) 119 suite.assertQueryResult(list, "{root{"+valuesKey+"(at:4)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 120 suite.assertQueryResult(list, "{root{"+valuesKey+"(count:0)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 121 suite.assertQueryResult(list, "{root{"+valuesKey+"(count:10)}}", `{"data":{"root":{"`+valuesKey+`":["a","b","c"]}}}`) 122 suite.assertQueryResult(list, "{root{"+valuesKey+"(at:-1)}}", `{"data":{"root":{"`+valuesKey+`":["a","b","c"]}}}`) 123 } 124 } 125 126 func (suite *QueryGraphQLSuite) TestListOfStruct() { 127 list := types.NewList(suite.vs, 128 types.NewStruct("Foo", types.StructData{ 129 "a": types.Number(28), 130 "b": types.String("foo"), 131 }), 132 types.NewStruct("Foo", types.StructData{ 133 "a": types.Number(-20.102), 134 "b": types.String("bar"), 135 }), 136 types.NewStruct("Foo", types.StructData{ 137 "a": types.Number(5), 138 "b": types.String("baz"), 139 }), 140 ) 141 142 suite.assertQueryResult(list, "{root{elements{a b}}}", `{"data":{"root":{"elements":[{"a":28,"b":"foo"},{"a":-20.102,"b":"bar"},{"a":5,"b":"baz"}]}}}`) 143 144 suite.assertQueryResult(list, "{root{elements{a}}}", `{"data":{"root":{"elements":[{"a":28},{"a":-20.102},{"a":5}]}}}`) 145 } 146 147 func (suite *QueryGraphQLSuite) TestListOfStructWithOptionalFields() { 148 list := types.NewList(suite.vs, 149 types.NewStruct("Foo", types.StructData{ 150 "a": types.Number(1), 151 }), 152 types.NewStruct("Foo", types.StructData{ 153 "a": types.Number(2), 154 "b": types.String("bar"), 155 }), 156 ) 157 158 suite.assertQueryResult(list, "{root{elements{a b}}}", `{ 159 "data": { 160 "root": { 161 "elements": [ 162 {"a": 1, "b": null}, 163 {"a": 2, "b": "bar"} 164 ] 165 } 166 } 167 }`) 168 } 169 170 func (suite *QueryGraphQLSuite) TestSetBasic() { 171 for _, valuesKey := range []string{"elements", "values"} { 172 set := types.NewSet(suite.vs) 173 suite.assertQueryResult(set, "{root{size}}", `{"data":{"root":{"size":0}}}`) 174 suite.assertQueryResult(set, "{root{"+valuesKey+"}}", `{"data":{"root":{}}}`) 175 176 set = types.NewSet(suite.vs, types.String("foo"), types.String("bar"), types.String("baz")) 177 178 suite.assertQueryResult(set, "{root{"+valuesKey+"}}", `{"data":{"root":{"`+valuesKey+`":["bar","baz","foo"]}}}`) 179 suite.assertQueryResult(set, "{root{size}}", `{"data":{"root":{"size":3}}}`) 180 suite.assertQueryResult(set, "{root{"+valuesKey+"(count:2)}}", `{"data":{"root":{"`+valuesKey+`":["bar","baz"]}}}`) 181 182 set = types.NewSet(suite.vs, types.Bool(true), types.Bool(false)) 183 184 suite.assertQueryResult(set, "{root{"+valuesKey+"}}", `{"data":{"root":{"`+valuesKey+`":[false,true]}}}`) 185 suite.assertQueryResult(set, "{root{"+valuesKey+"(count:1)}}", `{"data":{"root":{"`+valuesKey+`":[false]}}}`) 186 187 set = types.NewSet(suite.vs, types.Number(1), types.Number(1.1), types.Number(-100)) 188 189 suite.assertQueryResult(set, "{root{"+valuesKey+"}}", `{"data":{"root":{"`+valuesKey+`":[-100,1,1.1]}}}`) 190 suite.assertQueryResult(set, "{root{"+valuesKey+"(count:2)}}", `{"data":{"root":{"`+valuesKey+`":[-100,1]}}}`) 191 192 set = types.NewSet(suite.vs, types.String("a"), types.String("b"), types.String("c"), types.String("d")) 193 suite.assertQueryResult(set, "{root{"+valuesKey+"(count:0)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 194 suite.assertQueryResult(set, "{root{"+valuesKey+"(count:2)}}", `{"data":{"root":{"`+valuesKey+`":["a","b"]}}}`) 195 196 suite.assertQueryResult(set, "{root{"+valuesKey+"(at:0,count:2)}}", `{"data":{"root":{"`+valuesKey+`":["a","b"]}}}`) 197 suite.assertQueryResult(set, "{root{"+valuesKey+"(at:-1,count:2)}}", `{"data":{"root":{"`+valuesKey+`":["a","b"]}}}`) 198 suite.assertQueryResult(set, "{root{"+valuesKey+"(at:1,count:2)}}", `{"data":{"root":{"`+valuesKey+`":["b","c"]}}}`) 199 suite.assertQueryResult(set, "{root{"+valuesKey+"(at:2)}}", `{"data":{"root":{"`+valuesKey+`":["c","d"]}}}`) 200 suite.assertQueryResult(set, "{root{"+valuesKey+"(at:2,count:1)}}", `{"data":{"root":{"`+valuesKey+`":["c"]}}}`) 201 suite.assertQueryResult(set, "{root{"+valuesKey+"(at:2,count:0)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 202 suite.assertQueryResult(set, "{root{"+valuesKey+"(at:2,count:10)}}", `{"data":{"root":{"`+valuesKey+`":["c","d"]}}}`) 203 } 204 } 205 206 func (suite *QueryGraphQLSuite) TestSetOfStruct() { 207 set := types.NewSet(suite.vs, 208 types.NewStruct("Foo", types.StructData{ 209 "a": types.Number(28), 210 "b": types.String("foo"), 211 }), 212 types.NewStruct("Foo", types.StructData{ 213 "a": types.Number(-20.102), 214 "b": types.String("bar"), 215 }), 216 types.NewStruct("Foo", types.StructData{ 217 "a": types.Number(5), 218 "b": types.String("baz"), 219 }), 220 ) 221 222 suite.assertQueryResult(set, "{root{values{a b}}}", 223 `{"data":{"root":{"values":[{"a":28,"b":"foo"},{"a":5,"b":"baz"},{"a":-20.102,"b":"bar"}]}}}`) 224 suite.assertQueryResult(set, "{root{values{a}}}", `{"data":{"root":{"values":[{"a":28},{"a":5},{"a":-20.102}]}}}`) 225 } 226 227 func (suite *QueryGraphQLSuite) TestMapBasic() { 228 for _, entriesKey := range []string{"elements", "entries"} { 229 230 m := types.NewMap(suite.vs) 231 suite.assertQueryResult(m, "{root{size}}", `{"data":{"root":{"size":0}}}`) 232 suite.assertQueryResult(m, "{root{"+entriesKey+"}}", `{"data":{"root":{}}}`) 233 234 m = types.NewMap(suite.vs, 235 types.String("a"), types.Number(1), 236 types.String("b"), types.Number(2), 237 types.String("c"), types.Number(3), 238 types.String("d"), types.Number(4), 239 ) 240 241 suite.assertQueryResult(m, "{root{"+entriesKey+"{key value}}}", `{"data":{"root":{"`+entriesKey+`":[{"key":"a","value":1},{"key":"b","value":2},{"key":"c","value":3},{"key":"d","value":4}]}}}`) 242 suite.assertQueryResult(m, "{root{size}}", `{"data":{"root":{"size":4}}}`) 243 } 244 } 245 246 func (suite *QueryGraphQLSuite) TestMapOfStruct() { 247 m := types.NewMap(suite.vs, 248 types.String("foo"), types.NewStruct("Foo", types.StructData{ 249 "a": types.Number(28), 250 "b": types.String("foo"), 251 }), 252 types.String("bar"), types.NewStruct("Foo", types.StructData{ 253 "a": types.Number(-20.102), 254 "b": types.String("bar"), 255 }), 256 types.String("baz"), types.NewStruct("Foo", types.StructData{ 257 "a": types.Number(5), 258 "b": types.String("baz"), 259 }), 260 ) 261 262 suite.assertQueryResult(m, "{root{entries{key value{a}}}}", `{"data":{"root":{"entries":[{"key":"bar","value":{"a":-20.102}},{"key":"baz","value":{"a":5}},{"key":"foo","value":{"a":28}}]}}}`) 263 suite.assertQueryResult(m, "{root{entries(count:1){value{a b}}}}", `{"data":{"root":{"entries":[{"value":{"a":-20.102,"b":"bar"}}]}}}`) 264 suite.assertQueryResult(m, "{root{entries(count:3){key}}}", `{"data":{"root":{"entries":[{"key":"bar"},{"key":"baz"},{"key":"foo"}]}}}`) 265 } 266 267 func (suite *QueryGraphQLSuite) TestRef() { 268 r := suite.vs.WriteValue(types.Number(100)) 269 270 suite.assertQueryResult(r, "{root{targetValue}}", `{"data":{"root":{"targetValue":100}}}`) 271 suite.assertQueryResult(r, "{root{targetHash}}", `{"data":{"root":{"targetHash":"0123456789abcdefghijklmnopqrstuv"}}}`) 272 suite.assertQueryResult(r, "{root{targetValue targetHash}}", `{"data":{"root":{"targetHash":"0123456789abcdefghijklmnopqrstuv","targetValue":100}}}`) 273 274 r = suite.vs.WriteValue(types.NewStruct("Foo", types.StructData{ 275 "a": types.Number(28), 276 "b": types.String("foo"), 277 })) 278 279 suite.assertQueryResult(r, "{root{targetValue{a}}}", `{"data":{"root":{"targetValue":{"a":28}}}}`) 280 suite.assertQueryResult(r, "{root{targetValue{a b}}}", `{"data":{"root":{"targetValue":{"a":28,"b":"foo"}}}}`) 281 282 r = suite.vs.WriteValue(types.NewList(suite.vs, types.String("foo"), types.String("bar"), types.String("baz"))) 283 284 suite.assertQueryResult(r, "{root{targetValue{values}}}", `{"data":{"root":{"targetValue":{"values":["foo","bar","baz"]}}}}`) 285 suite.assertQueryResult(r, "{root{targetValue{values(at:1,count:2)}}}", `{"data":{"root":{"targetValue":{"values":["bar","baz"]}}}}`) 286 } 287 288 func (suite *QueryGraphQLSuite) TestListOfUnionOfStructs() { 289 list := types.NewList(suite.vs, 290 types.NewStruct("Foo", types.StructData{ 291 "a": types.Number(28), 292 "b": types.String("baz"), 293 }), 294 types.NewStruct("Bar", types.StructData{ 295 "b": types.String("bar"), 296 }), 297 types.NewStruct("Baz", types.StructData{ 298 "c": types.Bool(true), 299 }), 300 ) 301 302 suite.assertQueryResult(list, 303 fmt.Sprintf("{root{values{... on %s{a b} ... on %s{b} ... on %s{c}}}}", 304 GetTypeName(types.TypeOf(list.Get(0))), 305 GetTypeName(types.TypeOf(list.Get(1))), 306 GetTypeName(types.TypeOf(list.Get(2)))), 307 `{"data":{"root":{"values":[{"a":28,"b":"baz"},{"b":"bar"},{"c":true}]}}}`) 308 } 309 310 func (suite *QueryGraphQLSuite) TestListOfUnionOfStructsConflictingFieldTypes() { 311 list := types.NewList(suite.vs, 312 types.NewStruct("Foo", types.StructData{ 313 "a": types.Number(28), 314 }), 315 types.NewStruct("Bar", types.StructData{ 316 "a": types.String("bar"), 317 }), 318 types.NewStruct("Baz", types.StructData{ 319 "a": types.Bool(true), 320 }), 321 ) 322 323 suite.assertQueryResult(list, 324 fmt.Sprintf("{root{values{... on %s{a} ... on %s{b: a} ... on %s{c: a}}}}", 325 GetTypeName(types.TypeOf(list.Get(0))), 326 GetTypeName(types.TypeOf(list.Get(1))), 327 GetTypeName(types.TypeOf(list.Get(2)))), 328 `{"data":{"root":{"values":[{"a":28},{"b":"bar"},{"c":true}]}}}`) 329 } 330 331 func (suite *QueryGraphQLSuite) TestListOfUnionOfScalars() { 332 list := types.NewList(suite.vs, 333 types.Number(28), 334 types.String("bar"), 335 types.Bool(true), 336 ) 337 338 suite.assertQueryResult(list, "{root{values{... on BooleanValue{b: scalarValue} ... on StringValue{s: scalarValue} ... on NumberValue{n: scalarValue}}}}", `{"data":{"root":{"values":[{"n":28},{"s":"bar"},{"b":true}]}}}`) 339 } 340 341 func (suite *QueryGraphQLSuite) TestCyclicStructs() { 342 // struct A { 343 // a: "aaa" 344 // b: Set(struct A { 345 // a: "bbb" 346 // b: Set() 347 // }) 348 // } 349 350 s1 := types.NewStruct("A", types.StructData{ 351 "a": types.String("aaa"), 352 "b": types.NewSet(suite.vs, 353 types.NewStruct("A", types.StructData{ 354 "a": types.String("bbb"), 355 "b": types.NewSet(suite.vs), 356 })), 357 }) 358 359 suite.assertQueryResult(s1, "{root{a b{values{a}}}}", `{"data":{"root":{"a":"aaa","b":{"values":[{"a":"bbb"}]}}}}`) 360 } 361 362 func (suite *QueryGraphQLSuite) TestCyclicStructsWithUnion() { 363 // struct A { 364 // a: "aaa" 365 // b: Struct A { 366 // a: "bbb" 367 // b: 42 368 // }) 369 // } 370 371 // struct A { 372 // a: String, 373 // b: Number | Cycle<A>, 374 // } 375 376 s1 := types.NewStruct("A", types.StructData{ 377 "a": types.String("aaa"), 378 "b": types.NewStruct("A", types.StructData{ 379 "a": types.String("bbb"), 380 "b": types.Number(42), 381 }), 382 }) 383 384 suite.assertQueryResult(s1, 385 `{ 386 root{ 387 a 388 b { 389 a 390 b { 391 scalarValue 392 } 393 } 394 } 395 } 396 `, 397 `{ 398 "data": { 399 "root": { 400 "a": "aaa", 401 "b": { 402 "a": "bbb", 403 "b": { 404 "scalarValue": 42 405 } 406 } 407 } 408 } 409 }`) 410 411 suite.assertQueryResult(s1, 412 fmt.Sprintf(`{ 413 root{ 414 a 415 b { 416 ... on %s { 417 a 418 } 419 } 420 } 421 }`, GetTypeName(types.TypeOf(s1))), 422 `{ 423 "data": { 424 "root": { 425 "a": "aaa", 426 "b": { 427 "a": "bbb" 428 } 429 } 430 } 431 }`) 432 } 433 434 func (suite *QueryGraphQLSuite) TestNestedCollection() { 435 list := types.NewList(suite.vs, 436 types.NewSet(suite.vs, 437 types.NewMap(suite.vs, types.Number(10), types.String("foo")), 438 types.NewMap(suite.vs, types.Number(20), types.String("bar")), 439 ), 440 types.NewSet(suite.vs, 441 types.NewMap(suite.vs, types.Number(30), types.String("baz")), 442 types.NewMap(suite.vs, types.Number(40), types.String("bat")), 443 ), 444 ) 445 446 suite.assertQueryResult(list, "{root{size}}", `{"data":{"root":{"size":2}}}`) 447 suite.assertQueryResult(list, "{root{values(count:1){size}}}", `{"data":{"root":{"values":[{"size":2}]}}}`) 448 suite.assertQueryResult(list, "{root{values(at:1,count:1){values(count:1){entries{key value}}}}}", 449 `{"data":{"root":{"values":[{"values":[{"entries":[{"key":40,"value":"bat"}]}]}]}}}`) 450 } 451 452 func (suite *QueryGraphQLSuite) TestLoFi() { 453 b := types.NewBlob(suite.vs, bytes.NewBufferString("I am a blob")) 454 455 suite.assertQueryResult(b, "{root}", `{"data":{"root":"0123456789abcdefghijklmnopqrstuv"}}`) 456 457 t := types.StringType 458 suite.assertQueryResult(t, "{root}", `{"data":{"root":"0123456789abcdefghijklmnopqrstuv"}}`) 459 } 460 461 func (suite *QueryGraphQLSuite) TestError() { 462 buff := &bytes.Buffer{} 463 Error(errors.New("Some error string"), buff) 464 suite.Equal(buff.String(), `{"data":null,"errors":[{"message":"Some error string","locations":null}]} 465 `) 466 } 467 468 func (suite *QueryGraphQLSuite) TestMapArgs() { 469 for _, entriesKey := range []string{"elements", "entries"} { 470 471 m := types.NewMap(suite.vs, 472 types.String("a"), types.Number(1), 473 types.String("c"), types.Number(2), 474 types.String("e"), types.Number(3), 475 types.String("g"), types.Number(4), 476 ) 477 478 // count 479 suite.assertQueryResult(m, "{root{"+entriesKey+"(count:0){value}}}", `{"data":{"root":{"`+entriesKey+`":[]}}}`) 480 suite.assertQueryResult(m, "{root{"+entriesKey+"(count:2){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":1},{"value":2}]}}}`) 481 suite.assertQueryResult(m, "{root{"+entriesKey+"(count:3){key}}}", `{"data":{"root":{"`+entriesKey+`":[{"key":"a"},{"key":"c"},{"key":"e"}]}}}`) 482 suite.assertQueryResult(m, "{root{"+entriesKey+"(count: -1){key}}}", `{"data":{"root":{"`+entriesKey+`":[]}}}`) 483 suite.assertQueryResult(m, "{root{"+entriesKey+"(count:5){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":1},{"value":2},{"value":3},{"value":4}]}}}`) 484 485 // at 486 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:0){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":1},{"value":2},{"value":3},{"value":4}]}}}`) 487 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:-1){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":1},{"value":2},{"value":3},{"value":4}]}}}`) 488 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:2){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":3},{"value":4}]}}}`) 489 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:5){value}}}", `{"data":{"root":{"`+entriesKey+`":[]}}}`) 490 491 // at & count 492 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:0,count:2){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":1},{"value":2}]}}}`) 493 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:-1,count:2){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":1},{"value":2}]}}}`) 494 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:1,count:2){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":2},{"value":3}]}}}`) 495 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:2,count:1){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":3}]}}}`) 496 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:2,count:0){value}}}", `{"data":{"root":{"`+entriesKey+`":[]}}}`) 497 suite.assertQueryResult(m, "{root{"+entriesKey+"(at:2,count:10){value}}}", `{"data":{"root":{"`+entriesKey+`":[{"value":3},{"value":4}]}}}`) 498 499 // key 500 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"e"){key value}}}`, 501 `{"data":{"root":{"`+entriesKey+`":[{"key":"e","value":3}]}}}`) 502 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"g"){value}}}`, 503 `{"data":{"root":{"`+entriesKey+`":[{"value":4}]}}}`) 504 // "f", no count/through so asking for exact match 505 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"f"){value}}}`, 506 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 507 // "x" is larger than end 508 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"x"){value}}}`, 509 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 510 511 // key & at 512 // at is ignored when key is present 513 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"e",at:2){key value}}}`, 514 `{"data":{"root":{"`+entriesKey+`":[{"key":"e","value":3}]}}}`) 515 516 // key & count 517 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"c", count: 2){key value}}}`, 518 `{"data":{"root":{"`+entriesKey+`":[{"key":"c","value":2},{"key":"e","value":3}]}}}`) 519 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"c", count: 0){key value}}}`, 520 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 521 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"c", count: -1){key value}}}`, 522 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 523 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"e", count: 5){key value}}}`, 524 `{"data":{"root":{"`+entriesKey+`":[{"key":"e","value":3},{"key":"g","value":4}]}}}`) 525 526 // through 527 suite.assertQueryResult(m, `{root{`+entriesKey+`(through:"c"){key}}}`, 528 `{"data":{"root":{"`+entriesKey+`":[{"key":"a"},{"key":"c"}]}}}`) 529 suite.assertQueryResult(m, `{root{`+entriesKey+`(through:"b"){key}}}`, 530 `{"data":{"root":{"`+entriesKey+`":[{"key":"a"}]}}}`) 531 suite.assertQueryResult(m, `{root{`+entriesKey+`(through:"0"){key}}}`, 532 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 533 534 // key & through 535 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"c", through:"c"){key}}}`, 536 `{"data":{"root":{"`+entriesKey+`":[{"key":"c"}]}}}`) 537 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"c",through:"e"){key}}}`, 538 `{"data":{"root":{"`+entriesKey+`":[{"key":"c"},{"key":"e"}]}}}`) 539 540 // through & count 541 suite.assertQueryResult(m, `{root{`+entriesKey+`(through:"c",count:1){key}}}`, 542 `{"data":{"root":{"`+entriesKey+`":[{"key":"a"}]}}}`) 543 suite.assertQueryResult(m, `{root{`+entriesKey+`(through:"b",count:0){key}}}`, 544 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 545 suite.assertQueryResult(m, `{root{`+entriesKey+`(through:"0",count:10){key}}}`, 546 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 547 548 // at & through 549 suite.assertQueryResult(m, `{root{`+entriesKey+`(at:0,through:"a"){key}}}`, 550 `{"data":{"root":{"`+entriesKey+`":[{"key":"a"}]}}}`) 551 suite.assertQueryResult(m, `{root{`+entriesKey+`(at:1,through:"e"){key}}}`, 552 `{"data":{"root":{"`+entriesKey+`":[{"key":"c"},{"key":"e"}]}}}`) 553 554 // at & count & through 555 suite.assertQueryResult(m, `{root{`+entriesKey+`(at:0,count:2,through:"a"){key}}}`, 556 `{"data":{"root":{"`+entriesKey+`":[{"key":"a"}]}}}`) 557 suite.assertQueryResult(m, `{root{`+entriesKey+`(at:0,count:2,through:"e"){key}}}`, 558 `{"data":{"root":{"`+entriesKey+`":[{"key":"a"},{"key":"c"}]}}}`) 559 560 // key & count & through 561 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"c",count:2,through:"c"){key}}}`, 562 `{"data":{"root":{"`+entriesKey+`":[{"key":"c"}]}}}`) 563 suite.assertQueryResult(m, `{root{`+entriesKey+`(key:"c",count:2,through:"g"){key}}}`, 564 `{"data":{"root":{"`+entriesKey+`":[{"key":"c"},{"key":"e"}]}}}`) 565 } 566 } 567 568 func (suite *QueryGraphQLSuite) TestMapKeysArg() { 569 for _, entriesKey := range []string{"elements", "entries"} { 570 m := types.NewMap(suite.vs, 571 types.String("a"), types.Number(1), 572 types.String("c"), types.Number(2), 573 types.String("e"), types.Number(3), 574 types.String("g"), types.Number(4), 575 ) 576 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:["c","a"]){value}}}`, 577 `{"data":{"root":{"`+entriesKey+`":[{"value":2},{"value":1}]}}}`) 578 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:[]){value}}}`, 579 `{"data":{"root":{"`+entriesKey+`":[]}}}`) 580 581 m = types.NewMap(suite.vs, 582 types.Number(1), types.String("a"), 583 types.Number(2), types.String("c"), 584 types.Number(3), types.String("e"), 585 types.Number(4), types.String("g"), 586 ) 587 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:[4,1]){value}}}`, 588 `{"data":{"root":{"`+entriesKey+`":[{"value":"g"},{"value":"a"}]}}}`) 589 590 // Ignore other args 591 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:[4,1],key:2){value}}}`, 592 `{"data":{"root":{"`+entriesKey+`":[{"value":"g"},{"value":"a"}]}}}`) 593 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:[4,1],count:0){value}}}`, 594 `{"data":{"root":{"`+entriesKey+`":[{"value":"g"},{"value":"a"}]}}}`) 595 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:[4,1],at:4){value}}}`, 596 `{"data":{"root":{"`+entriesKey+`":[{"value":"g"},{"value":"a"}]}}}`) 597 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:[4,1],through:1){value}}}`, 598 `{"data":{"root":{"`+entriesKey+`":[{"value":"g"},{"value":"a"}]}}}`) 599 } 600 } 601 602 func (suite *QueryGraphQLSuite) TestSetArgs() { 603 for _, valuesKey := range []string{"elements", "values"} { 604 s := types.NewSet(suite.vs, 605 types.String("a"), 606 types.String("c"), 607 types.String("e"), 608 types.String("g"), 609 ) 610 611 // count 612 suite.assertQueryResult(s, "{root{"+valuesKey+"(count:0)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 613 suite.assertQueryResult(s, "{root{"+valuesKey+"(count:2)}}", `{"data":{"root":{"`+valuesKey+`":["a","c"]}}}`) 614 suite.assertQueryResult(s, "{root{"+valuesKey+"(count:3)}}", `{"data":{"root":{"`+valuesKey+`":["a","c","e"]}}}`) 615 suite.assertQueryResult(s, "{root{"+valuesKey+"(count: -1)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 616 suite.assertQueryResult(s, "{root{"+valuesKey+"(count:5)}}", `{"data":{"root":{"`+valuesKey+`":["a","c","e","g"]}}}`) 617 618 // at 619 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:0)}}", `{"data":{"root":{"`+valuesKey+`":["a","c","e","g"]}}}`) 620 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:-1)}}", `{"data":{"root":{"`+valuesKey+`":["a","c","e","g"]}}}`) 621 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:2)}}", `{"data":{"root":{"`+valuesKey+`":["e","g"]}}}`) 622 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:5)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 623 624 // at & count 625 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:0,count:2)}}", `{"data":{"root":{"`+valuesKey+`":["a","c"]}}}`) 626 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:-1,count:2)}}", `{"data":{"root":{"`+valuesKey+`":["a","c"]}}}`) 627 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:1,count:2)}}", `{"data":{"root":{"`+valuesKey+`":["c","e"]}}}`) 628 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:2,count:1)}}", `{"data":{"root":{"`+valuesKey+`":["e"]}}}`) 629 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:2,count:0)}}", `{"data":{"root":{"`+valuesKey+`":[]}}}`) 630 suite.assertQueryResult(s, "{root{"+valuesKey+"(at:2,count:10)}}", `{"data":{"root":{"`+valuesKey+`":["e","g"]}}}`) 631 632 // key 633 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"e")}}`, 634 `{"data":{"root":{"`+valuesKey+`":["e"]}}}`) 635 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"g")}}`, 636 `{"data":{"root":{"`+valuesKey+`":["g"]}}}`) 637 // "f", no count/through so asking for exact match 638 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"f")}}`, 639 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 640 // "x" is larger than end 641 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"x")}}`, 642 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 643 // exact match 644 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"0")}}`, 645 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 646 647 // key & at 648 // at is ignored when key is present 649 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"e",at:2)}}`, 650 `{"data":{"root":{"`+valuesKey+`":["e"]}}}`) 651 652 // key & count 653 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"c", count: 2)}}`, 654 `{"data":{"root":{"`+valuesKey+`":["c","e"]}}}`) 655 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"c", count: 0)}}`, 656 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 657 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"c", count: -1)}}`, 658 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 659 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"e", count: 5)}}`, 660 `{"data":{"root":{"`+valuesKey+`":["e","g"]}}}`) 661 662 // through 663 suite.assertQueryResult(s, `{root{`+valuesKey+`(through:"c")}}`, 664 `{"data":{"root":{"`+valuesKey+`":["a","c"]}}}`) 665 suite.assertQueryResult(s, `{root{`+valuesKey+`(through:"b")}}`, 666 `{"data":{"root":{"`+valuesKey+`":["a"]}}}`) 667 suite.assertQueryResult(s, `{root{`+valuesKey+`(through:"0")}}`, 668 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 669 670 // key & through 671 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"c", through:"c")}}`, 672 `{"data":{"root":{"`+valuesKey+`":["c"]}}}`) 673 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"c",through:"e")}}`, 674 `{"data":{"root":{"`+valuesKey+`":["c","e"]}}}`) 675 676 // through & count 677 suite.assertQueryResult(s, `{root{`+valuesKey+`(through:"c",count:1)}}`, 678 `{"data":{"root":{"`+valuesKey+`":["a"]}}}`) 679 suite.assertQueryResult(s, `{root{`+valuesKey+`(through:"b",count:0)}}`, 680 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 681 suite.assertQueryResult(s, `{root{`+valuesKey+`(through:"0",count:10)}}`, 682 `{"data":{"root":{"`+valuesKey+`":[]}}}`) 683 684 // at & through 685 suite.assertQueryResult(s, `{root{`+valuesKey+`(at:0,through:"a")}}`, 686 `{"data":{"root":{"`+valuesKey+`":["a"]}}}`) 687 suite.assertQueryResult(s, `{root{`+valuesKey+`(at:1,through:"e")}}`, 688 `{"data":{"root":{"`+valuesKey+`":["c","e"]}}}`) 689 690 // at & count & through 691 suite.assertQueryResult(s, `{root{`+valuesKey+`(at:0,count:2,through:"a")}}`, 692 `{"data":{"root":{"`+valuesKey+`":["a"]}}}`) 693 suite.assertQueryResult(s, `{root{`+valuesKey+`(at:0,count:2,through:"e")}}`, 694 `{"data":{"root":{"`+valuesKey+`":["a","c"]}}}`) 695 696 // key & count & through 697 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"c",count:2,through:"c")}}`, 698 `{"data":{"root":{"`+valuesKey+`":["c"]}}}`) 699 suite.assertQueryResult(s, `{root{`+valuesKey+`(key:"c",count:2,through:"g")}}`, 700 `{"data":{"root":{"`+valuesKey+`":["c","e"]}}}`) 701 } 702 } 703 704 func (suite *QueryGraphQLSuite) TestMapValues() { 705 m := types.NewMap(suite.vs, 706 types.String("a"), types.Number(1), 707 types.String("c"), types.Number(2), 708 types.String("e"), types.Number(3), 709 types.String("g"), types.Number(4), 710 ) 711 712 suite.assertQueryResult(m, "{root{values}}", `{"data":{"root":{"values":[1,2,3,4]}}}`) 713 714 // count 715 suite.assertQueryResult(m, "{root{values(count:0)}}", `{"data":{"root":{"values":[]}}}`) 716 suite.assertQueryResult(m, "{root{values(count:2)}}", `{"data":{"root":{"values":[1,2]}}}`) 717 suite.assertQueryResult(m, "{root{values(count:3)}}", `{"data":{"root":{"values":[1,2,3]}}}`) 718 suite.assertQueryResult(m, "{root{values(count: -1)}}", `{"data":{"root":{"values":[]}}}`) 719 suite.assertQueryResult(m, "{root{values(count:5)}}", `{"data":{"root":{"values":[1,2,3,4]}}}`) 720 721 // at 722 suite.assertQueryResult(m, "{root{values(at:0)}}", `{"data":{"root":{"values":[1,2,3,4]}}}`) 723 suite.assertQueryResult(m, "{root{values(at:-1)}}", `{"data":{"root":{"values":[1,2,3,4]}}}`) 724 suite.assertQueryResult(m, "{root{values(at:2)}}", `{"data":{"root":{"values":[3,4]}}}`) 725 suite.assertQueryResult(m, "{root{values(at:5)}}", `{"data":{"root":{"values":[]}}}`) 726 727 // at & count 728 suite.assertQueryResult(m, "{root{values(at:0,count:2)}}", `{"data":{"root":{"values":[1,2]}}}`) 729 suite.assertQueryResult(m, "{root{values(at:-1,count:2)}}", `{"data":{"root":{"values":[1,2]}}}`) 730 suite.assertQueryResult(m, "{root{values(at:1,count:2)}}", `{"data":{"root":{"values":[2,3]}}}`) 731 suite.assertQueryResult(m, "{root{values(at:2,count:1)}}", `{"data":{"root":{"values":[3]}}}`) 732 suite.assertQueryResult(m, "{root{values(at:2,count:0)}}", `{"data":{"root":{"values":[]}}}`) 733 suite.assertQueryResult(m, "{root{values(at:2,count:10)}}", `{"data":{"root":{"values":[3,4]}}}`) 734 735 // key 736 suite.assertQueryResult(m, `{root{values(key:"e")}}`, `{"data":{"root":{"values":[3]}}}`) 737 suite.assertQueryResult(m, `{root{values(key:"g")}}`, `{"data":{"root":{"values":[4]}}}`) 738 // "f", no count/through so asking for exact match 739 suite.assertQueryResult(m, `{root{values(key:"f")}}`, `{"data":{"root":{"values":[]}}}`) 740 // "x" is larger than end 741 suite.assertQueryResult(m, `{root{values(key:"x")}}`, `{"data":{"root":{"values":[]}}}`) 742 743 // key & at 744 // at is ignored when key is present 745 suite.assertQueryResult(m, `{root{values(key:"e",at:2)}}`, `{"data":{"root":{"values":[3]}}}`) 746 747 // key & count 748 suite.assertQueryResult(m, `{root{values(key:"c",count:2)}}`, `{"data":{"root":{"values":[2,3]}}}`) 749 suite.assertQueryResult(m, `{root{values(key:"c",count:0)}}`, `{"data":{"root":{"values":[]}}}`) 750 suite.assertQueryResult(m, `{root{values(key:"c",count:-1)}}`, `{"data":{"root":{"values":[]}}}`) 751 suite.assertQueryResult(m, `{root{values(key:"e",count:5)}}`, `{"data":{"root":{"values":[3,4]}}}`) 752 753 // through 754 suite.assertQueryResult(m, `{root{values(through:"c")}}`, `{"data":{"root":{"values":[1,2]}}}`) 755 suite.assertQueryResult(m, `{root{values(through:"b")}}`, `{"data":{"root":{"values":[1]}}}`) 756 suite.assertQueryResult(m, `{root{values(through:"0")}}`, `{"data":{"root":{"values":[]}}}`) 757 758 // key & through 759 suite.assertQueryResult(m, `{root{values(key:"c", through:"c")}}`, `{"data":{"root":{"values":[2]}}}`) 760 suite.assertQueryResult(m, `{root{values(key:"c",through:"e")}}`, `{"data":{"root":{"values":[2,3]}}}`) 761 762 // through & count 763 suite.assertQueryResult(m, `{root{values(through:"c",count:1)}}`, `{"data":{"root":{"values":[1]}}}`) 764 suite.assertQueryResult(m, `{root{values(through:"b",count:0)}}`, `{"data":{"root":{"values":[]}}}`) 765 suite.assertQueryResult(m, `{root{values(through:"0",count:10)}}`, `{"data":{"root":{"values":[]}}}`) 766 767 // at & through 768 suite.assertQueryResult(m, `{root{values(at:0,through:"a")}}`, `{"data":{"root":{"values":[1]}}}`) 769 suite.assertQueryResult(m, `{root{values(at:1,through:"e")}}`, `{"data":{"root":{"values":[2,3]}}}`) 770 771 // at & count & through 772 suite.assertQueryResult(m, `{root{values(at:0,count:2,through:"a")}}`, `{"data":{"root":{"values":[1]}}}`) 773 suite.assertQueryResult(m, `{root{values(at:0,count:2,through:"e")}}`, `{"data":{"root":{"values":[1,2]}}}`) 774 775 // key & count & through 776 suite.assertQueryResult(m, `{root{values(key:"c",count:2,through:"c")}}`, 777 `{"data":{"root":{"values":[2]}}}`) 778 suite.assertQueryResult(m, `{root{values(key:"c",count:2,through:"g")}}`, 779 `{"data":{"root":{"values":[2,3]}}}`) 780 } 781 782 func (suite *QueryGraphQLSuite) TestMapKeys() { 783 m := types.NewMap(suite.vs, 784 types.String("a"), types.Number(1), 785 types.String("c"), types.Number(2), 786 types.String("e"), types.Number(3), 787 types.String("g"), types.Number(4), 788 ) 789 790 suite.assertQueryResult(m, "{root{keys}}", `{"data":{"root":{"keys":["a","c","e","g"]}}}`) 791 792 // count 793 suite.assertQueryResult(m, "{root{keys(count:0)}}", `{"data":{"root":{"keys":[]}}}`) 794 suite.assertQueryResult(m, "{root{keys(count:2)}}", `{"data":{"root":{"keys":["a","c"]}}}`) 795 suite.assertQueryResult(m, "{root{keys(count:3)}}", `{"data":{"root":{"keys":["a","c","e"]}}}`) 796 suite.assertQueryResult(m, "{root{keys(count: -1)}}", `{"data":{"root":{"keys":[]}}}`) 797 suite.assertQueryResult(m, "{root{keys(count:5)}}", `{"data":{"root":{"keys":["a","c","e","g"]}}}`) 798 799 // at 800 suite.assertQueryResult(m, "{root{keys(at:0)}}", `{"data":{"root":{"keys":["a","c","e","g"]}}}`) 801 suite.assertQueryResult(m, "{root{keys(at:-1)}}", `{"data":{"root":{"keys":["a","c","e","g"]}}}`) 802 suite.assertQueryResult(m, "{root{keys(at:2)}}", `{"data":{"root":{"keys":["e","g"]}}}`) 803 suite.assertQueryResult(m, "{root{keys(at:5)}}", `{"data":{"root":{"keys":[]}}}`) 804 805 // at & count 806 suite.assertQueryResult(m, "{root{keys(at:0,count:2)}}", `{"data":{"root":{"keys":["a","c"]}}}`) 807 suite.assertQueryResult(m, "{root{keys(at:-1,count:2)}}", `{"data":{"root":{"keys":["a","c"]}}}`) 808 suite.assertQueryResult(m, "{root{keys(at:1,count:2)}}", `{"data":{"root":{"keys":["c","e"]}}}`) 809 suite.assertQueryResult(m, "{root{keys(at:2,count:1)}}", `{"data":{"root":{"keys":["e"]}}}`) 810 suite.assertQueryResult(m, "{root{keys(at:2,count:0)}}", `{"data":{"root":{"keys":[]}}}`) 811 suite.assertQueryResult(m, "{root{keys(at:2,count:10)}}", `{"data":{"root":{"keys":["e","g"]}}}`) 812 813 // key 814 suite.assertQueryResult(m, `{root{keys(key:"e")}}`, `{"data":{"root":{"keys":["e"]}}}`) 815 suite.assertQueryResult(m, `{root{keys(key:"g")}}`, `{"data":{"root":{"keys":["g"]}}}`) 816 // "f", no count/through so asking for exact match 817 suite.assertQueryResult(m, `{root{keys(key:"f")}}`, `{"data":{"root":{"keys":[]}}}`) 818 // "x" is larger than end 819 suite.assertQueryResult(m, `{root{keys(key:"x")}}`, `{"data":{"root":{"keys":[]}}}`) 820 821 // key & at 822 // at is ignored when key is present 823 suite.assertQueryResult(m, `{root{keys(key:"e",at:2)}}`, `{"data":{"root":{"keys":["e"]}}}`) 824 825 // key & count 826 suite.assertQueryResult(m, `{root{keys(key:"c",count:2)}}`, `{"data":{"root":{"keys":["c","e"]}}}`) 827 suite.assertQueryResult(m, `{root{keys(key:"c",count:0)}}`, `{"data":{"root":{"keys":[]}}}`) 828 suite.assertQueryResult(m, `{root{keys(key:"c",count:-1)}}`, `{"data":{"root":{"keys":[]}}}`) 829 suite.assertQueryResult(m, `{root{keys(key:"e",count:5)}}`, `{"data":{"root":{"keys":["e","g"]}}}`) 830 831 // through 832 suite.assertQueryResult(m, `{root{keys(through:"c")}}`, `{"data":{"root":{"keys":["a","c"]}}}`) 833 suite.assertQueryResult(m, `{root{keys(through:"b")}}`, `{"data":{"root":{"keys":["a"]}}}`) 834 suite.assertQueryResult(m, `{root{keys(through:"0")}}`, `{"data":{"root":{"keys":[]}}}`) 835 836 // key & through 837 suite.assertQueryResult(m, `{root{keys(key:"c", through:"c")}}`, `{"data":{"root":{"keys":["c"]}}}`) 838 suite.assertQueryResult(m, `{root{keys(key:"c",through:"e")}}`, `{"data":{"root":{"keys":["c","e"]}}}`) 839 840 // through & count 841 suite.assertQueryResult(m, `{root{keys(through:"c",count:1)}}`, `{"data":{"root":{"keys":["a"]}}}`) 842 suite.assertQueryResult(m, `{root{keys(through:"b",count:0)}}`, `{"data":{"root":{"keys":[]}}}`) 843 suite.assertQueryResult(m, `{root{keys(through:"0",count:10)}}`, `{"data":{"root":{"keys":[]}}}`) 844 845 // at & through 846 suite.assertQueryResult(m, `{root{keys(at:0,through:"a")}}`, `{"data":{"root":{"keys":["a"]}}}`) 847 suite.assertQueryResult(m, `{root{keys(at:1,through:"e")}}`, `{"data":{"root":{"keys":["c","e"]}}}`) 848 849 // at & count & through 850 suite.assertQueryResult(m, `{root{keys(at:0,count:2,through:"a")}}`, `{"data":{"root":{"keys":["a"]}}}`) 851 suite.assertQueryResult(m, `{root{keys(at:0,count:2,through:"e")}}`, `{"data":{"root":{"keys":["a","c"]}}}`) 852 853 // key & count & through 854 suite.assertQueryResult(m, `{root{keys(key:"c",count:2,through:"c")}}`, 855 `{"data":{"root":{"keys":["c"]}}}`) 856 suite.assertQueryResult(m, `{root{keys(key:"c",count:2,through:"g")}}`, 857 `{"data":{"root":{"keys":["c","e"]}}}`) 858 } 859 860 func (suite *QueryGraphQLSuite) TestMapNullable() { 861 // When selecting the result based on keys the values may be null. 862 m := types.NewMap(suite.vs, 863 types.String("a"), types.Number(1), 864 types.String("c"), types.Number(2), 865 ) 866 867 for _, entriesKey := range []string{"elements", "entries"} { 868 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:["a","b","c"]){value}}}`, 869 `{"data":{"root":{"`+entriesKey+`":[{"value":1},{"value":null},{"value":2}]}}}`) 870 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:["a","b","c"]){key}}}`, 871 `{"data":{"root":{"`+entriesKey+`":[{"key":"a"},{"key":"b"},{"key":"c"}]}}}`) 872 suite.assertQueryResult(m, `{root{`+entriesKey+`(keys:["a","b","c"]){key value}}}`, 873 `{"data":{"root":{"`+entriesKey+`":[{"key":"a","value":1},{"key":"b","value":null},{"key":"c","value":2}]}}}`) 874 } 875 suite.assertQueryResult(m, `{root{values(keys:["a","b","c"])}}`, 876 `{"data":{"root":{"values":[1,null,2]}}}`) 877 suite.assertQueryResult(m, `{root{keys(keys:["a","b","c"])}}`, 878 `{"data":{"root":{"keys":["a","b","c"]}}}`) 879 } 880 881 func (suite *QueryGraphQLSuite) TestStructWithOptionalField() { 882 tm := NewTypeMap() 883 rootValue := types.NewStruct("", types.StructData{ 884 "n": types.Number(42), 885 }) 886 rootType := NomsTypeToGraphQLType(types.MakeStructType("", 887 types.StructField{Name: "n", Type: types.NumberType, Optional: false}, 888 types.StructField{Name: "s", Type: types.StringType, Optional: true}, 889 ), false, tm) 890 891 queryObj := graphql.NewObject(graphql.ObjectConfig{ 892 Name: rootQueryKey, 893 Fields: graphql.Fields{ 894 rootKey: &graphql.Field{ 895 Type: rootType, 896 Resolve: func(p graphql.ResolveParams) (interface{}, error) { 897 return MaybeGetScalar(rootValue), nil 898 }, 899 }, 900 }}) 901 902 schemaConfig := graphql.SchemaConfig{Query: queryObj} 903 schema, err := graphql.NewSchema(schemaConfig) 904 suite.NoError(err) 905 ctx := NewContext(suite.vs) 906 query := `{root{n s}}` 907 908 r := graphql.Do(graphql.Params{ 909 Schema: schema, 910 RequestString: query, 911 Context: ctx, 912 }) 913 914 suite.Equal(map[string]interface{}{"root": map[string]interface{}{"n": float64(42), "s": nil}}, r.Data) 915 } 916 917 func (suite *QueryGraphQLSuite) TestMutationScalarArgs() { 918 test := func(query, expected string, nomsType *types.Type) { 919 tc := NewTypeConverter() 920 inType, err := tc.NomsTypeToGraphQLInputType(nomsType) 921 suite.NoError(err) 922 outType := tc.NomsTypeToGraphQLType(nomsType) 923 suite.assertMutationTypes(query, expected, tc, inType, outType, func(p graphql.ResolveParams) (interface{}, error) { 924 return p.Args["new"], nil 925 }) 926 } 927 928 test(`mutation {test(new: 123)}`, `{"data": {"test": 123}}`, types.NumberType) 929 test(`mutation {test(new: 0)}`, `{"data": {"test": 0}}`, types.NumberType) 930 931 test(`mutation {test(new: "hi")}`, `{"data": {"test": "hi"}}`, types.StringType) 932 test(`mutation {test(new: "")}`, `{"data": {"test": ""}}`, types.StringType) 933 934 test(`mutation {test(new: true)}`, `{"data": {"test": true}}`, types.BoolType) 935 test(`mutation {test(new: false)}`, `{"data": {"test": false}}`, types.BoolType) 936 } 937 938 func (suite *QueryGraphQLSuite) TestMutationWeirdosArgs() { 939 test := func(query, expected string, nomsType *types.Type) { 940 tc := NewTypeConverter() 941 inType, err := tc.NomsTypeToGraphQLInputType(nomsType) 942 suite.NoError(err) 943 outType := graphql.String 944 suite.assertMutationTypes(query, expected, tc, inType, outType, func(p graphql.ResolveParams) (interface{}, error) { 945 return p.Args["new"], nil 946 }) 947 } 948 949 test(`mutation {test(new: "#abc")}`, `{"data": {"test": "#abc"}}`, types.MakeRefType(types.NumberType)) 950 test(`mutation {test(new: "0123456789")}`, `{"data": {"test": "0123456789"}}`, types.BlobType) 951 } 952 953 func (suite *QueryGraphQLSuite) assertMutationTypes(query, expected string, tc *TypeConverter, inType graphql.Input, outType graphql.Type, resolver graphql.FieldResolveFn) { 954 buf := &bytes.Buffer{} 955 root := types.Number(0) 956 schemaConfig := graphql.SchemaConfig{ 957 Mutation: graphql.NewObject(graphql.ObjectConfig{ 958 Name: "Mutation", 959 Fields: graphql.Fields{ 960 "test": &graphql.Field{ 961 Type: outType, 962 Args: graphql.FieldConfigArgument{ 963 "new": &graphql.ArgumentConfig{ 964 Type: inType, 965 }, 966 }, 967 Resolve: resolver, 968 }, 969 }, 970 }), 971 } 972 queryWithSchemaConfig(root, query, schemaConfig, suite.vs, tc, buf) 973 suite.JSONEq(expected, buf.String()) 974 } 975 976 func (suite *QueryGraphQLSuite) TestMutationCollectionArgs() { 977 test := func(query, expected string, expectedArg interface{}, nomsType *types.Type) { 978 tc := NewTypeConverter() 979 inType, err := tc.NomsTypeToGraphQLInputType(nomsType) 980 suite.NoError(err) 981 outType := graphql.Boolean 982 suite.assertMutationTypes(query, expected, tc, inType, outType, func(p graphql.ResolveParams) (interface{}, error) { 983 suite.Equal(expectedArg, p.Args["new"]) 984 return true, nil 985 }) 986 } 987 988 test(`mutation {test(new: [0, 1, 2, 3])}`, `{"data": {"test": true}}`, []interface{}{float64(0), float64(1), float64(2), float64(3)}, types.MakeListType(types.NumberType)) 989 test(`mutation {test(new: [])}`, `{"data": {"test": true}}`, []interface{}{}, types.MakeListType(types.NumberType)) 990 991 test(`mutation {test(new: [0, 1, 2, 3])}`, `{"data": {"test": true}}`, []interface{}{float64(0), float64(1), float64(2), float64(3)}, types.MakeSetType(types.NumberType)) 992 test(`mutation {test(new: [])}`, `{"data": {"test": true}}`, []interface{}{}, types.MakeSetType(types.NumberType)) 993 994 test(`mutation { 995 test(new: [ 996 { 997 key: 1, 998 value: "a" 999 }, { 1000 key: 2, 1001 value: "b" 1002 } 1003 ]) 1004 }`, `{"data": {"test": true}}`, []interface{}{ 1005 map[string]interface{}{"key": float64(1), "value": "a"}, 1006 map[string]interface{}{"key": float64(2), "value": "b"}, 1007 }, types.MakeMapType(types.NumberType, types.StringType)) 1008 test(`mutation {test(new: [])}`, `{"data": {"test": true}}`, []interface{}{}, types.MakeMapType(types.NumberType, types.StringType)) 1009 1010 st := types.MakeStructTypeFromFields("N", types.FieldMap{ 1011 "f": types.NumberType, 1012 "b": types.BoolType, 1013 "s": types.StringType, 1014 }) 1015 test(`mutation {test(new: { 1016 f: 42, 1017 b: true, 1018 s: "hi" 1019 })}`, `{"data": {"test": true}}`, map[string]interface{}{"b": true, "f": float64(42), "s": "hi"}, st) 1020 } 1021 1022 func (suite *QueryGraphQLSuite) TestMapWithComplexKeys() { 1023 m := types.NewMap(suite.vs, 1024 types.NewList(suite.vs, types.String("a")), types.Number(1), 1025 types.NewList(suite.vs, types.String("c")), types.Number(2), 1026 types.NewList(suite.vs, types.String("e")), types.Number(3), 1027 types.NewList(suite.vs, types.String("g")), types.Number(4), 1028 ) 1029 1030 suite.assertQueryResult(m, `{root{values(key: ["e"])}}`, `{"data":{"root":{"values":[3]}}}`) 1031 suite.assertQueryResult(m, `{root{values(key: [])}}`, `{"data":{"root":{"values":[]}}}`) 1032 1033 // The ordering here depends on the hash of the value... 1034 suite.assertQueryResult(m, `{root{values(key: ["a"], through: ["e"])}}`, `{"data":{"root":{"values":[1, 2, 3]}}}`) 1035 1036 suite.assertQueryResult(m, `{root{values(keys: [["a"],["b"],["c"]])}}`, `{"data":{"root":{"values":[1, null, 2]}}}`) 1037 suite.assertQueryResult(m, `{ 1038 root { 1039 keys(keys: [["a"],["b"],["c"]]) { 1040 values 1041 } 1042 } 1043 }`, `{"data": { 1044 "root": { 1045 "keys": [ 1046 {"values": ["a"]}, 1047 {"values": ["b"]}, 1048 {"values": ["c"]} 1049 ] 1050 } 1051 }}`) 1052 1053 m2 := types.NewMap(suite.vs, 1054 types.NewStruct("", types.StructData{ 1055 "n": types.String("a"), 1056 }), types.Number(1), 1057 types.NewStruct("", types.StructData{ 1058 "n": types.String("c"), 1059 }), types.Number(2), 1060 types.NewStruct("", types.StructData{ 1061 "n": types.String("e"), 1062 }), types.Number(3), 1063 types.NewStruct("", types.StructData{ 1064 "n": types.String("g"), 1065 }), types.Number(4), 1066 ) 1067 suite.assertQueryResult(m2, `{root{values(key: {n: "e"})}}`, `{"data":{"root":{"values":[3]}}}`) 1068 suite.assertQueryResult(m2, `{root{values(key: {n: "x"})}}`, `{"data":{"root":{"values":[]}}}`) 1069 // The order is based on hash 1070 suite.assertQueryResult(m2, `{root{values(key: {n: "g"}, through: {n: "c"})}}`, `{"data":{"root":{"values":[4,2]}}}`) 1071 suite.assertQueryResult(m2, `{root{values(keys: [{n: "a"}, {n: "b"}, {n: "c"}])}}`, 1072 `{"data":{"root":{"values":[1, null, 2]}}}`) 1073 suite.assertQueryResult(m2, `{root{keys(keys: [{n: "a"}, {n: "b"}, {n: "c"}]) { n }}}`, 1074 `{"data":{"root":{"keys":[{"n": "a"}, {"n": "b"}, {"n": "c"}]}}}`) 1075 } 1076 1077 func (suite *QueryGraphQLSuite) TestSetWithComplexKeys() { 1078 s := types.NewSet(suite.vs, 1079 types.NewList(suite.vs, types.String("a")), 1080 types.NewList(suite.vs, types.String("c")), 1081 types.NewList(suite.vs, types.String("e")), 1082 types.NewList(suite.vs, types.String("g")), 1083 ) 1084 1085 suite.assertQueryResult(s, `{root{values(key: ["e"]) { values }}}`, 1086 `{"data":{"root":{"values":[{"values":["e"]}]}}}`) 1087 suite.assertQueryResult(s, `{root{values(key: []) { values }}}`, `{"data":{"root":{"values":[]}}}`) 1088 1089 // The ordering here depends on the hash of the value... 1090 suite.assertQueryResult(s, `{root{values(key: ["g"], through: ["c"]) { values }}}`, 1091 `{"data":{"root":{"values":[{"values":["g"]},{"values":["a"]},{"values":["c"]}]}}}`) 1092 1093 s2 := types.NewSet(suite.vs, 1094 types.NewStruct("", types.StructData{ 1095 "n": types.String("a"), 1096 }), 1097 types.NewStruct("", types.StructData{ 1098 "n": types.String("c"), 1099 }), 1100 types.NewStruct("", types.StructData{ 1101 "n": types.String("e"), 1102 }), 1103 types.NewStruct("", types.StructData{ 1104 "n": types.String("g"), 1105 }), 1106 ) 1107 1108 suite.assertQueryResult(s2, `{root{values(key: {n: "e"}) { n } }}`, 1109 `{"data":{"root":{"values":[{"n": "e"}]}}}`) 1110 suite.assertQueryResult(s2, `{root{values(key: {n: "x"}) { n } }}`, `{"data":{"root":{"values":[]}}}`) 1111 // The order is based on hash 1112 suite.assertQueryResult(s2, `{root{values(key: {n: "c"}, through: {n: "e"}) { n }}}`, 1113 `{"data":{"root":{"values":[{"n": "c"}, {"n": "e"}]}}}`) 1114 } 1115 1116 func (suite *QueryGraphQLSuite) TestInputToNomsValue() { 1117 test := func(expected types.Value, val interface{}) { 1118 suite.True(expected.Equals(InputToNomsValue(suite.vs, val, types.TypeOf(expected)))) 1119 } 1120 1121 test(types.Number(42), int(42)) 1122 test(types.Number(0), int(0)) 1123 1124 test(types.Number(1.23), float64(1.23)) 1125 test(types.Number(0), float64(0)) 1126 1127 test(types.Bool(true), true) 1128 test(types.Bool(false), false) 1129 1130 test(types.String("hi"), "hi") 1131 test(types.String(""), "") 1132 1133 test(types.NewList(suite.vs, types.Number(42)), []interface{}{float64(42)}) 1134 test(types.NewList(suite.vs, types.Number(1), types.Number(2)), []interface{}{float64(1), float64(2)}) 1135 1136 test(types.NewSet(suite.vs, types.Number(42)), []interface{}{float64(42)}) 1137 test(types.NewSet(suite.vs, types.Number(1), types.Number(2)), []interface{}{float64(1), float64(2)}) 1138 1139 test(types.NewMap(suite.vs, 1140 types.String("a"), types.Number(1), 1141 types.String("b"), types.Number(2), 1142 ), []interface{}{ 1143 map[string]interface{}{"key": "a", "value": 1}, 1144 map[string]interface{}{"key": "b", "value": 2}, 1145 }) 1146 test(types.NewMap(suite.vs, 1147 types.NewList(suite.vs, types.String("a")), types.Number(1), 1148 types.NewList(suite.vs, types.String("b")), types.Number(2), 1149 ), []interface{}{ 1150 map[string]interface{}{"key": []interface{}{"a"}, "value": 1}, 1151 map[string]interface{}{"key": []interface{}{"b"}, "value": 2}, 1152 }) 1153 1154 test(types.NewMap(suite.vs, 1155 types.NewStruct("S", types.StructData{"a": types.Number(1)}), types.Number(11), 1156 types.NewStruct("S", types.StructData{"a": types.Number(2)}), types.Number(22), 1157 ), []interface{}{ 1158 map[string]interface{}{"key": map[string]interface{}{"a": float64(1)}, "value": 11}, 1159 map[string]interface{}{"key": map[string]interface{}{"a": float64(2)}, "value": 22}, 1160 }) 1161 1162 test(types.NewSet(suite.vs, 1163 types.NewStruct("S", types.StructData{"a": types.Number(1)}), 1164 types.NewStruct("S", types.StructData{"a": types.Number(2)}), 1165 ), []interface{}{ 1166 map[string]interface{}{"a": float64(1)}, 1167 map[string]interface{}{"a": float64(2)}, 1168 }) 1169 1170 expected := types.NewStruct("S", types.StructData{ 1171 "x": types.Number(42), 1172 }) 1173 expectedType := types.MakeStructType("S", 1174 types.StructField{Name: "a", Type: types.BoolType, Optional: true}, 1175 types.StructField{Name: "x", Type: types.NumberType, Optional: false}, 1176 ) 1177 val := map[string]interface{}{ 1178 "x": float64(42), 1179 } 1180 suite.Equal(expected, InputToNomsValue(suite.vs, val, expectedType)) 1181 1182 val = map[string]interface{}{ 1183 "x": float64(42), 1184 "a": nil, 1185 } 1186 suite.Equal(expected, InputToNomsValue(suite.vs, val, expectedType)) 1187 1188 val = map[string]interface{}{ 1189 "x": nil, 1190 } 1191 suite.Panics(func() { 1192 InputToNomsValue(suite.vs, val, expectedType) 1193 }) 1194 } 1195 1196 func (suite *QueryGraphQLSuite) TestErrorsInInputType() { 1197 ut := types.MakeUnionType(types.BoolType, types.NumberType) 1198 1199 test := func(t *types.Type) { 1200 tm := NewTypeMap() 1201 _, err := NomsTypeToGraphQLInputType(t, tm) 1202 suite.Error(err) 1203 } 1204 1205 test(ut) 1206 test(types.MakeListType(ut)) 1207 test(types.MakeSetType(ut)) 1208 test(types.MakeMapType(ut, types.BoolType)) 1209 test(types.MakeMapType(types.BoolType, ut)) 1210 test(types.MakeMapType(ut, ut)) 1211 test(types.MakeStructTypeFromFields("", types.FieldMap{"u": ut})) 1212 1213 test(types.MakeStructTypeFromFields("S", types.FieldMap{ 1214 "l": types.MakeListType(types.MakeCycleType("S")), 1215 })) 1216 test(types.MakeStructTypeFromFields("S", types.FieldMap{ 1217 "n": types.NumberType, 1218 "l": types.MakeListType(types.MakeCycleType("S")), 1219 })) 1220 } 1221 1222 func (suite *QueryGraphQLSuite) TestVariables() { 1223 test := func(rootValue types.Value, expected string, query string, vars map[string]interface{}) { 1224 tc := NewTypeConverter() 1225 ctx := NewContext(suite.vs) 1226 schema, err := graphql.NewSchema(graphql.SchemaConfig{ 1227 Query: tc.NewRootQueryObject(rootValue), 1228 }) 1229 suite.NoError(err) 1230 1231 r := graphql.Do(graphql.Params{ 1232 Schema: schema, 1233 RequestString: query, 1234 Context: ctx, 1235 VariableValues: vars, 1236 }) 1237 b, err := json.Marshal(r) 1238 suite.NoError(err) 1239 suite.JSONEq(expected, string(b)) 1240 } 1241 1242 v := types.NewList(suite.vs, types.Number(0), types.Number(1), types.Number(2), types.Number(3)) 1243 test(v, `{"data":{"root":{"values":[0,1,2,3]}}}`, `query Test($c: Int) { root { values(count: $c) } }`, nil) 1244 test(v, `{"data":{"root":{"values":[0,1]}}}`, `query Test($c: Int) { root { values(count: $c) } }`, map[string]interface{}{ 1245 "c": 2, 1246 }) 1247 1248 m := types.NewMap(suite.vs, 1249 types.String("a"), types.Number(0), 1250 types.String("b"), types.Number(1), 1251 types.String("c"), types.Number(2), 1252 types.String("d"), types.Number(3), 1253 ) 1254 test(m, `{"data":{"root":{"values":[1]}}}`, `query Test($k: String) { root { values(key: $k) } }`, map[string]interface{}{ 1255 "k": "b", 1256 }) 1257 test(m, `{"data":{"root":{"values":[1, 2]}}}`, `query Test($k: String, $t: String) { root { values(key: $k, through: $t) } }`, 1258 map[string]interface{}{ 1259 "k": "b", 1260 "t": "c", 1261 }) 1262 test(m, `{"data":{"root":{"values":[0, 2]}}}`, `query Test($ks: [String!]!) { root { values(keys: $ks) } }`, 1263 map[string]interface{}{ 1264 "ks": []string{"a", "c"}, 1265 }) 1266 1267 m2 := types.NewMap(suite.vs, 1268 types.NewStruct("S", types.StructData{"n": types.String("a")}), types.Number(0), 1269 types.NewStruct("S", types.StructData{"n": types.String("b")}), types.Number(1), 1270 types.NewStruct("S", types.StructData{"n": types.String("c")}), types.Number(2), 1271 types.NewStruct("S", types.StructData{"n": types.String("d")}), types.Number(3), 1272 ) 1273 keyType := types.TypeOf(m2).Desc.(types.CompoundDesc).ElemTypes[0] 1274 q := fmt.Sprintf(`query Test($k: %s) { root { values(key: $k) } }`, GetInputTypeName(keyType)) 1275 test(m2, `{"data":{"root":{"values":[1]}}}`, q, map[string]interface{}{ 1276 "k": map[string]interface{}{ 1277 "n": "b", 1278 }, 1279 }) 1280 q = fmt.Sprintf(`query Test($ks: [%s!]) { root { values(keys: $ks) } }`, GetInputTypeName(keyType)) 1281 test(m2, `{"data":{"root":{"values":[0, 3]}}}`, q, map[string]interface{}{ 1282 "ks": []interface{}{ 1283 map[string]interface{}{ 1284 "n": "a", 1285 }, 1286 map[string]interface{}{ 1287 "n": "d", 1288 }, 1289 }, 1290 }) 1291 test(m2, `{"data":null,"errors":[{"message":"Variable \"$ks\" got invalid value [{}].\nIn element #1: In field \"n\": Expected \"String!\", found null.","locations":[{"line":1,"column":12}]}]}`, 1292 q, 1293 map[string]interface{}{ 1294 "ks": []interface{}{ 1295 map[string]interface{}{}, 1296 }, 1297 }, 1298 ) 1299 test(m2, `{"data":null,"errors":[{"message":"Variable \"$ks\" got invalid value [{\"m\":\"b\",\"n\":\"a\"}].\nIn element #1: In field \"m\": Unknown field.","locations":[{"line":1,"column":12}]}]}`, 1300 q, 1301 map[string]interface{}{ 1302 "ks": []interface{}{ 1303 map[string]interface{}{ 1304 "n": "a", 1305 "m": "b", 1306 }, 1307 }, 1308 }, 1309 ) 1310 test(m2, `{"data":null,"errors":[{"message":"Variable \"$ks\" got invalid value [{\"n\":null}].\nIn element #1: In field \"n\": Expected \"String!\", found null.","locations":[{"line":1,"column":12}]}]}`, 1311 q, 1312 map[string]interface{}{ 1313 "ks": []interface{}{ 1314 map[string]interface{}{ 1315 "n": nil, 1316 }, 1317 }, 1318 }, 1319 ) 1320 test(m2, `{"data":null,"errors":[{"message":"Variable \"$ks\" got invalid value [null].\nIn element #1: Expected \"SInput_cgmdbo!\", found null.","locations":[{"line":1,"column":12}]}]}`, 1321 q, 1322 map[string]interface{}{ 1323 "ks": []interface{}{ 1324 nil, 1325 }, 1326 }, 1327 ) 1328 1329 m3 := types.NewMap(suite.vs, 1330 types.NewMap(suite.vs, types.Number(0), types.String("zero")), types.Bool(false), 1331 types.NewMap(suite.vs, types.Number(1), types.String("one")), types.Bool(true), 1332 ) 1333 keyNomsType := types.TypeOf(m3).Desc.(types.CompoundDesc).ElemTypes[0] 1334 tc := NewTypeConverter() 1335 keyGraphQLInputType, err := tc.NomsTypeToGraphQLInputType(keyNomsType) 1336 suite.NoError(err) 1337 q = fmt.Sprintf(`query Test($k: %s!) { root { values(key: $k) } }`, keyGraphQLInputType.String()) 1338 test(m3, `{"data":{"root":{"values":[false]}}}`, q, map[string]interface{}{ 1339 "k": []interface{}{ 1340 map[string]interface{}{ 1341 "key": float64(0), 1342 "value": "zero", 1343 }, 1344 }, 1345 }) 1346 test(m3, `{"data":null,"errors":[{"message":"Variable \"$k\" got invalid value [{\"key\":0}].\nIn element #1: In field \"value\": Expected \"String!\", found null.","locations":[{"line":1,"column":12}]}]}`, 1347 q, 1348 map[string]interface{}{ 1349 "k": []interface{}{ 1350 map[string]interface{}{ 1351 "key": float64(0), 1352 }, 1353 }, 1354 }) 1355 test(m3, `{"data":null,"errors":[{"message":"Variable \"$k\" got invalid value [{\"key\":\"zero\"}].\nIn element #1: In field \"key\": Expected type \"Float\", found \"zero\".\nIn element #2: In field \"value\": Expected \"String!\", found null.","locations":[{"line":1,"column":12}]}]}`, 1356 q, 1357 map[string]interface{}{ 1358 "k": []interface{}{ 1359 map[string]interface{}{ 1360 "key": "zero", 1361 }, 1362 }, 1363 }) 1364 test(m3, `{"data":null,"errors":[{"message":"Variable \"$k\" got invalid value [{\"extra\":false,\"key\":0,\"value\":\"zero\"}].\nIn element #1: In field \"extra\": Unknown field.","locations":[{"line":1,"column":12}]}]}`, 1365 q, 1366 map[string]interface{}{ 1367 "k": []interface{}{ 1368 map[string]interface{}{ 1369 "key": float64(0), 1370 "value": "zero", 1371 "extra": false, 1372 }, 1373 }, 1374 }) 1375 test(m3, `{"data":null,"errors":[{"message":"Variable \"$k\" got invalid value [null].\nIn element #1: Expected \"NumberStringEntryInput!\", found null.","locations":[{"line":1,"column":12}]}]}`, 1376 q, 1377 map[string]interface{}{ 1378 "k": []interface{}{ 1379 nil, 1380 }, 1381 }) 1382 } 1383 1384 func (suite *QueryGraphQLSuite) TestNameFunc() { 1385 test := func(tc *TypeConverter, rootValue types.Value, expected string, query string, vars map[string]interface{}) { 1386 ctx := NewContext(suite.vs) 1387 schema, err := graphql.NewSchema(graphql.SchemaConfig{ 1388 Query: tc.NewRootQueryObject(rootValue), 1389 }) 1390 suite.NoError(err) 1391 1392 r := graphql.Do(graphql.Params{ 1393 Schema: schema, 1394 RequestString: query, 1395 Context: ctx, 1396 VariableValues: vars, 1397 }) 1398 1399 b, err := json.Marshal(r) 1400 suite.NoError(err) 1401 suite.JSONEq(expected, string(b)) 1402 } 1403 1404 aVal := types.NewStruct("A", types.StructData{ 1405 "a": types.Number(1), 1406 }) 1407 bVal := types.NewStruct("B", types.StructData{ 1408 "b": types.Number(2), 1409 }) 1410 1411 list := types.NewList(suite.vs, aVal, bVal) 1412 1413 tc := NewTypeConverter() 1414 tc.NameFunc = func(nomsType *types.Type, isInputType bool) string { 1415 if nomsType.Equals(types.TypeOf(aVal)) { 1416 return "A" 1417 } 1418 if nomsType.Equals(types.TypeOf(bVal)) { 1419 return "BBB" 1420 } 1421 return DefaultNameFunc(nomsType, isInputType) 1422 } 1423 1424 query := `query { 1425 root { 1426 values { 1427 ... on A { 1428 a 1429 } 1430 ... on BBB { 1431 b 1432 } 1433 } 1434 } 1435 }` 1436 expected := `{ 1437 "data": { 1438 "root": { 1439 "values": [ 1440 {"a": 1}, 1441 {"b": 2} 1442 ] 1443 } 1444 } 1445 }` 1446 test(tc, list, expected, query, nil) 1447 1448 set := types.NewSet(suite.vs, aVal, 1449 types.NewStruct("A", types.StructData{ 1450 "a": types.Number(2), 1451 }), 1452 types.NewStruct("A", types.StructData{ 1453 "a": types.Number(3), 1454 }), 1455 ) 1456 tc = NewTypeConverter() 1457 tc.NameFunc = func(nomsType *types.Type, isInputType bool) string { 1458 if nomsType.Equals(types.TypeOf(aVal)) { 1459 if isInputType { 1460 return "AI" 1461 } 1462 return "A" 1463 } 1464 return DefaultNameFunc(nomsType, isInputType) 1465 } 1466 1467 query = `query ($key: AI!) { 1468 root { 1469 values(key: $key) { 1470 a 1471 } 1472 } 1473 }` 1474 expected = `{ 1475 "data": { 1476 "root": { 1477 "values": [ 1478 {"a": 2} 1479 ] 1480 } 1481 } 1482 }` 1483 test(tc, set, expected, query, map[string]interface{}{ 1484 "key": map[string]interface{}{"a": 2}, 1485 }) 1486 } 1487 1488 func TestGetListElementsWithSet(t *testing.T) { 1489 assert := assert.New(t) 1490 vs := newTestValueStore() 1491 v := types.NewSet(vs, types.Number(0), types.Number(1), types.Number(2)) 1492 r := getListElements(vs, v, map[string]interface{}{}) 1493 assert.Equal([]interface{}{float64(0), float64(1), float64(2)}, r) 1494 1495 r = getListElements(vs, v, map[string]interface{}{ 1496 atKey: 1, 1497 }) 1498 assert.Equal([]interface{}{float64(1), float64(2)}, r) 1499 1500 r = getListElements(vs, v, map[string]interface{}{ 1501 countKey: 2, 1502 }) 1503 assert.Equal([]interface{}{float64(0), float64(1)}, r) 1504 } 1505 1506 func TestNoErrorOnNonCyclicTypeRefsInputType(t *testing.T) { 1507 assert := assert.New(t) 1508 1509 type User struct { 1510 ID string `noms:"id"` 1511 } 1512 type Account struct { 1513 PendingUsers map[string]User 1514 Users map[string]User 1515 } 1516 1517 var a Account 1518 typ := marshal.MustMarshalType(a) 1519 tc := NewTypeConverter() 1520 _, err := tc.NomsTypeToGraphQLInputType(typ) 1521 assert.NoError(err) 1522 } 1523 1524 func TestErrorOnCyclicTypeRefsInputType(t *testing.T) { 1525 assert := assert.New(t) 1526 1527 type Node struct { 1528 Children map[string]Node 1529 } 1530 1531 var n Node 1532 typ := marshal.MustMarshalType(n) 1533 tc := NewTypeConverter() 1534 _, err := tc.NomsTypeToGraphQLInputType(typ) 1535 assert.Error(err) 1536 }