github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/query/query1_test.go (about) 1 /* 2 * Copyright 2018 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package query 18 19 import ( 20 "context" 21 "encoding/json" 22 "io/ioutil" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/require" 28 "google.golang.org/grpc/metadata" 29 ) 30 31 func TestSchemaBlock2(t *testing.T) { 32 query := ` 33 schema(pred: name) { 34 index 35 reverse 36 type 37 tokenizer 38 count 39 } 40 ` 41 42 js := processQueryNoErr(t, query) 43 require.JSONEq(t, `{"data":{"schema":[{"predicate":"name","type":"string","index":true,"tokenizer":["term","exact","trigram"],"count":true}]}}`, js) 44 } 45 46 func TestSchemaBlock3(t *testing.T) { 47 query := ` 48 schema(pred: age) { 49 index 50 reverse 51 type 52 tokenizer 53 count 54 } 55 ` 56 js := processQueryNoErr(t, query) 57 require.JSONEq(t, `{"data":{"schema":[{"predicate":"age","type":"int","index":true,"tokenizer":["int"]}]}}`, js) 58 } 59 60 func TestSchemaBlock4(t *testing.T) { 61 query := ` 62 schema(pred: [age, genre, random]) { 63 index 64 reverse 65 type 66 tokenizer 67 } 68 ` 69 js := processQueryNoErr(t, query) 70 require.JSONEq(t, `{"data":{"schema":[{"predicate":"age","type":"int","index":true,"tokenizer":["int"]},{"predicate":"genre","type":"uid","reverse":true}]}}`, js) 71 } 72 73 func TestSchemaBlock5(t *testing.T) { 74 query := ` 75 schema(pred: name) { 76 } 77 ` 78 79 js := processQueryNoErr(t, query) 80 require.JSONEq(t, `{"data":{"schema":[{"predicate":"name","type":"string","index":true,"tokenizer":["term","exact","trigram"],"count":true,"lang":true}]}}`, js) 81 } 82 83 func TestFilterNonIndexedPredicateFail(t *testing.T) { 84 85 // filtering on non indexing predicate fails 86 query := ` 87 { 88 me(func: uid(0x01)) { 89 friend @filter(le(survival_rate, 30)) { 90 uid 91 name 92 age 93 } 94 } 95 } 96 ` 97 _, err := processQuery(context.Background(), t, query) 98 require.Error(t, err) 99 } 100 101 func TestMultipleSamePredicateInBlockFail(t *testing.T) { 102 103 // name is asked for two times.. 104 query := ` 105 { 106 me(func: uid(0x01)) { 107 name 108 friend { 109 age 110 } 111 name 112 } 113 } 114 ` 115 _, err := processQuery(context.Background(), t, query) 116 require.Error(t, err) 117 } 118 119 func TestMultipleSamePredicateInBlockFail2(t *testing.T) { 120 121 // age is asked for two times.. 122 query := ` 123 { 124 me(func: uid(0x01)) { 125 friend { 126 age 127 age 128 } 129 name 130 } 131 } 132 ` 133 _, err := processQuery(context.Background(), t, query) 134 require.Error(t, err) 135 } 136 137 func TestMultipleSamePredicateInBlockFail3(t *testing.T) { 138 139 // friend is asked for two times.. 140 query := ` 141 { 142 me(func: uid(0x01)) { 143 friend { 144 age 145 } 146 friend { 147 name 148 } 149 name 150 } 151 } 152 ` 153 _, err := processQuery(context.Background(), t, query) 154 require.Error(t, err) 155 } 156 157 func TestXidInvalidJSON(t *testing.T) { 158 159 query := ` 160 { 161 me(func: uid(0x01)) { 162 name 163 _xid_ 164 gender 165 alive 166 friend { 167 _xid_ 168 random 169 name 170 } 171 } 172 } 173 ` 174 js := processQueryNoErr(t, query) 175 require.JSONEq(t, 176 `{"data": {"me":[{"_xid_":"mich","alive":true,"friend":[{"name":"Rick Grimes"},{"_xid_":"g\"lenn","name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"gender":"female","name":"Michonne"}]}}`, 177 js) 178 m := make(map[string]interface{}) 179 err := json.Unmarshal([]byte(js), &m) 180 require.NoError(t, err) 181 } 182 183 func TestToJSONReverseNegativeFirst(t *testing.T) { 184 185 query := ` 186 { 187 me(func: allofterms(name, "Andrea")) { 188 name 189 ~friend (first: -1) { 190 name 191 gender 192 } 193 } 194 } 195 ` 196 js := processQueryNoErr(t, query) 197 require.JSONEq(t, 198 `{"data": {"me":[{"name":"Andrea","~friend":[{"gender":"female","name":"Michonne"}]},{"name":"Andrea With no friends"}]}}`, 199 js) 200 } 201 202 func TestToFastJSONOrderLang(t *testing.T) { 203 204 query := ` 205 { 206 me(func: uid(0x01)) { 207 friend(first:2, orderdesc: alias@en:de:.) { 208 alias 209 } 210 } 211 } 212 ` 213 214 js := processQueryNoErr(t, query) 215 require.JSONEq(t, 216 `{"data": {"me":[{"friend":[{"alias":"Zambo Alice"},{"alias":"John Oliver"}]}]}}`, 217 js) 218 } 219 220 func TestBoolIndexEqRoot1(t *testing.T) { 221 222 query := ` 223 { 224 me(func: eq(alive, true)) { 225 name 226 alive 227 } 228 } 229 ` 230 js := processQueryNoErr(t, query) 231 require.JSONEq(t, 232 `{"data": {"me":[{"alive":true,"name":"Michonne"},{"alive":true,"name":"Rick Grimes"}]}}`, 233 js) 234 } 235 236 func TestBoolIndexEqRoot2(t *testing.T) { 237 238 query := ` 239 { 240 me(func: eq(alive, false)) { 241 name 242 alive 243 } 244 } 245 ` 246 js := processQueryNoErr(t, query) 247 require.JSONEq(t, 248 `{"data": {"me":[{"alive":false,"name":"Daryl Dixon"},{"alive":false,"name":"Andrea"}]}}`, 249 js) 250 } 251 252 func TestBoolIndexgeRoot(t *testing.T) { 253 254 q := ` 255 { 256 me(func: ge(alive, true)) { 257 name 258 alive 259 friend { 260 name 261 alive 262 } 263 } 264 }` 265 266 _, err := processQuery(context.Background(), t, q) 267 require.Error(t, err) 268 } 269 270 func TestBoolIndexEqChild(t *testing.T) { 271 272 query := ` 273 { 274 me(func: eq(alive, true)) { 275 name 276 alive 277 friend @filter(eq(alive, false)) { 278 name 279 alive 280 } 281 } 282 } 283 ` 284 js := processQueryNoErr(t, query) 285 require.JSONEq(t, 286 `{"data": {"me":[{"alive":true,"friend":[{"alive":false,"name":"Daryl Dixon"},{"alive":false,"name":"Andrea"}],"name":"Michonne"},{"alive":true,"name":"Rick Grimes"}]}}`, 287 js) 288 } 289 290 func TestBoolSort(t *testing.T) { 291 292 q := ` 293 { 294 me(func: anyofterms(name, "Michonne Andrea Rick"), orderasc: alive) { 295 name 296 alive 297 } 298 } 299 ` 300 301 _, err := processQuery(context.Background(), t, q) 302 require.Error(t, err) 303 } 304 305 func TestStringEscape(t *testing.T) { 306 307 query := ` 308 { 309 me(func: uid(2301)) { 310 name 311 } 312 } 313 ` 314 js := processQueryNoErr(t, query) 315 require.JSONEq(t, 316 `{"data": {"me":[{"name":"Alice\""}]}}`, 317 js) 318 } 319 320 func TestJSONQueryVariables(t *testing.T) { 321 322 q := `query test ($a: int = 1) { 323 me(func: uid(0x01)) { 324 name 325 gender 326 friend(first: $a) { 327 name 328 } 329 } 330 }` 331 js, err := processQueryWithVars(t, q, map[string]string{"$a": "2"}) 332 require.NoError(t, err) 333 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"}],"gender":"female","name":"Michonne"}]}}`, js) 334 } 335 336 func TestOrderDescFilterCount(t *testing.T) { 337 338 query := ` 339 { 340 me(func: uid(0x01)) { 341 friend(first:2, orderdesc: age) @filter(eq(alias, "Zambo Alice")) { 342 alias 343 } 344 } 345 } 346 ` 347 348 js := processQueryNoErr(t, query) 349 require.JSONEq(t, 350 `{"data": {"me":[{"friend":[{"alias":"Zambo Alice"}]}]}}`, 351 js) 352 } 353 354 func TestHashTokEq(t *testing.T) { 355 356 query := ` 357 { 358 me(func: eq(full_name, "Michonne's large name for hashing")) { 359 full_name 360 alive 361 friend { 362 name 363 } 364 } 365 } 366 ` 367 js := processQueryNoErr(t, query) 368 require.JSONEq(t, 369 `{"data": {"me":[{"alive":true,"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"full_name":"Michonne's large name for hashing"}]}}`, 370 js) 371 } 372 373 func TestHashTokGeqErr(t *testing.T) { 374 375 query := ` 376 { 377 me(func: ge(full_name, "Michonne's large name for hashing")) { 378 full_name 379 alive 380 friend { 381 name 382 } 383 } 384 } 385 ` 386 _, err := processQuery(context.Background(), t, query) 387 require.Error(t, err) 388 } 389 390 func TestNameNotIndexed(t *testing.T) { 391 392 query := ` 393 { 394 me(func: eq(noindex_name, "Michonne's name not indexed")) { 395 full_name 396 alive 397 friend { 398 name 399 } 400 } 401 } 402 ` 403 404 _, err := processQuery(context.Background(), t, query) 405 require.Error(t, err) 406 } 407 408 func TestMultipleMinMax(t *testing.T) { 409 410 query := ` 411 { 412 me(func: uid(0x01)) { 413 friend { 414 x as age 415 n as name 416 } 417 min(val(x)) 418 max(val(x)) 419 min(val(n)) 420 max(val(n)) 421 } 422 }` 423 js := processQueryNoErr(t, query) 424 require.JSONEq(t, 425 `{"data": {"me":[{"friend":[{"age":15,"name":"Rick Grimes"},{"age":15,"name":"Glenn Rhee"},{"age":17,"name":"Daryl Dixon"},{"age":19,"name":"Andrea"}],"max(val(n))":"Rick Grimes","max(val(x))":19,"min(val(n))":"Andrea","min(val(x))":15}]}}`, 426 js) 427 } 428 429 func TestDuplicateAlias(t *testing.T) { 430 431 query := ` 432 { 433 me(func: uid(0x01)) { 434 friend { 435 x as age 436 } 437 a: min(val(x)) 438 a: max(val(x)) 439 } 440 }` 441 442 _, err := processQuery(context.Background(), t, query) 443 require.Error(t, err) 444 } 445 446 func TestGraphQLId(t *testing.T) { 447 448 q := `query test ($a: string = 1) { 449 me(func: uid($a)) { 450 name 451 gender 452 friend(first: 1) { 453 name 454 } 455 } 456 }` 457 js, err := processQueryWithVars(t, q, map[string]string{"$a": "[1, 31]"}) 458 require.NoError(t, err) 459 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Rick Grimes"}],"gender":"female","name":"Michonne"},{"friend":[{"name":"Glenn Rhee"}],"name":"Andrea"}]}}`, js) 460 } 461 462 func TestDebugUid(t *testing.T) { 463 464 query := ` 465 { 466 me(func: uid(0x01)) { 467 name 468 friend { 469 name 470 friend 471 } 472 } 473 }` 474 475 md := metadata.Pairs("debug", "true") 476 ctx := context.Background() 477 ctx = metadata.NewOutgoingContext(ctx, md) 478 479 buf, err := processQuery(ctx, t, query) 480 require.NoError(t, err) 481 var mp map[string]interface{} 482 require.NoError(t, json.Unmarshal([]byte(buf), &mp)) 483 resp := mp["data"].(map[string]interface{})["me"] 484 body, err := json.Marshal(resp) 485 require.NoError(t, err) 486 require.JSONEq(t, `[{"friend":[{"name":"Rick Grimes","uid":"0x17"},{"name":"Glenn Rhee","uid":"0x18"},{"name":"Daryl Dixon","uid":"0x19"},{"name":"Andrea","uid":"0x1f"}],"name":"Michonne","uid":"0x1"}]`, string(body)) 487 } 488 489 func TestUidAlias(t *testing.T) { 490 491 query := ` 492 { 493 me(func: uid(0x1)) { 494 id: uid 495 alive 496 friend { 497 uid: uid 498 name 499 } 500 } 501 } 502 ` 503 js := processQueryNoErr(t, query) 504 require.JSONEq(t, 505 `{"data": {"me":[{"alive":true,"friend":[{"name":"Rick Grimes","uid":"0x17"},{"name":"Glenn Rhee","uid":"0x18"},{"name":"Daryl Dixon","uid":"0x19"},{"name":"Andrea","uid":"0x1f"},{"uid":"0x65"}],"id":"0x1"}]}}`, 506 js) 507 } 508 509 func TestCountAtRoot(t *testing.T) { 510 511 query := ` 512 { 513 me(func: gt(count(friend), 0)) { 514 count(uid) 515 } 516 } 517 ` 518 js := processQueryNoErr(t, query) 519 require.JSONEq(t, `{"data": {"me":[{"count": 3}]}}`, js) 520 } 521 522 func TestCountAtRoot2(t *testing.T) { 523 524 query := ` 525 { 526 me(func: anyofterms(name, "Michonne Rick Andrea")) { 527 count(uid) 528 } 529 } 530 ` 531 js := processQueryNoErr(t, query) 532 require.JSONEq(t, `{"data": {"me":[{"count": 4}]}}`, js) 533 } 534 535 func TestCountAtRoot3(t *testing.T) { 536 537 query := ` 538 { 539 me(func:anyofterms(name, "Michonne Rick Daryl")) { 540 name 541 count(uid) 542 count(friend) 543 friend { 544 name 545 count(uid) 546 } 547 } 548 } 549 ` 550 js := processQueryNoErr(t, query) 551 require.JSONEq(t, `{"data": {"me":[{"count":3},{"count(friend)":5,"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"},{"count":5}],"name":"Michonne"},{"count(friend)":1,"friend":[{"name":"Michonne"},{"count":1}],"name":"Rick Grimes"},{"count(friend)":0,"name":"Daryl Dixon"}]}}`, js) 552 } 553 554 func TestCountAtRootWithAlias4(t *testing.T) { 555 556 query := ` 557 { 558 me(func:anyofterms(name, "Michonne Rick Daryl")) @filter(le(count(friend), 2)) { 559 personCount: count(uid) 560 } 561 } 562 ` 563 js := processQueryNoErr(t, query) 564 require.JSONEq(t, `{"data": {"me": [{"personCount": 2}]}}`, js) 565 } 566 567 func TestCountAtRoot5(t *testing.T) { 568 569 query := ` 570 { 571 me(func: uid(1)) { 572 f as friend { 573 name 574 } 575 } 576 MichonneFriends(func: uid(f)) { 577 count(uid) 578 } 579 } 580 581 582 ` 583 js := processQueryNoErr(t, query) 584 require.JSONEq(t, `{"data": {"MichonneFriends":[{"count":5}],"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}]}}`, js) 585 } 586 587 func TestHasFuncAtRoot(t *testing.T) { 588 589 query := ` 590 { 591 me(func: has(friend)) { 592 name 593 friend { 594 count(uid) 595 } 596 } 597 } 598 ` 599 600 js := processQueryNoErr(t, query) 601 require.JSONEq(t, `{"data": {"me":[{"friend":[{"count":5}],"name":"Michonne"},{"friend":[{"count":1}],"name":"Rick Grimes"},{"friend":[{"count":1}],"name":"Andrea"}]}}`, js) 602 } 603 604 func TestHasFuncAtRootWithAfter(t *testing.T) { 605 606 query := ` 607 { 608 me(func: has(friend), after: 0x01) { 609 uid 610 name 611 friend { 612 count(uid) 613 } 614 } 615 } 616 ` 617 618 js := processQueryNoErr(t, query) 619 require.JSONEq(t, `{"data": {"me":[{"friend":[{"count":1}],"name":"Rick Grimes","uid":"0x17"},{"friend":[{"count":1}],"name":"Andrea","uid":"0x1f"}]}}`, js) 620 } 621 622 func TestHasFuncAtRootFilter(t *testing.T) { 623 624 query := ` 625 { 626 me(func: anyofterms(name, "Michonne Rick Daryl")) @filter(has(friend)) { 627 name 628 friend { 629 count(uid) 630 } 631 } 632 } 633 ` 634 635 js := processQueryNoErr(t, query) 636 require.JSONEq(t, `{"data": {"me":[{"friend":[{"count":5}],"name":"Michonne"},{"friend":[{"count":1}],"name":"Rick Grimes"}]}}`, js) 637 } 638 639 func TestHasFuncAtChild1(t *testing.T) { 640 641 query := ` 642 { 643 me(func: has(school)) { 644 name 645 friend @filter(has(scooter)) { 646 name 647 } 648 } 649 } 650 ` 651 652 js := processQueryNoErr(t, query) 653 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"},{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`, js) 654 } 655 656 func TestHasFuncAtChild2(t *testing.T) { 657 658 query := ` 659 { 660 me(func: has(school)) { 661 name 662 friend @filter(has(alias)) { 663 name 664 alias 665 } 666 } 667 } 668 ` 669 670 js := processQueryNoErr(t, query) 671 require.JSONEq(t, `{"data": {"me":[{"friend":[{"alias":"Zambo Alice","name":"Rick Grimes"},{"alias":"John Alice","name":"Glenn Rhee"},{"alias":"Bob Joe","name":"Daryl Dixon"},{"alias":"Allan Matt","name":"Andrea"},{"alias":"John Oliver"}],"name":"Michonne"},{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"friend":[{"alias":"John Alice","name":"Glenn Rhee"}],"name":"Andrea"}]}}`, js) 672 } 673 674 func TestHasFuncAtRoot2(t *testing.T) { 675 676 query := ` 677 { 678 me(func: has(name@en)) { 679 name@en 680 } 681 } 682 ` 683 684 js := processQueryNoErr(t, query) 685 require.JSONEq(t, `{"data": {"me":[{"name@en":"Alex"},{"name@en":"Amit"},{"name@en":"Andrew"}, 686 {"name@en":"European badger"},{"name@en":"Honey badger"},{"name@en":"Honey bee"}, 687 {"name@en":"Artem Tkachenko"},{"name@en":"Baz Luhrmann"},{"name@en":"Strictly Ballroom"}, 688 {"name@en":"Puccini: La boheme (Sydney Opera)"}, {"name@en":"No. 5 the film"}]}}`, js) 689 } 690 691 func TestMathVarCrash(t *testing.T) { 692 693 query := ` 694 { 695 f(func: anyofterms(name, "Rick Michonne Andrea")) { 696 age as age 697 a as math(age *2) 698 val(a) 699 } 700 } 701 ` 702 _, err := processQuery(context.Background(), t, query) 703 require.Error(t, err) 704 } 705 706 func TestMathVarAlias(t *testing.T) { 707 708 query := ` 709 { 710 f(func: anyofterms(name, "Rick Michonne Andrea")) { 711 ageVar as age 712 a: math(ageVar *2) 713 } 714 } 715 ` 716 js := processQueryNoErr(t, query) 717 require.JSONEq(t, `{"data": {"f":[{"a":76.000000,"age":38},{"a":30.000000,"age":15},{"a":38.000000,"age":19}]}}`, js) 718 } 719 720 func TestMathVarAlias2(t *testing.T) { 721 722 query := ` 723 { 724 f as me(func: anyofterms(name, "Rick Michonne Andrea")) { 725 ageVar as age 726 doubleAge: a as math(ageVar *2) 727 } 728 729 me2(func: uid(f)) { 730 val(a) 731 } 732 } 733 ` 734 js := processQueryNoErr(t, query) 735 require.JSONEq(t, `{"data": {"me":[{"age":38,"doubleAge":76.000000},{"age":15,"doubleAge":30.000000},{"age":19,"doubleAge":38.000000}],"me2":[{"val(a)":76.000000},{"val(a)":30.000000},{"val(a)":38.000000}]}}`, js) 736 } 737 738 func TestMathVar3(t *testing.T) { 739 740 query := ` 741 { 742 f as me(func: anyofterms(name, "Rick Michonne Andrea")) { 743 ageVar as age 744 a as math(ageVar *2) 745 } 746 747 me2(func: uid(f)) { 748 val(a) 749 } 750 } 751 ` 752 js := processQueryNoErr(t, query) 753 require.JSONEq(t, `{"data": {"me":[{"age":38,"val(a)":76.000000},{"age":15,"val(a)":30.000000},{"age":19,"val(a)":38.000000}],"me2":[{"val(a)":76.000000},{"val(a)":30.000000},{"val(a)":38.000000}]}}`, js) 754 } 755 756 func TestMultipleEquality(t *testing.T) { 757 758 query := ` 759 { 760 me(func: eq(name, ["Rick Grimes"])) { 761 name 762 friend { 763 name 764 } 765 } 766 } 767 768 769 ` 770 js := processQueryNoErr(t, query) 771 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Michonne"}],"name":"Rick Grimes"}]}}`, js) 772 } 773 774 func TestMultipleEquality2(t *testing.T) { 775 776 query := ` 777 { 778 me(func: eq(name, ["Badger", "Bobby", "Matt"])) { 779 name 780 friend { 781 name 782 } 783 } 784 } 785 786 ` 787 js := processQueryNoErr(t, query) 788 require.JSONEq(t, `{"data": {"me":[{"name":"Matt"},{"name":"Badger"}]}}`, js) 789 } 790 791 func TestMultipleEquality3(t *testing.T) { 792 793 query := ` 794 { 795 me(func: eq(dob, ["1910-01-01", "1909-05-05"])) { 796 name 797 friend { 798 name 799 } 800 } 801 } 802 803 ` 804 js := processQueryNoErr(t, query) 805 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"name":"Michonne"},{"name":"Glenn Rhee"}]}}`, js) 806 } 807 808 func TestMultipleEquality4(t *testing.T) { 809 810 query := ` 811 { 812 me(func: eq(dob, ["1910-01-01", "1909-05-05"])) { 813 name 814 friend @filter(eq(name, ["Rick Grimes", "Andrea"])) { 815 name 816 } 817 } 818 } 819 820 ` 821 js := processQueryNoErr(t, query) 822 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Andrea"}],"name":"Michonne"},{"name":"Glenn Rhee"}]}}`, js) 823 } 824 825 func TestMultipleEquality5(t *testing.T) { 826 827 query := ` 828 { 829 me(func: eq(name@en, ["Honey badger", "Honey bee"])) { 830 name@en 831 } 832 } 833 834 ` 835 js := processQueryNoErr(t, query) 836 require.JSONEq(t, `{"data": {"me":[{"name@en":"Honey badger"},{"name@en":"Honey bee"}]}}`, js) 837 } 838 839 func TestMultipleGtError(t *testing.T) { 840 841 query := ` 842 { 843 me(func: gt(name, ["Badger", "Bobby"])) { 844 name 845 friend { 846 name 847 } 848 } 849 } 850 851 ` 852 _, err := processQuery(context.Background(), t, query) 853 require.Error(t, err) 854 } 855 856 func TestMultipleEqQuote(t *testing.T) { 857 858 query := ` 859 { 860 me(func: eq(name, ["Alice\"", "Michonne"])) { 861 name 862 friend { 863 name 864 } 865 } 866 } 867 ` 868 js := processQueryNoErr(t, query) 869 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"name":"Michonne"},{"name":"Alice\""}]}}`, js) 870 } 871 872 func TestMultipleEqInt(t *testing.T) { 873 874 query := ` 875 { 876 me(func: eq(age, [15, 17, 38])) { 877 name 878 friend { 879 name 880 } 881 } 882 } 883 ` 884 js := processQueryNoErr(t, query) 885 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]},{"name":"Rick Grimes","friend":[{"name":"Michonne"}]},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"}]}}`, js) 886 } 887 888 func TestUidFunction(t *testing.T) { 889 890 query := ` 891 { 892 me(func: uid(23, 1, 24, 25, 31)) { 893 name 894 } 895 }` 896 js := processQueryNoErr(t, query) 897 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"},{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`, js) 898 } 899 900 func TestUidFunctionInFilter(t *testing.T) { 901 902 query := ` 903 { 904 me(func: uid(23, 1, 24, 25, 31)) @filter(uid(1, 24)) { 905 name 906 } 907 }` 908 js := processQueryNoErr(t, query) 909 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"},{"name":"Glenn Rhee"}]}}`, js) 910 } 911 912 func TestUidFunctionInFilter2(t *testing.T) { 913 914 query := ` 915 { 916 me(func: uid(23, 1, 24, 25, 31)) { 917 name 918 # Filtering only Michonne and Rick. 919 friend @filter(uid(23, 1)) { 920 name 921 } 922 } 923 }` 924 js := processQueryNoErr(t, query) 925 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","friend":[{"name":"Rick Grimes"}]},{"name":"Rick Grimes","friend":[{"name":"Michonne"}]},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`, js) 926 } 927 928 func TestUidFunctionInFilter3(t *testing.T) { 929 930 query := ` 931 { 932 me(func: anyofterms(name, "Michonne Andrea")) @filter(uid(1)) { 933 name 934 } 935 }` 936 js := processQueryNoErr(t, query) 937 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"}]}}`, js) 938 } 939 940 func TestUidFunctionInFilter4(t *testing.T) { 941 942 query := ` 943 { 944 me(func: anyofterms(name, "Michonne Andrea")) @filter(not uid(1, 31)) { 945 name 946 } 947 }` 948 js := processQueryNoErr(t, query) 949 require.JSONEq(t, `{"data": {"me":[{"name":"Andrea With no friends"}]}}`, js) 950 } 951 952 func TestUidInFunction(t *testing.T) { 953 954 query := ` 955 { 956 me(func: uid(1, 23, 24)) @filter(uid_in(friend, 23)) { 957 name 958 } 959 }` 960 js := processQueryNoErr(t, query) 961 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"}]}}`, js) 962 } 963 964 func TestUidInFunction1(t *testing.T) { 965 966 query := ` 967 { 968 me(func: UID(1, 23, 24)) @filter(uid_in(school, 5000)) { 969 name 970 } 971 }` 972 js := processQueryNoErr(t, query) 973 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"},{"name":"Glenn Rhee"}]}}`, js) 974 } 975 976 func TestUidInFunction2(t *testing.T) { 977 978 query := ` 979 { 980 me(func: uid(1, 23, 24)) { 981 friend @filter(uid_in(school, 5000)) { 982 name 983 } 984 } 985 }` 986 js := processQueryNoErr(t, query) 987 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Glenn Rhee"},{"name":"Daryl Dixon"}]},{"friend":[{"name":"Michonne"}]}]}}`, 988 js) 989 } 990 991 func TestUidInFunctionAtRoot(t *testing.T) { 992 993 query := ` 994 { 995 me(func: uid_in(school, 5000)) { 996 name 997 } 998 }` 999 1000 _, err := processQuery(context.Background(), t, query) 1001 require.Error(t, err) 1002 } 1003 1004 func TestBinaryJSON(t *testing.T) { 1005 query := ` 1006 { 1007 me(func: uid(1)) { 1008 name 1009 bin_data 1010 } 1011 }` 1012 js := processQueryNoErr(t, query) 1013 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","bin_data":"YmluLWRhdGE="}]}}`, js) 1014 } 1015 1016 func TestReflexive(t *testing.T) { 1017 1018 query := ` 1019 { 1020 me(func:anyofterms(name, "Michonne Rick Daryl")) @ignoreReflex { 1021 name 1022 friend { 1023 name 1024 friend { 1025 name 1026 } 1027 } 1028 } 1029 }` 1030 js := processQueryNoErr(t, query) 1031 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"friend":[{"name":"Glenn Rhee"}],"name":"Andrea"}],"name":"Michonne"},{"friend":[{"friend":[{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"name":"Michonne"}],"name":"Rick Grimes"},{"name":"Daryl Dixon"}]}}`, js) 1032 } 1033 1034 func TestReflexive2(t *testing.T) { 1035 1036 query := ` 1037 { 1038 me(func:anyofterms(name, "Michonne Rick Daryl")) @IGNOREREFLEX { 1039 name 1040 friend { 1041 name 1042 friend { 1043 name 1044 } 1045 } 1046 } 1047 }` 1048 js := processQueryNoErr(t, query) 1049 require.JSONEq(t, `{"data": {"me":[{"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"friend":[{"name":"Glenn Rhee"}],"name":"Andrea"}],"name":"Michonne"},{"friend":[{"friend":[{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"name":"Michonne"}],"name":"Rick Grimes"},{"name":"Daryl Dixon"}]}}`, js) 1050 } 1051 1052 func TestReflexive3(t *testing.T) { 1053 1054 query := ` 1055 { 1056 me(func:anyofterms(name, "Michonne Rick Daryl")) @IGNOREREFLEX @normalize { 1057 Me: name 1058 friend { 1059 Friend: name 1060 friend { 1061 Cofriend: name 1062 } 1063 } 1064 } 1065 }` 1066 js := processQueryNoErr(t, query) 1067 require.JSONEq(t, `{"data": {"me":[{"Friend":"Rick Grimes","Me":"Michonne"},{"Friend":"Glenn Rhee","Me":"Michonne"},{"Friend":"Daryl Dixon","Me":"Michonne"},{"Cofriend":"Glenn Rhee","Friend":"Andrea","Me":"Michonne"},{"Cofriend":"Glenn Rhee","Friend":"Michonne","Me":"Rick Grimes"},{"Cofriend":"Daryl Dixon","Friend":"Michonne","Me":"Rick Grimes"},{"Cofriend":"Andrea","Friend":"Michonne","Me":"Rick Grimes"},{"Me":"Daryl Dixon"}]}}`, js) 1068 } 1069 1070 func TestCascadeUid(t *testing.T) { 1071 1072 query := ` 1073 { 1074 me(func: uid(0x01)) @cascade { 1075 name 1076 gender 1077 friend { 1078 uid 1079 name 1080 friend{ 1081 name 1082 dob 1083 age 1084 } 1085 } 1086 } 1087 } 1088 ` 1089 1090 js := processQueryNoErr(t, query) 1091 require.JSONEq(t, `{"data": {"me":[{"friend":[{"uid":"0x17","friend":[{"age":38,"dob":"1910-01-01T00:00:00Z","name":"Michonne"}],"name":"Rick Grimes"},{"uid":"0x1f","friend":[{"age":15,"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"}],"name":"Andrea"}],"gender":"female","name":"Michonne"}]}}`, js) 1092 } 1093 1094 func TestUseVariableBeforeDefinitionError(t *testing.T) { 1095 1096 query := ` 1097 { 1098 me(func: anyofterms(name, "Michonne Daryl Andrea"), orderasc: val(avgAge)) { 1099 name 1100 friend { 1101 x as age 1102 } 1103 avgAge as avg(val(x)) 1104 } 1105 }` 1106 1107 _, err := processQuery(context.Background(), t, query) 1108 require.Contains(t, err.Error(), "Variable: [avgAge] used before definition.") 1109 } 1110 1111 func TestAggregateRoot1(t *testing.T) { 1112 1113 query := ` 1114 { 1115 var(func: anyofterms(name, "Rick Michonne Andrea")) { 1116 a as age 1117 } 1118 1119 me() { 1120 sum(val(a)) 1121 } 1122 } 1123 ` 1124 js := processQueryNoErr(t, query) 1125 require.JSONEq(t, `{"data": {"me":[{"sum(val(a))":72}]}}`, js) 1126 } 1127 1128 func TestAggregateRoot2(t *testing.T) { 1129 1130 query := ` 1131 { 1132 var(func: anyofterms(name, "Rick Michonne Andrea")) { 1133 a as age 1134 } 1135 1136 me() { 1137 avg(val(a)) 1138 min(val(a)) 1139 max(val(a)) 1140 } 1141 } 1142 ` 1143 js := processQueryNoErr(t, query) 1144 require.JSONEq(t, `{"data": {"me":[{"avg(val(a))":24.000000},{"min(val(a))":15},{"max(val(a))":38}]}}`, js) 1145 } 1146 1147 func TestAggregateRoot3(t *testing.T) { 1148 1149 query := ` 1150 { 1151 me1(func: anyofterms(name, "Rick Michonne Andrea")) { 1152 a as age 1153 } 1154 1155 me() { 1156 sum(val(a)) 1157 } 1158 } 1159 ` 1160 js := processQueryNoErr(t, query) 1161 require.JSONEq(t, `{"data": {"me1":[{"age":38},{"age":15},{"age":19}],"me":[{"sum(val(a))":72}]}}`, js) 1162 } 1163 1164 func TestAggregateRoot4(t *testing.T) { 1165 1166 query := ` 1167 { 1168 var(func: anyofterms(name, "Rick Michonne Andrea")) { 1169 a as age 1170 } 1171 1172 me() { 1173 minVal as min(val(a)) 1174 maxVal as max(val(a)) 1175 Sum: math(minVal + maxVal) 1176 } 1177 } 1178 ` 1179 js := processQueryNoErr(t, query) 1180 require.JSONEq(t, `{"data": {"me":[{"min(val(a))":15},{"max(val(a))":38},{"Sum":53.000000}]}}`, js) 1181 } 1182 1183 func TestAggregateRoot5(t *testing.T) { 1184 1185 query := ` 1186 { 1187 var(func: anyofterms(name, "Rick Michonne Andrea")) { 1188 # money edge doesn't exist 1189 m as money 1190 } 1191 1192 me() { 1193 sum(val(m)) 1194 } 1195 } 1196 ` 1197 js := processQueryNoErr(t, query) 1198 require.JSONEq(t, `{"data": {"me":[{"sum(val(m))":0.000000}]}}`, js) 1199 } 1200 1201 func TestAggregateRoot6(t *testing.T) { 1202 query := ` 1203 { 1204 uids as var(func: anyofterms(name, "Rick Michonne Andrea")) 1205 1206 var(func: uid(uids)) @cascade { 1207 reason { 1208 killed_zombies as math(1) 1209 } 1210 zombie_count as sum(val(killed_zombies)) 1211 } 1212 1213 me(func: uid(uids)) { 1214 money: val(zombie_count) 1215 } 1216 } 1217 ` 1218 js := processQueryNoErr(t, query) 1219 require.JSONEq(t, `{"data": {"me":[]}}`, js) 1220 } 1221 1222 func TestAggregateRootError(t *testing.T) { 1223 1224 query := ` 1225 { 1226 var(func: anyofterms(name, "Rick Michonne Andrea")) { 1227 a as age 1228 } 1229 1230 var(func: anyofterms(name, "Rick Michonne")) { 1231 a2 as age 1232 } 1233 1234 me() { 1235 Sum: math(a + a2) 1236 } 1237 } 1238 ` 1239 _, err := processQuery(context.Background(), t, query) 1240 require.Error(t, err) 1241 require.Contains(t, err.Error(), "Only aggregated variables allowed within empty block.") 1242 } 1243 1244 func TestAggregateEmpty1(t *testing.T) { 1245 query := ` 1246 { 1247 var(func: has(number)) { 1248 number as number 1249 } 1250 var() { 1251 highest as max(val(number)) 1252 } 1253 1254 all(func: eq(number, val(highest))) { 1255 uid 1256 number 1257 } 1258 }` 1259 1260 js := processQueryNoErr(t, query) 1261 require.JSONEq(t, `{"data": {"all":[]}}`, js) 1262 } 1263 1264 func TestAggregateEmpty2(t *testing.T) { 1265 query := ` 1266 { 1267 var(func: has(number)) 1268 { 1269 highest_number as number 1270 } 1271 all(func: eq(number, val(highest_number))) 1272 { 1273 uid 1274 } 1275 } 1276 ` 1277 js := processQueryNoErr(t, query) 1278 require.JSONEq(t, `{"data": {"all":[]}}`, js) 1279 } 1280 1281 func TestAggregateEmpty3(t *testing.T) { 1282 query := ` 1283 { 1284 var(func: has(number)) 1285 { 1286 highest_number as number 1287 } 1288 all(func: ge(number, val(highest_number))) 1289 { 1290 uid 1291 } 1292 } 1293 ` 1294 js := processQueryNoErr(t, query) 1295 require.JSONEq(t, `{"data": {"all":[]}}`, js) 1296 } 1297 1298 func TestFilterLang(t *testing.T) { 1299 // This tests the fix for #1334. While getting uids for filter, we fetch data keys when number 1300 // of uids is less than number of tokens. Lang tag was not passed correctly while fetching these 1301 // data keys. 1302 1303 query := ` 1304 { 1305 me(func: uid(0x1001, 0x1002, 0x1003)) @filter(ge(name@en, "D")) { 1306 name@en 1307 } 1308 } 1309 ` 1310 js := processQueryNoErr(t, query) 1311 require.JSONEq(t, 1312 `{"data": {"me":[{"name@en":"European badger"},{"name@en":"Honey badger"},{"name@en":"Honey bee"}]}}`, js) 1313 } 1314 1315 func TestMathCeil1(t *testing.T) { 1316 1317 query := ` 1318 { 1319 me as var(func: eq(name, "XxXUnknownXxX")) 1320 var(func: uid(me)) { 1321 friend { 1322 x as age 1323 } 1324 x2 as sum(val(x)) 1325 c as count(friend) 1326 } 1327 1328 me(func: uid(me)) { 1329 ceilAge: math(ceil(x2/c)) 1330 } 1331 } 1332 ` 1333 js := processQueryNoErr(t, query) 1334 require.JSONEq(t, `{"data": {"me": []}}`, js) 1335 } 1336 1337 func TestMathCeil2(t *testing.T) { 1338 1339 query := ` 1340 { 1341 me as var(func: eq(name, "Michonne")) 1342 var(func: uid(me)) { 1343 friend { 1344 x as age 1345 } 1346 x2 as sum(val(x)) 1347 c as count(friend) 1348 } 1349 1350 me(func: uid(me)) { 1351 ceilAge: math(ceil(x2/c)) 1352 } 1353 } 1354 ` 1355 js := processQueryNoErr(t, query) 1356 require.JSONEq(t, `{"data": {"me":[{"ceilAge":14.000000}]}}`, js) 1357 } 1358 1359 func TestUidAttr(t *testing.T) { 1360 tests := []struct { 1361 in, out, failure string 1362 }{ 1363 {in: `{q(func:ge(uid, 1)) { uid }}`, 1364 failure: `Argument cannot be "uid`}, 1365 {in: `{q(func:eq(uid, 2)) { uid }}`, 1366 failure: `Argument cannot be "uid`}, 1367 {in: `{q(func:lt(uid, 3)) { uid }}`, 1368 failure: `Argument cannot be "uid`}, 1369 {in: `{q(func:has(uid)) { uid }}`, 1370 failure: `Argument cannot be "uid`}, 1371 {in: `{q(func:anyoftext(uid, "")) { uid }}`, 1372 failure: `Argument cannot be "uid`}, 1373 {in: `{q(func:alloftext(uid, "")) { uid }}`, 1374 failure: `Argument cannot be "uid`}, 1375 {in: `{q(func:regexp(uid)) { uid }}`, 1376 failure: `Argument cannot be "uid`}, 1377 {in: `{q(func:match(uid, "", 8)) { uid }}`, 1378 failure: `Argument cannot be "uid`}, 1379 {in: `{q(func:has(name)) @filter(uid_in(uid, 0x1)) { uid }}`, 1380 failure: `Argument cannot be "uid"`}, 1381 {in: `{q(func:uid(0x1)) { checkpwd(uid, "") }}`, 1382 failure: `Argument cannot be "uid"`}, 1383 {in: `{q(func:uid(0x1)) { uid }}`, 1384 out: `{"data":{"q":[{"uid":"0x1"}]}}`}, 1385 {in: `{q(func:eq(name, "uid")) { uid }}`, 1386 out: `{"data":{"q":[]}}`}, 1387 } 1388 for _, tc := range tests { 1389 js, err := processQuery(context.Background(), t, tc.in) 1390 if tc.failure != "" { 1391 require.Error(t, err) 1392 require.Contains(t, err.Error(), tc.failure) 1393 } else { 1394 require.NoError(t, err) 1395 require.JSONEq(t, tc.out, js) 1396 } 1397 } 1398 } 1399 1400 func TestMultipleValueFilter(t *testing.T) { 1401 1402 query := ` 1403 { 1404 me(func: ge(graduation, "1930")) { 1405 name 1406 graduation 1407 } 1408 } 1409 ` 1410 js := processQueryNoErr(t, query) 1411 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","graduation":["1932-01-01T00:00:00Z"]},{"name":"Andrea","graduation":["1935-01-01T00:00:00Z","1933-01-01T00:00:00Z"]}]}}`, js) 1412 } 1413 1414 func TestMultipleValueFilter2(t *testing.T) { 1415 1416 query := ` 1417 { 1418 me(func: le(graduation, "1933")) { 1419 name 1420 graduation 1421 } 1422 } 1423 ` 1424 js := processQueryNoErr(t, query) 1425 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","graduation":["1932-01-01T00:00:00Z"]},{"name":"Andrea","graduation":["1935-01-01T00:00:00Z","1933-01-01T00:00:00Z"]}]}}`, js) 1426 } 1427 1428 func TestMultipleValueArray(t *testing.T) { 1429 1430 query := ` 1431 { 1432 me(func: uid(1)) { 1433 name 1434 graduation 1435 } 1436 } 1437 ` 1438 js := processQueryNoErr(t, query) 1439 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","graduation":["1932-01-01T00:00:00Z"]}]}}`, js) 1440 } 1441 1442 func TestMultipleValueArray2(t *testing.T) { 1443 1444 query := ` 1445 { 1446 me(func: uid(1)) { 1447 graduation 1448 name 1449 } 1450 } 1451 ` 1452 js := processQueryNoErr(t, query) 1453 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","graduation":["1932-01-01T00:00:00Z"]}]}}`, js) 1454 } 1455 1456 func TestMultipleValueHasAndCount(t *testing.T) { 1457 1458 query := ` 1459 { 1460 me(func: has(graduation)) { 1461 name 1462 count(graduation) 1463 graduation 1464 } 1465 } 1466 ` 1467 js := processQueryNoErr(t, query) 1468 require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","count(graduation)":1,"graduation":["1932-01-01T00:00:00Z"]},{"name":"Andrea","count(graduation)":2,"graduation":["1935-01-01T00:00:00Z","1933-01-01T00:00:00Z"]}]}}`, js) 1469 } 1470 1471 func TestMultipleValueSortError(t *testing.T) { 1472 1473 query := ` 1474 { 1475 me(func: anyofterms(name, "Michonne Rick"), orderdesc: graduation) { 1476 name 1477 graduation 1478 } 1479 } 1480 ` 1481 _, err := processQuery(context.Background(), t, query) 1482 require.Error(t, err) 1483 require.Contains(t, err.Error(), "Sorting not supported on attr: graduation of type: [scalar]") 1484 } 1485 1486 func TestMultipleValueGroupByError(t *testing.T) { 1487 t.Skip() 1488 1489 query := ` 1490 { 1491 me(func: uid(1)) { 1492 friend @groupby(name, graduation) { 1493 count(uid) 1494 } 1495 } 1496 } 1497 ` 1498 _, err := processQuery(context.Background(), t, query) 1499 require.Error(t, err) 1500 require.Contains(t, err.Error(), "Groupby not allowed for attr: graduation of type list") 1501 } 1502 1503 func TestMultiPolygonIntersects(t *testing.T) { 1504 1505 usc, err := ioutil.ReadFile("testdata/us-coordinates.txt") 1506 require.NoError(t, err) 1507 query := `{ 1508 me(func: intersects(geometry, "` + strings.TrimSpace(string(usc)) + `" )) { 1509 name 1510 } 1511 } 1512 ` 1513 1514 js := processQueryNoErr(t, query) 1515 require.JSONEq(t, `{"data": {"me":[{"name":"Googleplex"},{"name":"Shoreline Amphitheater"},{"name":"San Carlos Airport"},{"name":"SF Bay area"},{"name":"Mountain View"},{"name":"San Carlos"}, {"name": "New York"}]}}`, js) 1516 } 1517 1518 func TestMultiPolygonWithin(t *testing.T) { 1519 1520 usc, err := ioutil.ReadFile("testdata/us-coordinates.txt") 1521 require.NoError(t, err) 1522 query := `{ 1523 me(func: within(geometry, "` + strings.TrimSpace(string(usc)) + `" )) { 1524 name 1525 } 1526 } 1527 ` 1528 1529 js := processQueryNoErr(t, query) 1530 require.JSONEq(t, `{"data": {"me":[{"name":"Googleplex"},{"name":"Shoreline Amphitheater"},{"name":"San Carlos Airport"},{"name":"Mountain View"},{"name":"San Carlos"}]}}`, js) 1531 } 1532 1533 func TestNearPointMultiPolygon(t *testing.T) { 1534 1535 query := `{ 1536 me(func: near(loc, [1.0, 1.0], 1)) { 1537 name 1538 } 1539 }` 1540 1541 js := processQueryNoErr(t, query) 1542 require.JSONEq(t, `{"data": {"me":[{"name":"Rick Grimes"}]}}`, js) 1543 } 1544 1545 func TestMultiSort1(t *testing.T) { 1546 1547 time.Sleep(10 * time.Millisecond) 1548 1549 query := `{ 1550 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: age) { 1551 name 1552 age 1553 } 1554 }` 1555 1556 js := processQueryNoErr(t, query) 1557 require.JSONEq(t, `{"data": {"me":[{"name":"Alice","age":25},{"name":"Alice","age":75},{"name":"Alice","age":75},{"name":"Bob","age":25},{"name":"Bob","age":75},{"name":"Colin","age":25},{"name":"Elizabeth","age":25},{"name":"Elizabeth","age":75}]}}`, js) 1558 } 1559 1560 func TestMultiSort2(t *testing.T) { 1561 1562 query := `{ 1563 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderdesc: age) { 1564 name 1565 age 1566 } 1567 }` 1568 1569 js := processQueryNoErr(t, query) 1570 require.JSONEq(t, `{"data": {"me":[{"name":"Alice","age":75},{"name":"Alice","age":75},{"name":"Alice","age":25},{"name":"Bob","age":75},{"name":"Bob","age":25},{"name":"Colin","age":25},{"name":"Elizabeth","age":75},{"name":"Elizabeth","age":25}]}}`, js) 1571 } 1572 1573 func TestMultiSort3(t *testing.T) { 1574 1575 query := `{ 1576 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: age, orderdesc: name) { 1577 name 1578 age 1579 } 1580 }` 1581 1582 js := processQueryNoErr(t, query) 1583 require.JSONEq(t, `{"data": {"me":[{"name":"Elizabeth","age":25},{"name":"Colin","age":25},{"name":"Bob","age":25},{"name":"Alice","age":25},{"name":"Elizabeth","age":75},{"name":"Bob","age":75},{"name":"Alice","age":75},{"name":"Alice","age":75}]}}`, js) 1584 } 1585 1586 func TestMultiSort4(t *testing.T) { 1587 1588 query := `{ 1589 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: salary) { 1590 name 1591 age 1592 salary 1593 } 1594 }` 1595 js := processQueryNoErr(t, query) 1596 // Null value for third Alice comes at last. 1597 require.JSONEq(t, `{"data": {"me":[{"name":"Alice","age":25,"salary":10000.000000},{"name":"Alice","age":75,"salary":10002.000000},{"name":"Alice","age":75},{"name":"Bob","age":75},{"name":"Bob","age":25},{"name":"Colin","age":25},{"name":"Elizabeth","age":75},{"name":"Elizabeth","age":25}]}}`, js) 1598 } 1599 1600 func TestMultiSort5(t *testing.T) { 1601 1602 query := `{ 1603 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderdesc: salary) { 1604 name 1605 age 1606 salary 1607 } 1608 }` 1609 js := processQueryNoErr(t, query) 1610 // Null value for third Alice comes at first. 1611 require.JSONEq(t, `{"data": {"me":[{"name":"Alice","age":75},{"name":"Alice","age":75,"salary":10002.000000},{"name":"Alice","age":25,"salary":10000.000000},{"name":"Bob","age":25},{"name":"Bob","age":75},{"name":"Colin","age":25},{"name":"Elizabeth","age":25},{"name":"Elizabeth","age":75}]}}`, js) 1612 } 1613 1614 func TestMultiSort6Paginate(t *testing.T) { 1615 1616 query := `{ 1617 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderdesc: age, first: 7) { 1618 name 1619 age 1620 } 1621 }` 1622 1623 js := processQueryNoErr(t, query) 1624 require.JSONEq(t, `{"data": {"me":[{"name":"Alice","age":75},{"name":"Alice","age":75},{"name":"Alice","age":25},{"name":"Bob","age":75},{"name":"Bob","age":25},{"name":"Colin","age":25},{"name":"Elizabeth","age":75}]}}`, js) 1625 } 1626 1627 func TestMultiSort7Paginate(t *testing.T) { 1628 1629 query := `{ 1630 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: age, first: 7) { 1631 name 1632 age 1633 } 1634 }` 1635 1636 js := processQueryNoErr(t, query) 1637 require.JSONEq(t, `{"data": {"me":[{"name":"Alice","age":25},{"name":"Alice","age":75},{"name":"Alice","age":75},{"name":"Bob","age":25},{"name":"Bob","age":75},{"name":"Colin","age":25},{"name":"Elizabeth","age":25}]}}`, js) 1638 } 1639 1640 func TestMultiSortPaginateWithOffset(t *testing.T) { 1641 t.Parallel() 1642 tests := []struct { 1643 name string 1644 query string 1645 result string 1646 }{ 1647 { 1648 "Offset in middle of bucket", 1649 `{ 1650 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: age, first: 6, offset: 1) { 1651 name 1652 age 1653 } 1654 }`, 1655 `{"data": {"me":[{"name":"Alice","age":75},{"name":"Alice","age":75},{"name":"Bob","age":25},{"name":"Bob","age":75},{"name":"Colin","age":25},{"name":"Elizabeth","age":25}]}}`, 1656 }, 1657 { 1658 "Offset at boundary of bucket", 1659 `{ 1660 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: age, first: 4, offset: 3) { 1661 name 1662 age 1663 } 1664 }`, 1665 `{"data": {"me":[{"name":"Bob","age":25},{"name":"Bob","age":75},{"name":"Colin","age":25},{"name":"Elizabeth","age":25}]}}`, 1666 }, 1667 { 1668 "Offset in middle of second bucket", 1669 `{ 1670 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: age, first: 3, offset: 4) { 1671 name 1672 age 1673 } 1674 }`, 1675 `{"data": {"me":[{"name":"Bob","age":75},{"name":"Colin","age":25},{"name":"Elizabeth","age":25}]}}`, 1676 }, 1677 { 1678 "Offset equal to number of uids", 1679 `{ 1680 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: age, first: 3, offset: 8) { 1681 name 1682 age 1683 } 1684 }`, 1685 `{"data": {"me":[]}}`, 1686 }, 1687 { 1688 "Offset larger than records", 1689 `{ 1690 me(func: uid(10005, 10006, 10001, 10002, 10003, 10004, 10007, 10000), orderasc: name, orderasc: age, first: 10, offset: 10000) { 1691 name 1692 age 1693 } 1694 }`, 1695 `{"data": {"me":[]}}`, 1696 }, 1697 } 1698 1699 for _, tt := range tests { 1700 t.Run(tt.name, func(t *testing.T) { 1701 js := processQueryNoErr(t, tt.query) 1702 require.JSONEq(t, tt.result, js) 1703 }) 1704 } 1705 } 1706 1707 func TestFilterRootOverride(t *testing.T) { 1708 1709 query := `{ 1710 a as var(func: eq(name, "Michonne")) @filter(eq(name, "Rick Grimes")) 1711 1712 me(func: uid(a)) { 1713 uid 1714 name 1715 } 1716 } 1717 ` 1718 js := processQueryNoErr(t, query) 1719 require.JSONEq(t, `{"data": {"me": []}}`, js) 1720 } 1721 1722 func TestFilterRoot(t *testing.T) { 1723 1724 query := `{ 1725 me(func: eq(name, "Michonne")) @filter(eq(name, "Rick Grimes")) { 1726 uid 1727 name 1728 } 1729 } 1730 ` 1731 js := processQueryNoErr(t, query) 1732 require.JSONEq(t, `{"data": {"me": []}}`, js) 1733 } 1734 1735 func TestMathAlias(t *testing.T) { 1736 1737 query := `{ 1738 me(func:allofterms(name, "Michonne")) { 1739 p as count(friend) 1740 score: math(p + 1) 1741 name 1742 } 1743 }` 1744 1745 js := processQueryNoErr(t, query) 1746 require.JSONEq(t, `{"data": {"me":[{"count(friend)":5,"score":6.000000,"name":"Michonne"}]}}`, js) 1747 } 1748 1749 func TestUidVariable(t *testing.T) { 1750 1751 query := `{ 1752 var(func:allofterms(name, "Michonne")) { 1753 friend { 1754 f as uid 1755 } 1756 } 1757 1758 me(func: uid(f)) { 1759 name 1760 } 1761 }` 1762 1763 js := processQueryNoErr(t, query) 1764 require.JSONEq(t, `{"data": {"me":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`, js) 1765 } 1766 1767 func TestMultipleValueVarError(t *testing.T) { 1768 1769 query := `{ 1770 var(func:ge(graduation, "1930")) { 1771 o as graduation 1772 } 1773 1774 me(func: uid(o)) { 1775 graduation 1776 } 1777 }` 1778 1779 _, err := processQuery(context.Background(), t, query) 1780 require.Error(t, err) 1781 require.Contains(t, err.Error(), "Value variables not supported for predicate with list type.") 1782 } 1783 1784 func TestReturnEmptyBlock(t *testing.T) { 1785 1786 query := `{ 1787 me(func:allofterms(name, "Michonne")) @filter(eq(name, "Rick Grimes")) { 1788 } 1789 1790 me2(func: eq(name, "XYZ")) 1791 1792 me3(func: eq(name, "Michonne")) { 1793 name 1794 } 1795 }` 1796 1797 js := processQueryNoErr(t, query) 1798 require.JSONEq(t, `{"data": {"me":[],"me2":[],"me3":[{"name":"Michonne"}]}}`, js) 1799 } 1800 1801 func TestExpandVal(t *testing.T) { 1802 query := ` 1803 { 1804 var(func: uid(11)) { 1805 pred as name 1806 } 1807 1808 me(func: uid(11)) { 1809 expand(val(pred)) 1810 } 1811 } 1812 ` 1813 js := processQueryNoErr(t, query) 1814 require.JSONEq(t, 1815 `{"data":{"me":[{"name":"name"}]}}`, js) 1816 } 1817 1818 func TestGroupByGeoCrash(t *testing.T) { 1819 1820 query := ` 1821 { 1822 q(func: uid(1, 23, 24, 25, 31)) @groupby(loc) { 1823 count(uid) 1824 } 1825 } 1826 ` 1827 js := processQueryNoErr(t, query) 1828 require.Contains(t, js, `{"loc":{"type":"Point","coordinates":[1.1,2]},"count":2}`) 1829 } 1830 1831 func TestPasswordError(t *testing.T) { 1832 1833 query := ` 1834 { 1835 q(func: uid(1)) { 1836 checkpwd(name, "Michonne") 1837 } 1838 } 1839 ` 1840 _, err := processQuery(context.Background(), t, query) 1841 require.Error(t, err) 1842 require.Contains(t, 1843 err.Error(), "checkpwd fn can only be used on attr: [name] with schema type password. Got type: string") 1844 } 1845 1846 func TestCountPanic(t *testing.T) { 1847 1848 query := ` 1849 { 1850 q(func: uid(1, 300)) { 1851 uid 1852 name 1853 count(name) 1854 } 1855 } 1856 ` 1857 js := processQueryNoErr(t, query) 1858 require.JSONEq(t, `{"data": {"q":[{"uid":"0x1","name":"Michonne","count(name)":1},{"uid":"0x12c","count(name)":0}]}}`, js) 1859 } 1860 1861 func TestUidWithoutDebug(t *testing.T) { 1862 1863 query := ` 1864 { 1865 q(func: uid(1, 24)) { 1866 uid 1867 friend 1868 } 1869 } 1870 ` 1871 js := processQueryNoErr(t, query) 1872 require.JSONEq(t, `{"data":{"q":[{"uid":"0x1"},{"uid":"0x18"}]}}`, js) 1873 } 1874 1875 func TestUidWithoutDebug2(t *testing.T) { 1876 1877 query := ` 1878 { 1879 q(func: uid(1)) { 1880 uid 1881 friend { 1882 uid 1883 } 1884 } 1885 } 1886 ` 1887 js := processQueryNoErr(t, query) 1888 require.JSONEq(t, `{"data":{"q":[{"uid":"0x1","friend":[{"uid":"0x17"},{"uid":"0x18"},{"uid":"0x19"},{"uid":"0x1f"},{"uid":"0x65"}]}]}}`, js) 1889 } 1890 1891 func TestExpandAll_empty_panic(t *testing.T) { 1892 1893 query := ` 1894 { 1895 me(func: uid(0x01)) @filter(eq(name,"foobar")){ 1896 expand(_all_) 1897 } 1898 } 1899 ` 1900 js := processQueryNoErr(t, query) 1901 require.JSONEq(t, `{"data":{"me":[]}}`, js) 1902 }