github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/gql/parser_test.go (about) 1 /* 2 * Copyright 2015-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 gql 18 19 import ( 20 "bytes" 21 "os" 22 "runtime/debug" 23 "testing" 24 25 "github.com/dgraph-io/dgo/protos/api" 26 "github.com/dgraph-io/dgraph/chunker" 27 "github.com/dgraph-io/dgraph/lex" 28 "github.com/stretchr/testify/require" 29 ) 30 31 func childAttrs(g *GraphQuery) []string { 32 var out []string 33 for _, c := range g.Children { 34 out = append(out, c.Attr) 35 } 36 return out 37 } 38 39 func TestParseCountValError(t *testing.T) { 40 query := ` 41 { 42 me(func: uid(1)) { 43 Upvote { 44 u as Author 45 } 46 count(val(u)) 47 } 48 } 49 ` 50 _, err := Parse(Request{Str: query}) 51 require.Error(t, err) 52 require.Contains(t, err.Error(), "Count of a variable is not allowed") 53 } 54 55 func TestParseVarError(t *testing.T) { 56 query := ` 57 { 58 var(func: uid(0x0a)) { 59 a as friends 60 } 61 62 me(func: uid(a)) { 63 uid(a) 64 } 65 } 66 ` 67 _, err := Parse(Request{Str: query}) 68 require.Error(t, err) 69 require.Contains(t, err.Error(), "Cannot do uid() of a variable") 70 } 71 72 func TestDuplicateQueryAliasesError(t *testing.T) { 73 query := ` 74 { 75 find_michael(func: eq(name@., "Michael")) { 76 uid 77 name@. 78 age 79 } 80 find_michael(func: eq(name@., "Amit")) { 81 uid 82 name@. 83 } 84 }` 85 _, err := Parse(Request{Str: query}) 86 require.Error(t, err) 87 88 queryInOpType := ` 89 { 90 find_michael(func: eq(name@., "Michael")) { 91 uid 92 name@. 93 age 94 } 95 } 96 query {find_michael(func: eq(name@., "Amit")) { 97 uid 98 name@. 99 } 100 } 101 ` 102 _, err = Parse(Request{Str: queryInOpType}) 103 require.Error(t, err) 104 105 queryWithDuplicateShortestPaths := ` 106 { 107 path as shortest(from: 0x1, to: 0x4) { 108 friend 109 } 110 path2 as shortest(from: 0x2, to: 0x3) { 111 friend 112 } 113 pathQuery1(func: uid(path)) { 114 name 115 } 116 pathQuery2(func: uid(path2)) { 117 name 118 } 119 120 }` 121 _, err = Parse(Request{Str: queryWithDuplicateShortestPaths}) 122 require.NoError(t, err) 123 } 124 125 func TestParseQueryListPred1(t *testing.T) { 126 query := ` 127 { 128 var(func: uid( 0x0a)) { 129 friends { 130 expand(_all_) 131 } 132 } 133 } 134 ` 135 _, err := Parse(Request{Str: query}) 136 require.NoError(t, err) 137 } 138 139 func TestParseQueryExpandForward(t *testing.T) { 140 query := ` 141 { 142 var(func: uid( 0x0a)) { 143 friends { 144 expand(_forward_) 145 } 146 } 147 } 148 ` 149 _, err := Parse(Request{Str: query}) 150 require.NoError(t, err) 151 } 152 153 func TestParseQueryExpandReverse(t *testing.T) { 154 query := ` 155 { 156 var(func: uid( 0x0a)) { 157 friends { 158 expand(_reverse_) 159 } 160 } 161 } 162 ` 163 _, err := Parse(Request{Str: query}) 164 require.NoError(t, err) 165 } 166 167 func TestParseQueryAliasListPred(t *testing.T) { 168 query := ` 169 { 170 me(func: uid(0x0a)) { 171 pred: some_pred 172 } 173 } 174 ` 175 res, err := Parse(Request{Str: query}) 176 require.NoError(t, err) 177 require.Equal(t, "pred", res.Query[0].Children[0].Alias) 178 require.Equal(t, "some_pred", res.Query[0].Children[0].Attr) 179 } 180 181 func TestParseQueryCountListPred(t *testing.T) { 182 query := ` 183 { 184 me(func: uid(0x0a)) { 185 count(some_pred) 186 } 187 } 188 ` 189 res, err := Parse(Request{Str: query}) 190 require.NoError(t, err) 191 require.Equal(t, true, res.Query[0].Children[0].IsCount) 192 require.Equal(t, "some_pred", res.Query[0].Children[0].Attr) 193 } 194 195 func TestParseQueryListPred2(t *testing.T) { 196 query := ` 197 { 198 var(func: uid(0x0a)) { 199 f as friends 200 } 201 202 var(func: uid(f)) { 203 l as some_pred 204 } 205 206 var(func: uid( 0x0a)) { 207 friends { 208 expand(val(l)) 209 } 210 } 211 } 212 ` 213 _, err := Parse(Request{Str: query}) 214 require.NoError(t, err) 215 } 216 217 func TestParseQueryListPred_MultiVarError(t *testing.T) { 218 query := ` 219 { 220 var(func: uid(0x0a)) { 221 f as friends 222 } 223 224 var(func: uid(f)) { 225 l as some_pred 226 friend { 227 g as some_pred 228 } 229 } 230 231 var(func: uid( 0x0a)) { 232 friends { 233 expand(val(l, g)) 234 } 235 } 236 } 237 ` 238 _, err := Parse(Request{Str: query}) 239 // Only one variable allowed in expand. 240 require.Error(t, err) 241 require.Contains(t, err.Error(), "Exactly one variable expected") 242 } 243 244 func TestParseQueryWithNoVarValError(t *testing.T) { 245 query := ` 246 { 247 me(func: uid(), orderasc: val(n)) { 248 name 249 } 250 251 var(func: uid(0x0a)) { 252 friends { 253 n AS name 254 } 255 } 256 } 257 ` 258 _, err := Parse(Request{Str: query}) 259 require.NoError(t, err) 260 } 261 262 func TestParseQueryAggChild(t *testing.T) { 263 query := ` 264 { 265 var(func: uid(0x0a)) { 266 min(friends) { 267 name 268 } 269 } 270 } 271 ` 272 _, err := Parse(Request{Str: query}) 273 require.Error(t, err) 274 require.Contains(t, err.Error(), "Only variables allowed in aggregate functions") 275 } 276 277 func TestParseQueryWithXIDError(t *testing.T) { 278 query := ` 279 { 280 me(func: uid(aliceInWonderland)) { 281 type 282 writtenIn 283 name 284 character { 285 name 286 } 287 author { 288 name 289 born 290 died 291 } 292 } 293 }` 294 _, err := Parse(Request{Str: query}) 295 require.Error(t, err) 296 require.Contains(t, err.Error(), "Some variables are used but not defined") 297 require.Contains(t, err.Error(), "Used:[aliceInWonderland]") 298 } 299 300 func TestParseQueryWithMultiVarValError(t *testing.T) { 301 query := ` 302 { 303 me(func: uid(L), orderasc: val(n, d)) { 304 name 305 } 306 307 var(func: uid(0x0a)) { 308 L AS friends { 309 n AS name 310 d as age 311 } 312 } 313 } 314 ` 315 _, err := Parse(Request{Str: query}) 316 require.Error(t, err) 317 require.Contains(t, err.Error(), "Expected only one variable but got: 2") 318 } 319 320 func TestParseQueryWithVarValAggErr(t *testing.T) { 321 query := ` 322 { 323 me(func: uid(L), orderasc: val(c)) { 324 name 325 } 326 327 var(func: uid(0x0a)) { 328 L as friends { 329 a as age 330 c as sumvar() 331 } 332 } 333 } 334 ` 335 _, err := Parse(Request{Str: query}) 336 require.Error(t, err) 337 require.Contains(t, err.Error(), "Expected argument but got ')'") 338 } 339 340 func TestParseQueryWithVarValAgg_Error1(t *testing.T) { 341 query := ` 342 { 343 me(func: uid(L), orderasc: val(d)) { 344 name 345 } 346 347 var(func: uid(0x0a)) { 348 L as friends { 349 a as age 350 b as count(friends) 351 c as count(relatives) 352 d as math(a + b*c + exp()) 353 } 354 } 355 } 356 ` 357 _, err := Parse(Request{Str: query}) 358 require.Error(t, err) 359 require.Contains(t, err.Error(), "Empty () not allowed in math block") 360 } 361 362 func TestParseQueryWithVarValAgg_Error2(t *testing.T) { 363 query := ` 364 { 365 me(func: uid(L), orderasc: val(d)) { 366 name 367 } 368 369 var(func: uid(0x0a)) { 370 L as friends { 371 a as age 372 b as count(friends) 373 c as count(relatives) 374 d as math(a + b*c+ log()) 375 } 376 } 377 } 378 ` 379 _, err := Parse(Request{Str: query}) 380 require.Error(t, err) 381 require.Contains(t, err.Error(), "Unknown math function: log") 382 } 383 384 func TestParseQueryWithVarValAgg_Error3(t *testing.T) { 385 query := ` 386 { 387 me(func: uid(L), orderasc: val(d)) { 388 name 389 val(f) 390 } 391 392 var(func: uid(0x0a)) { 393 L as friends { 394 a as age 395 b as count(friends) 396 c as count(relatives) 397 d as math(a + b*c) 398 f as math() 399 } 400 } 401 } 402 ` 403 _, err := Parse(Request{Str: query}) 404 require.Error(t, err) 405 require.Contains(t, err.Error(), "Empty () not allowed in math block") 406 } 407 func TestParseQueryWithVarValAggNested(t *testing.T) { 408 query := ` 409 { 410 me(func: uid(L), orderasc: val(d)) { 411 name 412 } 413 414 var(func: uid(0x0a)) { 415 L as friends { 416 a as age 417 b as count(friends) 418 c as count(relatives) 419 d as math(a + b*c) 420 } 421 } 422 } 423 ` 424 res, err := Parse(Request{Str: query}) 425 require.EqualValues(t, "(+ a (* b c))", 426 res.Query[1].Children[0].Children[3].MathExp.debugString()) 427 require.NoError(t, err) 428 } 429 430 func TestParseQueryWithVarValAggNested2(t *testing.T) { 431 query := ` 432 { 433 me(func: uid(L), orderasc: val(d)) { 434 name 435 val(q) 436 } 437 438 var(func: uid(0x0a)) { 439 L as friends { 440 a as age 441 b as count(friends) 442 c as count(relatives) 443 d as math(exp(a + b + 1) - ln(c)) 444 q as math(c*-1+-b+(-b*c)) 445 } 446 } 447 } 448 ` 449 res, err := Parse(Request{Str: query}) 450 require.NoError(t, err) 451 require.EqualValues(t, "(- (exp (+ (+ a b) 1E+00)) (ln c))", 452 res.Query[1].Children[0].Children[3].MathExp.debugString()) 453 require.EqualValues(t, "(+ (+ (* c (u- 1E+00)) (u- b)) (* (u- b) c))", 454 res.Query[1].Children[0].Children[4].MathExp.debugString()) 455 } 456 457 func TestParseQueryWithVarValAggNested4(t *testing.T) { 458 query := ` 459 { 460 me(func: uid(L), orderasc: val(d) ) { 461 name 462 } 463 464 var(func: uid(0x0a)) { 465 L as friends { 466 a as age 467 b as count(friends) 468 c as count(relatives) 469 d as math(exp(a + b + 1) - max(c,ln(c)) + sqrt(a%b)) 470 } 471 } 472 } 473 ` 474 res, err := Parse(Request{Str: query}) 475 require.NoError(t, err) 476 require.EqualValues(t, "(+ (- (exp (+ (+ a b) 1E+00)) (max c (ln c))) (sqrt (% a b)))", 477 res.Query[1].Children[0].Children[3].MathExp.debugString()) 478 } 479 480 func TestParseQueryWithVarValAggLogSqrt(t *testing.T) { 481 query := ` 482 { 483 me(func: uid(L), orderasc: val(d) ) { 484 name 485 val(e) 486 } 487 488 var(func: uid(0x0a)) { 489 L as friends { 490 a as age 491 d as math(ln(sqrt(a))) 492 e as math(sqrt(ln(a))) 493 } 494 } 495 } 496 ` 497 res, err := Parse(Request{Str: query}) 498 require.NoError(t, err) 499 require.EqualValues(t, "(ln (sqrt a))", 500 res.Query[1].Children[0].Children[1].MathExp.debugString()) 501 require.EqualValues(t, "(sqrt (ln a))", 502 res.Query[1].Children[0].Children[2].MathExp.debugString()) 503 } 504 505 func TestParseQueryWithVarValAggNestedConditional(t *testing.T) { 506 query := ` 507 { 508 me(func: uid(L), orderasc: val(d) ) { 509 name 510 val(f) 511 } 512 513 var(func: uid(0x0a)) { 514 L as friends { 515 a as age 516 b as count(friends) 517 c as count(relatives) 518 d as math(cond(a <= 10, exp(a + b + 1), ln(c)) + 10*a) 519 e as math(cond(a!=10, exp(a + b + 1), ln(d))) 520 f as math(cond(a==10, exp(a + b + 1), ln(e))) 521 } 522 } 523 } 524 ` 525 res, err := Parse(Request{Str: query}) 526 require.NoError(t, err) 527 require.EqualValues(t, "(+ (cond (<= a 1E+01) (exp (+ (+ a b) 1E+00)) (ln c)) (* 1E+01 a))", 528 res.Query[1].Children[0].Children[3].MathExp.debugString()) 529 require.EqualValues(t, "(cond (!= a 1E+01) (exp (+ (+ a b) 1E+00)) (ln d))", 530 res.Query[1].Children[0].Children[4].MathExp.debugString()) 531 require.EqualValues(t, "(cond (== a 1E+01) (exp (+ (+ a b) 1E+00)) (ln e))", 532 res.Query[1].Children[0].Children[5].MathExp.debugString()) 533 } 534 535 func TestParseQueryWithVarValAggNested3(t *testing.T) { 536 query := ` 537 { 538 me(func: uid(L), orderasc: val(d) ) { 539 name 540 } 541 542 var(func: uid(0x0a)) { 543 L as friends { 544 a as age 545 b as count(friends) 546 c as count(relatives) 547 d as math(a + b * c / a + exp(a + b + 1) - ln(c)) 548 } 549 } 550 } 551 ` 552 res, err := Parse(Request{Str: query}) 553 require.NoError(t, err) 554 require.EqualValues(t, "(+ (+ a (* b (/ c a))) (- (exp (+ (+ a b) 1E+00)) (ln c)))", 555 res.Query[1].Children[0].Children[3].MathExp.debugString()) 556 } 557 558 func TestParseQueryWithVarValAggNested_Error1(t *testing.T) { 559 // No args to mulvar. 560 query := ` 561 { 562 me(func: uid(L), orderasc: val(d)) { 563 name 564 } 565 566 var(func: uid(0x0a)) { 567 L as friends { 568 a as age 569 d as math(a + *) 570 } 571 } 572 } 573 ` 574 _, err := Parse(Request{Str: query}) 575 require.Error(t, err) 576 require.Contains(t, err.Error(), "Expected 2 operands") 577 } 578 579 func TestParseQueryWithVarValAggNested_Error2(t *testing.T) { 580 query := ` 581 { 582 me(func: uid(L), orderasc: val(d)) { 583 name 584 } 585 586 var(func: uid(0x0a)) { 587 L as friends { 588 a as age 589 b as count(friends) 590 c as count(relatives) 591 d as math(a +b*c -) 592 } 593 } 594 } 595 ` 596 _, err := Parse(Request{Str: query}) 597 require.Error(t, err) 598 require.Contains(t, err.Error(), "Expected 2 operands") 599 } 600 601 func TestParseQueryWithLevelAgg(t *testing.T) { 602 query := ` 603 { 604 var(func: uid(0x0a)) { 605 friends { 606 a as count(age) 607 } 608 s as sum(val(a)) 609 } 610 611 sumage(func: uid( 0x0a)) { 612 val(s) 613 } 614 } 615 ` 616 res, err := Parse(Request{Str: query}) 617 require.NoError(t, err) 618 require.NotNil(t, res.Query) 619 require.Equal(t, 2, len(res.Query)) 620 require.Equal(t, "a", res.Query[0].Children[0].Children[0].Var) 621 require.True(t, res.Query[0].Children[1].IsInternal) 622 require.Equal(t, "a", res.Query[0].Children[1].NeedsVar[0].Name) 623 require.Equal(t, ValueVar, res.Query[0].Children[1].NeedsVar[0].Typ) 624 require.Equal(t, "s", res.Query[0].Children[1].Var) 625 } 626 627 func TestParseQueryWithVarValAggCombination(t *testing.T) { 628 query := ` 629 { 630 me(func: uid(L), orderasc: val(c) ) { 631 name 632 val(c) 633 } 634 635 var(func: uid(0x0a)) { 636 L as friends { 637 x as age 638 } 639 a as min(val(x)) 640 b as max(val(x)) 641 c as math(a + b) 642 } 643 } 644 ` 645 res, err := Parse(Request{Str: query}) 646 require.NoError(t, err) 647 require.NotNil(t, res.Query) 648 require.Equal(t, 2, len(res.Query)) 649 require.Equal(t, "L", res.Query[0].NeedsVar[0].Name) 650 require.Equal(t, UidVar, res.Query[0].NeedsVar[0].Typ) 651 require.Equal(t, "c", res.Query[0].NeedsVar[1].Name) 652 require.Equal(t, ValueVar, res.Query[0].NeedsVar[1].Typ) 653 require.Equal(t, "c", res.Query[0].Order[0].Attr) 654 require.Equal(t, "name", res.Query[0].Children[0].Attr) 655 require.Equal(t, "val", res.Query[0].Children[1].Attr) 656 require.Equal(t, 1, len(res.Query[0].Children[1].NeedsVar)) 657 require.Equal(t, "c", res.Query[0].Children[1].NeedsVar[0].Name) 658 require.Equal(t, "L", res.Query[1].Children[0].Var) 659 require.Equal(t, "a", res.Query[1].Children[1].Var) 660 require.Equal(t, "b", res.Query[1].Children[2].Var) 661 require.Equal(t, "c", res.Query[1].Children[3].Var) 662 require.NotNil(t, res.Query[1].Children[3].MathExp) 663 require.Equal(t, "+", res.Query[1].Children[3].MathExp.Fn) 664 require.Equal(t, "a", res.Query[1].Children[3].MathExp.Child[0].Var) 665 require.Equal(t, "b", res.Query[1].Children[3].MathExp.Child[1].Var) 666 } 667 668 func TestParseQueryWithVarValAgg(t *testing.T) { 669 query := ` 670 { 671 me(func: uid(L), orderasc: val(n) ) { 672 name 673 } 674 675 var(func: uid(0x0a)) { 676 L AS friends { 677 na as name 678 } 679 n as min(val(na)) 680 } 681 } 682 ` 683 res, err := Parse(Request{Str: query}) 684 require.NoError(t, err) 685 require.NotNil(t, res.Query) 686 require.Equal(t, 2, len(res.Query)) 687 require.Equal(t, "L", res.Query[0].NeedsVar[0].Name) 688 require.Equal(t, UidVar, res.Query[0].NeedsVar[0].Typ) 689 require.Equal(t, "n", res.Query[0].NeedsVar[1].Name) 690 require.Equal(t, ValueVar, res.Query[0].NeedsVar[1].Typ) 691 require.Equal(t, "n", res.Query[0].Order[0].Attr) 692 require.Equal(t, "name", res.Query[0].Children[0].Attr) 693 require.Equal(t, "L", res.Query[1].Children[0].Var) 694 require.Equal(t, "na", res.Query[1].Children[0].Children[0].Var) 695 require.Equal(t, "n", res.Query[1].Children[1].Var) 696 require.Equal(t, "min", res.Query[1].Children[1].Func.Name) 697 } 698 699 func TestParseQueryWithVarValAggError(t *testing.T) { 700 query := ` 701 { 702 me(func: uid(L), orderasc: uid(n)) { 703 name 704 } 705 706 var(func: uid(0x0a)) { 707 L AS friends { 708 na as name 709 } 710 n as min(val(na)) 711 } 712 } 713 ` 714 _, err := Parse(Request{Str: query}) 715 require.Error(t, err) 716 require.Contains(t, err.Error(), "Expected val(). Got uid() with order.") 717 } 718 719 func TestParseQueryWithVarValAggError2(t *testing.T) { 720 query := ` 721 { 722 me(func: val(L), orderasc: val(n)) { 723 name 724 } 725 726 var(func: uid(0x0a)) { 727 L AS friends { 728 na as name 729 } 730 n as min(val(na)) 731 } 732 } 733 ` 734 _, err := Parse(Request{Str: query}) 735 require.Error(t, err) 736 require.Contains(t, err.Error(), "Function name: val is not valid.") 737 } 738 739 func TestParseQueryWithVarValCount(t *testing.T) { 740 query := ` 741 { 742 me(func: uid(L), orderasc: val(n) ) { 743 name 744 } 745 746 var(func: uid(0x0a)) { 747 L AS friends { 748 n AS count(friend) 749 } 750 } 751 } 752 ` 753 res, err := Parse(Request{Str: query}) 754 require.NoError(t, err) 755 require.NotNil(t, res.Query) 756 require.Equal(t, 2, len(res.Query)) 757 require.Equal(t, "L", res.Query[0].NeedsVar[0].Name) 758 require.Equal(t, UidVar, res.Query[0].NeedsVar[0].Typ) 759 require.Equal(t, "n", res.Query[0].NeedsVar[1].Name) 760 require.Equal(t, ValueVar, res.Query[0].NeedsVar[1].Typ) 761 require.Equal(t, "n", res.Query[0].Order[0].Attr) 762 require.Equal(t, "name", res.Query[0].Children[0].Attr) 763 require.Equal(t, "L", res.Query[1].Children[0].Var) 764 require.True(t, res.Query[1].Children[0].Children[0].IsCount) 765 } 766 767 func TestParseQueryWithVarVal(t *testing.T) { 768 query := ` 769 { 770 me(func: uid(L), orderasc: val(n) ) { 771 name 772 } 773 774 var(func: uid(0x0a)) { 775 L AS friends { 776 n AS name 777 } 778 } 779 } 780 ` 781 res, err := Parse(Request{Str: query}) 782 require.NoError(t, err) 783 require.NotNil(t, res.Query) 784 require.Equal(t, 2, len(res.Query)) 785 require.Equal(t, "L", res.Query[0].NeedsVar[0].Name) 786 require.Equal(t, UidVar, res.Query[0].NeedsVar[0].Typ) 787 require.Equal(t, "n", res.Query[0].NeedsVar[1].Name) 788 require.Equal(t, ValueVar, res.Query[0].NeedsVar[1].Typ) 789 require.Equal(t, "n", res.Query[0].Order[0].Attr) 790 require.Equal(t, "name", res.Query[0].Children[0].Attr) 791 require.Equal(t, "L", res.Query[1].Children[0].Var) 792 require.Equal(t, "n", res.Query[1].Children[0].Children[0].Var) 793 } 794 795 func TestParseQueryWithVarMultiRoot(t *testing.T) { 796 query := ` 797 { 798 me(func: uid( L, J, K)) {name} 799 var(func: uid(0x0a)) {L AS friends} 800 var(func: uid(0x0a)) {J AS friends} 801 var(func: uid(0x0a)) {K AS friends} 802 } 803 ` 804 res, err := Parse(Request{Str: query}) 805 require.NoError(t, err) 806 require.NotNil(t, res.Query) 807 require.Equal(t, 4, len(res.Query)) 808 require.Equal(t, "L", res.Query[0].NeedsVar[0].Name) 809 require.Equal(t, "J", res.Query[0].NeedsVar[1].Name) 810 require.Equal(t, "K", res.Query[0].NeedsVar[2].Name) 811 require.Equal(t, UidVar, res.Query[0].NeedsVar[0].Typ) 812 require.Equal(t, UidVar, res.Query[0].NeedsVar[1].Typ) 813 require.Equal(t, UidVar, res.Query[0].NeedsVar[2].Typ) 814 require.Equal(t, "L", res.Query[1].Children[0].Var) 815 require.Equal(t, "J", res.Query[2].Children[0].Var) 816 require.Equal(t, "K", res.Query[3].Children[0].Var) 817 } 818 819 func TestParseQueryWithVar(t *testing.T) { 820 query := ` 821 { 822 me(func: uid(L)) {name} 823 him(func: uid(J)) {name} 824 you(func: uid(K)) {name} 825 var(func: uid(0x0a)) {L AS friends} 826 var(func: uid(0x0a)) {J AS friends} 827 var(func: uid(0x0a)) {K AS friends} 828 } 829 ` 830 res, err := Parse(Request{Str: query}) 831 require.NoError(t, err) 832 require.NotNil(t, res.Query) 833 require.Equal(t, 6, len(res.Query)) 834 require.Equal(t, "L", res.Query[0].NeedsVar[0].Name) 835 require.Equal(t, "J", res.Query[1].NeedsVar[0].Name) 836 require.Equal(t, "K", res.Query[2].NeedsVar[0].Name) 837 require.Equal(t, UidVar, res.Query[0].NeedsVar[0].Typ) 838 require.Equal(t, UidVar, res.Query[1].NeedsVar[0].Typ) 839 require.Equal(t, UidVar, res.Query[2].NeedsVar[0].Typ) 840 require.Equal(t, "L", res.Query[3].Children[0].Var) 841 require.Equal(t, "J", res.Query[4].Children[0].Var) 842 require.Equal(t, "K", res.Query[5].Children[0].Var) 843 } 844 845 func TestParseQueryWithVarError1(t *testing.T) { 846 query := ` 847 { 848 him(func: uid(J)) {name} 849 you(func: uid(K)) {name} 850 var(func: uid(0x0a)) {L AS friends} 851 var(func: uid(0x0a)) {J AS friends} 852 var(func: uid(0x0a)) {K AS friends} 853 } 854 ` 855 _, err := Parse(Request{Str: query}) 856 require.Error(t, err) 857 require.Contains(t, err.Error(), "Some variables are defined but not used") 858 } 859 860 func TestParseQueryWithVarError2(t *testing.T) { 861 query := ` 862 { 863 me(func: uid(L)) {name} 864 him(func: uid(J)) {name} 865 you(func: uid(K)) {name} 866 var(func: uid(0x0a)) {L AS friends} 867 var(func: uid(0x0a)) {K AS friends} 868 } 869 ` 870 _, err := Parse(Request{Str: query}) 871 require.Error(t, err) 872 require.Contains(t, err.Error(), "Some variables are used but not defined") 873 } 874 875 func TestParseQueryFilterError1A(t *testing.T) { 876 query := ` 877 { 878 me(func: uid(1) @filter(anyof(name, "alice"))) { 879 name 880 } 881 } 882 ` 883 _, err := Parse(Request{Str: query}) 884 require.Error(t, err) 885 require.Contains(t, err.Error(), "\"@\"") 886 } 887 888 func TestParseQueryFilterError1B(t *testing.T) { 889 query := ` 890 { 891 me(func: uid(1)) @filter(anyofterms(name"alice")) { 892 name 893 } 894 } 895 ` 896 _, err := Parse(Request{Str: query}) 897 require.Error(t, err) 898 require.Contains(t, err.Error(), "Expected comma or language but got: \"alice\"") 899 } 900 901 func TestParseQueryFilterError2(t *testing.T) { 902 query := ` 903 { 904 me(func: uid(1)) @filter(anyofterms(name "alice")) { 905 name 906 } 907 } 908 ` 909 _, err := Parse(Request{Str: query}) 910 require.Error(t, err) 911 require.Contains(t, err.Error(), "Expected comma or language but got: \"alice\"") 912 } 913 914 func TestParseQueryWithVarAtRootFilterID(t *testing.T) { 915 query := ` 916 { 917 K as var(func: uid(0x0a)) { 918 L AS friends 919 } 920 me(func: uid(K)) @filter(uid(L)) { 921 name 922 } 923 } 924 ` 925 res, err := Parse(Request{Str: query}) 926 require.NoError(t, err) 927 require.NotNil(t, res.Query) 928 require.Equal(t, 2, len(res.Query)) 929 require.Equal(t, "K", res.Query[0].Var) 930 require.Equal(t, "L", res.Query[0].Children[0].Var) 931 require.Equal(t, "L", res.Query[1].Filter.Func.NeedsVar[0].Name) 932 require.Equal(t, UidVar, res.Query[1].Filter.Func.NeedsVar[0].Typ) 933 require.Equal(t, []string{"K", "L"}, res.QueryVars[0].Defines) 934 } 935 936 func TestParseQueryWithVarAtRoot(t *testing.T) { 937 query := ` 938 { 939 K AS var(func: uid(0x0a)) { 940 fr as friends 941 } 942 me(func: uid(fr)) @filter(uid(K)) { 943 name @filter(uid(fr)) 944 } 945 } 946 ` 947 res, err := Parse(Request{Str: query}) 948 require.NoError(t, err) 949 require.NotNil(t, res.Query) 950 require.Equal(t, 2, len(res.Query)) 951 require.Equal(t, "K", res.Query[0].Var) 952 require.Equal(t, "fr", res.Query[0].Children[0].Var) 953 require.Equal(t, "fr", res.Query[1].NeedsVar[0].Name) 954 require.Equal(t, UidVar, res.Query[1].NeedsVar[0].Typ) 955 require.Equal(t, []string{"K", "fr"}, res.QueryVars[0].Defines) 956 } 957 958 func TestParseQueryWithVarInIneqError(t *testing.T) { 959 query := ` 960 { 961 var(func: uid(0x0a)) { 962 fr as friends { 963 a as age 964 } 965 } 966 967 me(func: uid(fr)) @filter(gt(val(a, b), 10)) { 968 name 969 } 970 } 971 ` 972 // Multiple vars not allowed. 973 _, err := Parse(Request{Str: query}) 974 require.Error(t, err) 975 require.Contains(t, err.Error(), "Multiple variables not allowed in a function") 976 } 977 978 func TestLenFunctionWithMultipleVariableError(t *testing.T) { 979 query := ` 980 { 981 var(func: uid(0x0a)) { 982 fr as friends { 983 a as age 984 } 985 } 986 987 me(func: uid(fr)) @filter(gt(len(a, b), 10)) { 988 name 989 } 990 } 991 ` 992 // Multiple vars not allowed. 993 _, err := Parse(Request{Str: query}) 994 require.Error(t, err) 995 require.Contains(t, err.Error(), "Multiple variables not allowed in len function") 996 } 997 998 func TestLenFunctionInsideUidError(t *testing.T) { 999 query := ` 1000 { 1001 var(func: uid(0x0a)) { 1002 fr as friends { 1003 a as age 1004 } 1005 } 1006 1007 me(func: uid(fr)) @filter(uid(len(a), 10)) { 1008 name 1009 } 1010 } 1011 ` 1012 _, err := Parse(Request{Str: query}) 1013 require.Error(t, err) 1014 require.Contains(t, err.Error(), "len function only allowed inside inequality") 1015 } 1016 1017 func TestLenFunctionWithNoVariable(t *testing.T) { 1018 query := ` 1019 { 1020 var(func: uid(0x0a)) { 1021 fr as friends { 1022 a as age 1023 } 1024 } 1025 1026 me(func: uid(fr)) @filter(len(), 10) { 1027 name 1028 } 1029 } 1030 ` 1031 _, err := Parse(Request{Str: query}) 1032 require.Error(t, err) 1033 require.Contains(t, err.Error(), "Got empty attr for function") 1034 } 1035 1036 func TestLenAsSecondArgumentError(t *testing.T) { 1037 query := ` 1038 { 1039 var(func: uid(0x0a)) { 1040 fr as friends { 1041 a as age 1042 } 1043 } 1044 1045 me(func: uid(fr)) @filter(10, len(fr)) { 1046 name 1047 } 1048 } 1049 ` 1050 _, err := Parse(Request{Str: query}) 1051 // TODO(pawan) - Error message can be improved. We should validate function names from a 1052 // whitelist. 1053 require.Error(t, err) 1054 } 1055 1056 func TestCountWithLenFunctionError(t *testing.T) { 1057 query := ` 1058 { 1059 var(func: uid(0x0a)) { 1060 fr as friends { 1061 a as age 1062 } 1063 } 1064 1065 me(func: uid(fr)) @filter(count(name), len(fr)) { 1066 name 1067 } 1068 } 1069 ` 1070 _, err := Parse(Request{Str: query}) 1071 // TODO(pawan) - Error message can be improved. 1072 require.Error(t, err) 1073 } 1074 1075 func TestParseQueryWithVarInIneq(t *testing.T) { 1076 query := ` 1077 { 1078 var(func: uid(0x0a)) { 1079 fr as friends { 1080 a as age 1081 } 1082 } 1083 1084 me(func: uid(fr)) @filter(gt(val(a), 10)) { 1085 name 1086 } 1087 } 1088 ` 1089 res, err := Parse(Request{Str: query}) 1090 require.NoError(t, err) 1091 require.NotNil(t, res.Query) 1092 require.Equal(t, 2, len(res.Query)) 1093 require.Equal(t, "fr", res.Query[0].Children[0].Var) 1094 require.Equal(t, "fr", res.Query[1].NeedsVar[0].Name) 1095 require.Equal(t, UidVar, res.Query[1].NeedsVar[0].Typ) 1096 require.Equal(t, ValueVar, res.Query[1].Filter.Func.NeedsVar[0].Typ) 1097 require.Equal(t, 1, len(res.Query[1].Filter.Func.Args)) 1098 require.Equal(t, "a", res.Query[1].Filter.Func.Attr) 1099 require.Equal(t, true, res.Query[1].Filter.Func.IsValueVar) 1100 require.Equal(t, "10", res.Query[1].Filter.Func.Args[0].Value) 1101 require.Equal(t, false, res.Query[1].Filter.Func.Args[0].IsValueVar) 1102 require.Equal(t, "gt", res.Query[1].Filter.Func.Name) 1103 } 1104 1105 func TestParseQueryWithVar1(t *testing.T) { 1106 query := ` 1107 { 1108 var(func: uid(0x0a)) { 1109 L AS friends 1110 } 1111 1112 me(func: uid(L)) { 1113 name 1114 } 1115 } 1116 ` 1117 res, err := Parse(Request{Str: query}) 1118 require.NoError(t, err) 1119 require.NotNil(t, res.Query) 1120 require.Equal(t, 2, len(res.Query)) 1121 require.Equal(t, "L", res.Query[0].Children[0].Var) 1122 require.Equal(t, "L", res.Query[1].NeedsVar[0].Name) 1123 require.Equal(t, UidVar, res.Query[1].NeedsVar[0].Typ) 1124 } 1125 1126 func TestParseQueryWithMultipleVar(t *testing.T) { 1127 query := ` 1128 { 1129 var(func: uid(0x0a)) { 1130 L AS friends { 1131 B AS relatives 1132 } 1133 } 1134 1135 me(func: uid(L)) { 1136 name 1137 } 1138 1139 relatives(func: uid(B)) { 1140 name 1141 } 1142 } 1143 ` 1144 res, err := Parse(Request{Str: query}) 1145 require.NoError(t, err) 1146 require.NotNil(t, res.Query) 1147 require.Equal(t, 3, len(res.Query)) 1148 require.Equal(t, "L", res.Query[0].Children[0].Var) 1149 require.Equal(t, "B", res.Query[0].Children[0].Children[0].Var) 1150 require.Equal(t, "L", res.Query[1].NeedsVar[0].Name) 1151 require.Equal(t, "B", res.Query[2].NeedsVar[0].Name) 1152 require.Equal(t, UidVar, res.Query[1].NeedsVar[0].Typ) 1153 require.Equal(t, UidVar, res.Query[2].NeedsVar[0].Typ) 1154 require.Equal(t, []string{"L", "B"}, res.QueryVars[0].Defines) 1155 require.Equal(t, []string{"L"}, res.QueryVars[1].Needs) 1156 require.Equal(t, []string{"B"}, res.QueryVars[2].Needs) 1157 } 1158 1159 func TestParseShortestPath(t *testing.T) { 1160 query := ` 1161 { 1162 shortest(from:0x0a, to:0x0b, numpaths: 3, minweight: 3, maxweight: 6) { 1163 friends 1164 name 1165 } 1166 } 1167 ` 1168 res, err := Parse(Request{Str: query}) 1169 require.NoError(t, err) 1170 require.NotNil(t, res.Query) 1171 require.Equal(t, 1, len(res.Query)) 1172 require.Equal(t, uint64(0xa), res.Query[0].ShortestPathArgs.From.UID[0]) 1173 require.Equal(t, uint64(0xb), res.Query[0].ShortestPathArgs.To.UID[0]) 1174 require.Equal(t, "3", res.Query[0].Args["numpaths"]) 1175 require.Equal(t, "3", res.Query[0].Args["minweight"]) 1176 require.Equal(t, "6", res.Query[0].Args["maxweight"]) 1177 } 1178 1179 func TestParseShortestPathWithUidVars(t *testing.T) { 1180 query := `{ 1181 a as var(func: uid(0x01)) 1182 b as var(func: uid(0x02)) 1183 1184 shortest(from: uid(a), to: uid(b)) { 1185 password 1186 friend 1187 } 1188 1189 }` 1190 res, err := Parse(Request{Str: query}) 1191 require.NoError(t, err) 1192 q := res.Query[2] 1193 require.NotNil(t, q.ShortestPathArgs.From) 1194 require.Equal(t, 1, len(q.ShortestPathArgs.From.NeedsVar)) 1195 require.Equal(t, "a", q.ShortestPathArgs.From.NeedsVar[0].Name) 1196 require.Equal(t, "uid", q.ShortestPathArgs.From.Name) 1197 require.NotNil(t, q.ShortestPathArgs.To) 1198 require.Equal(t, 1, len(q.ShortestPathArgs.To.NeedsVar)) 1199 } 1200 1201 func TestParseShortestPathInvalidFnError(t *testing.T) { 1202 query := `{ 1203 shortest(from: eq(a), to: uid(b)) { 1204 password 1205 friend 1206 } 1207 1208 }` 1209 _, err := Parse(Request{Str: query}) 1210 require.Error(t, err) 1211 } 1212 1213 func TestParseMultipleQueries(t *testing.T) { 1214 query := ` 1215 { 1216 you(func: uid(0x0a)) { 1217 name 1218 } 1219 1220 me(func: uid(0x0b)) { 1221 friends 1222 } 1223 } 1224 ` 1225 res, err := Parse(Request{Str: query}) 1226 require.NoError(t, err) 1227 require.NotNil(t, res.Query) 1228 require.Equal(t, 2, len(res.Query)) 1229 } 1230 1231 func TestParseRootArgs1(t *testing.T) { 1232 query := ` 1233 query { 1234 me(func: uid(0x0a), first: -4, offset: +1) { 1235 friends { 1236 name 1237 } 1238 gender,age 1239 hometown 1240 } 1241 } 1242 ` 1243 res, err := Parse(Request{Str: query}) 1244 require.NoError(t, err) 1245 require.NotNil(t, res.Query) 1246 require.Equal(t, 1, len(res.Query)) 1247 require.Equal(t, 2, len(res.Query[0].Args)) 1248 require.Equal(t, "-4", res.Query[0].Args["first"]) 1249 require.Equal(t, "+1", res.Query[0].Args["offset"]) 1250 require.Equal(t, childAttrs(res.Query[0]), []string{"friends", "gender", "age", "hometown"}) 1251 require.Equal(t, childAttrs(res.Query[0].Children[0]), []string{"name"}) 1252 } 1253 1254 func TestParseRootArgs2(t *testing.T) { 1255 query := ` 1256 query { 1257 me(func: uid(0x0a), first: 1, offset:0) { 1258 friends { 1259 name 1260 } 1261 gender,age 1262 hometown 1263 } 1264 } 1265 ` 1266 res, err := Parse(Request{Str: query}) 1267 require.NoError(t, err) 1268 require.NotNil(t, res.Query) 1269 require.Equal(t, 1, len(res.Query)) 1270 require.Equal(t, 2, len(res.Query[0].Args)) 1271 require.Equal(t, "1", res.Query[0].Args["first"]) 1272 require.Equal(t, "0", res.Query[0].Args["offset"]) 1273 require.Equal(t, childAttrs(res.Query[0]), []string{"friends", "gender", "age", "hometown"}) 1274 require.Equal(t, childAttrs(res.Query[0].Children[0]), []string{"name"}) 1275 } 1276 1277 func TestParse(t *testing.T) { 1278 query := ` 1279 query { 1280 me(func: uid(0x0a)) { 1281 friends { 1282 name 1283 } 1284 gender,age 1285 hometown 1286 } 1287 } 1288 ` 1289 res, err := Parse(Request{Str: query}) 1290 require.NoError(t, err) 1291 require.NotNil(t, res.Query) 1292 require.Equal(t, 1, len(res.Query)) 1293 require.Equal(t, childAttrs(res.Query[0]), []string{"friends", "gender", "age", "hometown"}) 1294 require.Equal(t, childAttrs(res.Query[0].Children[0]), []string{"name"}) 1295 } 1296 1297 func TestParseError(t *testing.T) { 1298 query := ` 1299 me(func: uid(0x0a)) { 1300 friends { 1301 name 1302 } 1303 gender,age 1304 hometown 1305 } 1306 } 1307 ` 1308 _, err := Parse(Request{Str: query}) 1309 require.Error(t, err) 1310 require.Contains(t, err.Error(), "Invalid operation type: me") 1311 } 1312 1313 func TestParseXid(t *testing.T) { 1314 query := ` 1315 query { 1316 user(func: uid( 0x11)) { 1317 type.object.name 1318 } 1319 }` 1320 res, err := Parse(Request{Str: query}) 1321 require.NoError(t, err) 1322 require.NotNil(t, res.Query[0]) 1323 require.Equal(t, childAttrs(res.Query[0]), []string{"type.object.name"}) 1324 } 1325 1326 func TestParseIdList(t *testing.T) { 1327 query := ` 1328 query { 1329 user(func: uid(0x1)) { 1330 type.object.name 1331 } 1332 }` 1333 r, err := Parse(Request{Str: query}) 1334 gq := r.Query[0] 1335 require.NoError(t, err) 1336 require.NotNil(t, gq) 1337 require.Equal(t, []string{"type.object.name"}, childAttrs(gq)) 1338 // require.Equal(t, []uint64{0x1}, gq.UID) 1339 } 1340 1341 func TestParseIdList1(t *testing.T) { 1342 query := ` 1343 query { 1344 user(func: uid(0x1, 0x34)) { 1345 type.object.name 1346 } 1347 }` 1348 r, err := Parse(Request{Str: query}) 1349 gq := r.Query[0] 1350 require.NoError(t, err) 1351 require.NotNil(t, gq) 1352 require.Equal(t, []string{"type.object.name"}, childAttrs(gq)) 1353 require.Equal(t, []uint64{0x1, 0x34}, gq.UID) 1354 require.Equal(t, 2, len(gq.UID)) 1355 } 1356 1357 func TestParseIdListError(t *testing.T) { 1358 query := ` 1359 query { 1360 user(func: uid( [0x1, 0x1, abc, ade, 0x34))] { 1361 type.object.name 1362 } 1363 }` 1364 _, err := Parse(Request{Str: query}) 1365 require.Error(t, err) 1366 require.Contains(t, err.Error(), 1367 "Unrecognized character in lexText: U+005D ']'") 1368 } 1369 1370 func TestParseIdListError2(t *testing.T) { 1371 query := ` 1372 query { 1373 user(func: uid( [0x1, 0x1, 2, 3, 0x34])) { 1374 type.object.name 1375 } 1376 }` 1377 _, err := Parse(Request{Str: query}) 1378 require.Error(t, err) 1379 require.Contains(t, err.Error(), 1380 "Unexpected character [ while parsing request.") 1381 } 1382 1383 func TestParseFirst(t *testing.T) { 1384 query := ` 1385 query { 1386 user(func: uid( 0x1)) { 1387 type.object.name 1388 friends (first: 10) { 1389 } 1390 } 1391 }` 1392 res, err := Parse(Request{Str: query}) 1393 require.NoError(t, err) 1394 require.NotNil(t, res.Query[0]) 1395 require.Equal(t, []string{"type.object.name", "friends"}, childAttrs(res.Query[0])) 1396 require.Equal(t, "10", res.Query[0].Children[1].Args["first"]) 1397 } 1398 1399 func TestParseFirst_error(t *testing.T) { 1400 query := ` 1401 query { 1402 user(func: uid( 0x1)) { 1403 type.object.name 1404 friends (first: ) { 1405 } 1406 } 1407 }` 1408 _, err := Parse(Request{Str: query}) 1409 require.Error(t, err) 1410 require.Contains(t, err.Error(), "Expecting argument value") 1411 require.Contains(t, err.Error(), "\")\"") 1412 } 1413 1414 func TestParseAfter(t *testing.T) { 1415 query := ` 1416 query { 1417 user(func: uid( 0x1)) { 1418 type.object.name 1419 friends (first: 10, after: 3) { 1420 } 1421 } 1422 }` 1423 res, err := Parse(Request{Str: query}) 1424 require.NoError(t, err) 1425 require.NotNil(t, res.Query[0]) 1426 require.Equal(t, childAttrs(res.Query[0]), []string{"type.object.name", "friends"}) 1427 require.Equal(t, res.Query[0].Children[1].Args["first"], "10") 1428 require.Equal(t, res.Query[0].Children[1].Args["after"], "3") 1429 } 1430 1431 func TestParseOffset(t *testing.T) { 1432 query := ` 1433 query { 1434 user(func: uid( 0x1)) { 1435 type.object.name 1436 friends (first: 10, offset: 3) { 1437 } 1438 } 1439 }` 1440 res, err := Parse(Request{Str: query}) 1441 require.NoError(t, err) 1442 require.NotNil(t, res.Query[0]) 1443 require.Equal(t, childAttrs(res.Query[0]), []string{"type.object.name", "friends"}) 1444 require.Equal(t, res.Query[0].Children[1].Args["first"], "10") 1445 require.Equal(t, res.Query[0].Children[1].Args["offset"], "3") 1446 } 1447 1448 func TestParseOffset_error(t *testing.T) { 1449 query := ` 1450 query { 1451 user(func: uid( 0x1)) { 1452 type.object.name 1453 friends (first: 10, offset: ) { 1454 } 1455 } 1456 }` 1457 _, err := Parse(Request{Str: query}) 1458 require.Error(t, err) 1459 require.Contains(t, err.Error(), "Expecting argument value") 1460 require.Contains(t, err.Error(), "\")\"") 1461 } 1462 1463 func TestParse_error2(t *testing.T) { 1464 query := ` 1465 query { 1466 me { 1467 name 1468 } 1469 } 1470 ` 1471 _, err := Parse(Request{Str: query}) 1472 require.Error(t, err) 1473 require.Contains(t, err.Error(), "Expected Left round brackets") 1474 require.Contains(t, err.Error(), "\"{\"") 1475 1476 } 1477 1478 func TestParse_pass1(t *testing.T) { 1479 query := ` 1480 { 1481 me(func: uid(0x0a)) { 1482 name, 1483 friends(xid:what) { # xid would be ignored. 1484 } 1485 } 1486 } 1487 ` 1488 _, err := Parse(Request{Str: query}) 1489 require.Error(t, err) 1490 require.Contains(t, err.Error(), "Got invalid keyword: xid") 1491 } 1492 1493 func TestParse_alias_count(t *testing.T) { 1494 query := ` 1495 { 1496 me(func: uid(0x0a)) { 1497 name, 1498 bestFriend: friends(first: 10) { 1499 nameCount: count(name) 1500 } 1501 } 1502 } 1503 ` 1504 res, err := Parse(Request{Str: query}) 1505 require.NoError(t, err) 1506 require.NotNil(t, res.Query[0]) 1507 require.Equal(t, childAttrs(res.Query[0]), []string{"name", "friends"}) 1508 require.Equal(t, res.Query[0].Children[1].Alias, "bestFriend") 1509 require.Equal(t, childAttrs(res.Query[0].Children[1]), []string{"name"}) 1510 require.Equal(t, "nameCount", res.Query[0].Children[1].Children[0].Alias) 1511 } 1512 1513 func TestParse_alias_var(t *testing.T) { 1514 query := ` 1515 { 1516 me(func: uid(0x0a)) { 1517 name, 1518 f as bestFriend: friends(first: 10) { 1519 c as count(friend) 1520 } 1521 } 1522 1523 friend(func: uid(f)) { 1524 name 1525 fcount: val(c) 1526 } 1527 } 1528 ` 1529 res, err := Parse(Request{Str: query}) 1530 require.NoError(t, err) 1531 require.NotNil(t, res.Query[0]) 1532 require.Equal(t, childAttrs(res.Query[0]), []string{"name", "friends"}) 1533 require.Equal(t, res.Query[0].Children[1].Alias, "bestFriend") 1534 require.Equal(t, "fcount", res.Query[1].Children[1].Alias) 1535 } 1536 1537 func TestParse_alias_max(t *testing.T) { 1538 query := ` 1539 { 1540 me(func: uid(0x0a)) { 1541 name, 1542 bestFriend: friends(first: 10) { 1543 x as count(friends) 1544 } 1545 maxfriendcount: max(val(x)) 1546 } 1547 } 1548 ` 1549 res, err := Parse(Request{Str: query}) 1550 require.NoError(t, err) 1551 require.NotNil(t, res.Query[0]) 1552 require.Equal(t, res.Query[0].Children[1].Alias, "bestFriend") 1553 require.Equal(t, "maxfriendcount", res.Query[0].Children[2].Alias) 1554 } 1555 1556 func TestParse_alias(t *testing.T) { 1557 query := ` 1558 { 1559 me(func: uid(0x0a)) { 1560 name, 1561 bestFriend: friends(first: 10) { 1562 name 1563 } 1564 } 1565 } 1566 ` 1567 res, err := Parse(Request{Str: query}) 1568 require.NoError(t, err) 1569 require.NotNil(t, res.Query[0]) 1570 require.Equal(t, childAttrs(res.Query[0]), []string{"name", "friends"}) 1571 require.Equal(t, res.Query[0].Children[1].Alias, "bestFriend") 1572 require.Equal(t, childAttrs(res.Query[0].Children[1]), []string{"name"}) 1573 } 1574 1575 func TestParse_alias1(t *testing.T) { 1576 query := ` 1577 { 1578 me(func: uid(0x0a)) { 1579 name: type.object.name.en 1580 bestFriend: friends(first: 10) { 1581 name: type.object.name.hi 1582 } 1583 } 1584 } 1585 ` 1586 res, err := Parse(Request{Str: query}) 1587 require.NoError(t, err) 1588 require.NotNil(t, res.Query[0]) 1589 require.Equal(t, childAttrs(res.Query[0]), []string{"type.object.name.en", "friends"}) 1590 require.Equal(t, res.Query[0].Children[1].Alias, "bestFriend") 1591 require.Equal(t, res.Query[0].Children[1].Children[0].Alias, "name") 1592 require.Equal(t, childAttrs(res.Query[0].Children[1]), []string{"type.object.name.hi"}) 1593 } 1594 1595 func TestParse_block(t *testing.T) { 1596 query := ` 1597 { 1598 root(func: uid( 0x0a)) { 1599 type.object.name.es.419 1600 } 1601 } 1602 ` 1603 res, err := Parse(Request{Str: query}) 1604 require.NoError(t, err) 1605 require.NotNil(t, res.Query[0]) 1606 require.Equal(t, childAttrs(res.Query[0]), []string{"type.object.name.es.419"}) 1607 } 1608 1609 func TestParseSchema(t *testing.T) { 1610 query := ` 1611 schema (pred : name) { 1612 pred 1613 type 1614 } 1615 ` 1616 res, err := Parse(Request{Str: query}) 1617 require.NoError(t, err) 1618 require.Equal(t, res.Schema.Predicates[0], "name") 1619 require.Equal(t, len(res.Schema.Fields), 2) 1620 require.Equal(t, res.Schema.Fields[0], "pred") 1621 require.Equal(t, res.Schema.Fields[1], "type") 1622 } 1623 1624 func TestParseSchemaMulti(t *testing.T) { 1625 query := ` 1626 schema (pred : [name,hi]) { 1627 pred 1628 type 1629 } 1630 ` 1631 res, err := Parse(Request{Str: query}) 1632 require.NoError(t, err) 1633 require.Equal(t, len(res.Schema.Predicates), 2) 1634 require.Equal(t, res.Schema.Predicates[0], "name") 1635 require.Equal(t, res.Schema.Predicates[1], "hi") 1636 require.Equal(t, len(res.Schema.Fields), 2) 1637 require.Equal(t, res.Schema.Fields[0], "pred") 1638 require.Equal(t, res.Schema.Fields[1], "type") 1639 } 1640 1641 func TestParseSchemaAll(t *testing.T) { 1642 query := ` 1643 schema { 1644 pred 1645 type 1646 } 1647 ` 1648 res, err := Parse(Request{Str: query}) 1649 require.NoError(t, err) 1650 require.Equal(t, len(res.Schema.Predicates), 0) 1651 require.Equal(t, len(res.Schema.Fields), 2) 1652 require.Equal(t, res.Schema.Fields[0], "pred") 1653 require.Equal(t, res.Schema.Fields[1], "type") 1654 } 1655 1656 func TestParseSchemaWithComments(t *testing.T) { 1657 query := ` 1658 schema (pred : name) { 1659 #hi 1660 pred #bye 1661 type 1662 } 1663 ` 1664 res, err := Parse(Request{Str: query}) 1665 require.NoError(t, err) 1666 require.Equal(t, res.Schema.Predicates[0], "name") 1667 require.Equal(t, len(res.Schema.Fields), 2) 1668 require.Equal(t, res.Schema.Fields[0], "pred") 1669 require.Equal(t, res.Schema.Fields[1], "type") 1670 } 1671 1672 func TestParseSchemaAndQuery(t *testing.T) { 1673 query1 := ` 1674 schema { 1675 pred 1676 type 1677 } 1678 query { 1679 me(func: uid( tomhanks)) { 1680 name 1681 hometown 1682 } 1683 } 1684 ` 1685 query2 := ` 1686 query { 1687 me(func: uid( tomhanks)) { 1688 name 1689 hometown 1690 } 1691 } 1692 schema { 1693 pred 1694 type 1695 } 1696 ` 1697 1698 _, err := Parse(Request{Str: query1}) 1699 require.Error(t, err) 1700 require.Contains(t, err.Error(), "Schema block is not allowed with query block") 1701 1702 _, err = Parse(Request{Str: query2}) 1703 require.Error(t, err) 1704 require.Contains(t, err.Error(), "Schema block is not allowed with query block") 1705 } 1706 1707 func TestParseSchemaType(t *testing.T) { 1708 query := ` 1709 schema (type: Person) { 1710 } 1711 ` 1712 res, err := Parse(Request{Str: query}) 1713 require.NoError(t, err) 1714 require.Equal(t, len(res.Schema.Predicates), 0) 1715 require.Equal(t, len(res.Schema.Types), 1) 1716 require.Equal(t, res.Schema.Types[0], "Person") 1717 require.Equal(t, len(res.Schema.Fields), 0) 1718 } 1719 1720 func TestParseSchemaTypeMulti(t *testing.T) { 1721 query := ` 1722 schema (type: [Person, Animal]) { 1723 } 1724 ` 1725 res, err := Parse(Request{Str: query}) 1726 require.NoError(t, err) 1727 require.Equal(t, len(res.Schema.Predicates), 0) 1728 require.Equal(t, len(res.Schema.Types), 2) 1729 require.Equal(t, res.Schema.Types[0], "Person") 1730 require.Equal(t, res.Schema.Types[1], "Animal") 1731 require.Equal(t, len(res.Schema.Fields), 0) 1732 } 1733 1734 func TestParseSchemaError(t *testing.T) { 1735 query := ` 1736 schema () { 1737 pred 1738 type 1739 } 1740 ` 1741 _, err := Parse(Request{Str: query}) 1742 require.Error(t, err) 1743 require.Contains(t, err.Error(), "Invalid schema block") 1744 } 1745 1746 func TestParseSchemaErrorMulti(t *testing.T) { 1747 query := ` 1748 schema { 1749 pred 1750 type 1751 } 1752 schema { 1753 pred 1754 type 1755 } 1756 ` 1757 _, err := Parse(Request{Str: query}) 1758 require.Error(t, err) 1759 require.Contains(t, err.Error(), "Only one schema block allowed") 1760 } 1761 1762 func TestParseMutationError(t *testing.T) { 1763 query := ` 1764 mutation { 1765 set { 1766 <name> <is> <something> . 1767 <hometown> <is> <san/francisco> . 1768 } 1769 delete { 1770 <name> <is> <something-else> . 1771 } 1772 } 1773 ` 1774 _, err := ParseMutation(query) 1775 require.Error(t, err) 1776 require.Contains(t, err.Error(), `Invalid block: [mutation]`) 1777 } 1778 1779 func TestParseMutationError2(t *testing.T) { 1780 query := ` 1781 set { 1782 <name> <is> <something> . 1783 <hometown> <is> <san/francisco> . 1784 } 1785 delete { 1786 <name> <is> <something-else> . 1787 } 1788 ` 1789 _, err := ParseMutation(query) 1790 require.Error(t, err) 1791 require.Contains(t, err.Error(), `Invalid block: [set]`) 1792 } 1793 1794 func TestParseMutationAndQueryWithComments(t *testing.T) { 1795 query := ` 1796 # Mutation 1797 mutation { 1798 # Set block 1799 set { 1800 <name> <is> <something> . 1801 <hometown> <is> <san/francisco> . 1802 } 1803 # Delete block 1804 delete { 1805 <name> <is> <something-else> . 1806 } 1807 } 1808 # Query starts here. 1809 query { 1810 me(func: uid( 0x5)) { # now mention children 1811 name # Name 1812 hometown # hometown of the person 1813 } 1814 } 1815 ` 1816 _, err := Parse(Request{Str: query}) 1817 require.Error(t, err) 1818 } 1819 1820 func TestParseFragmentMultiQuery(t *testing.T) { 1821 query := ` 1822 { 1823 user(func: uid(0x0a)) { 1824 ...fragmenta,...fragmentb 1825 friends { 1826 name 1827 } 1828 ...fragmentc 1829 hobbies 1830 ...fragmentd 1831 } 1832 1833 me(func: uid(0x01)) { 1834 ...fragmenta 1835 ...fragmentb 1836 } 1837 } 1838 1839 fragment fragmenta { 1840 name 1841 } 1842 1843 fragment fragmentb { 1844 id 1845 } 1846 1847 fragment fragmentc { 1848 name 1849 } 1850 1851 fragment fragmentd { 1852 id 1853 } 1854 ` 1855 res, err := Parse(Request{Str: query}) 1856 require.NoError(t, err) 1857 require.NotNil(t, res.Query[0]) 1858 require.Equal(t, []string{"name", "id", "friends", "name", "hobbies", "id"}, childAttrs(res.Query[0])) 1859 require.Equal(t, []string{"name", "id"}, childAttrs(res.Query[1])) 1860 } 1861 1862 func TestParseFragmentNoNesting(t *testing.T) { 1863 query := ` 1864 query { 1865 user(func: uid(0x0a)) { 1866 ...fragmenta,...fragmentb 1867 friends { 1868 name 1869 } 1870 ...fragmentc 1871 hobbies 1872 ...fragmentd 1873 } 1874 } 1875 1876 fragment fragmenta { 1877 name 1878 } 1879 1880 fragment fragmentb { 1881 id 1882 } 1883 1884 fragment fragmentc { 1885 name 1886 } 1887 1888 fragment fragmentd { 1889 id 1890 } 1891 ` 1892 res, err := Parse(Request{Str: query}) 1893 require.NoError(t, err) 1894 require.NotNil(t, res.Query[0]) 1895 require.Equal(t, childAttrs(res.Query[0]), []string{"name", "id", "friends", "name", "hobbies", "id"}) 1896 } 1897 1898 func TestParseFragmentNest1(t *testing.T) { 1899 query := ` 1900 query { 1901 user(func: uid(0x0a)) { 1902 ...fragmenta 1903 friends { 1904 name 1905 } 1906 } 1907 } 1908 1909 fragment fragmenta { 1910 id 1911 ...fragmentb 1912 } 1913 1914 fragment fragmentb { 1915 hobbies 1916 } 1917 ` 1918 res, err := Parse(Request{Str: query}) 1919 require.NoError(t, err) 1920 require.NotNil(t, res.Query[0]) 1921 require.Equal(t, childAttrs(res.Query[0]), []string{"id", "hobbies", "friends"}) 1922 } 1923 1924 func TestParseFragmentNest2(t *testing.T) { 1925 query := ` 1926 query { 1927 user(func: uid(0x0a)) { 1928 friends { 1929 ...fragmenta 1930 } 1931 } 1932 } 1933 fragment fragmenta { 1934 name 1935 ...fragmentb 1936 } 1937 fragment fragmentb { 1938 nickname 1939 } 1940 ` 1941 res, err := Parse(Request{Str: query}) 1942 require.NoError(t, err) 1943 require.NotNil(t, res.Query[0]) 1944 require.Equal(t, childAttrs(res.Query[0]), []string{"friends"}) 1945 require.Equal(t, childAttrs(res.Query[0].Children[0]), []string{"name", "nickname"}) 1946 } 1947 1948 func TestParseFragmentCycle(t *testing.T) { 1949 query := ` 1950 query { 1951 user(func: uid(0x0a)) { 1952 ...fragmenta 1953 } 1954 } 1955 fragment fragmenta { 1956 name 1957 ...fragmentb 1958 } 1959 fragment fragmentb { 1960 ...fragmentc 1961 } 1962 fragment fragmentc { 1963 id 1964 ...fragmenta 1965 } 1966 ` 1967 _, err := Parse(Request{Str: query}) 1968 require.Error(t, err, "Expected error with cycle") 1969 require.Contains(t, err.Error(), "Cycle detected") 1970 } 1971 1972 func TestParseFragmentMissing(t *testing.T) { 1973 query := ` 1974 query { 1975 user(func: uid(0x0a)) { 1976 ...fragmenta 1977 } 1978 } 1979 fragment fragmentb { 1980 ...fragmentc 1981 } 1982 fragment fragmentc { 1983 id 1984 ...fragmenta 1985 } 1986 ` 1987 _, err := Parse(Request{Str: query}) 1988 require.Error(t, err, "Expected error with missing fragment") 1989 require.Contains(t, err.Error(), "Missing fragment: fragmenta") 1990 } 1991 1992 func TestParseStringVarInFilter(t *testing.T) { 1993 query := ` 1994 query versions($version: string = "v0.7.3/beta") 1995 { 1996 versions(func:eq(type, "version")) 1997 { 1998 versions @filter(eq(version_number, $version)) 1999 { 2000 version_number 2001 } 2002 } 2003 } 2004 ` 2005 res, err := Parse(Request{Str: query}) 2006 require.NoError(t, err) 2007 require.NotNil(t, res.Query[0]) 2008 require.Equal(t, "v0.7.3/beta", res.Query[0].Children[0].Filter.Func.Args[0].Value) 2009 } 2010 2011 func TestParseVariablesError1(t *testing.T) { 2012 query := ` 2013 query testQuery($a: string, $b: int!){ 2014 root(func: uid( 0x0a)) { 2015 type.object.name.es-419 2016 } 2017 } 2018 ` 2019 _, err := Parse(Request{Str: query}) 2020 require.Error(t, err) 2021 require.Contains(t, err.Error(), "Unrecognized character in lexText: U+0034 '4'") 2022 } 2023 2024 func TestParseFilter_root(t *testing.T) { 2025 query := ` 2026 query { 2027 me(func:anyofterms(abc, "Abc")) @filter(allofterms(name, "alice")) { 2028 friends @filter() { 2029 name @filter(namefilter(name, "a")) 2030 } 2031 gender @filter(eq(g, "a")),age @filter(neq(a, "b")) 2032 hometown 2033 } 2034 } 2035 ` 2036 res, err := Parse(Request{Str: query}) 2037 require.NoError(t, err) 2038 require.NotNil(t, res.Query[0]) 2039 require.NotNil(t, res.Query[0].Filter) 2040 require.Equal(t, `(allofterms name "alice")`, res.Query[0].Filter.debugString()) 2041 require.Equal(t, []string{"friends", "gender", "age", "hometown"}, childAttrs(res.Query[0])) 2042 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2043 require.Nil(t, res.Query[0].Children[0].Filter) 2044 require.Equal(t, `(eq g "a")`, res.Query[0].Children[1].Filter.debugString()) 2045 require.Equal(t, `(neq a "b")`, res.Query[0].Children[2].Filter.debugString()) 2046 require.Equal(t, `(namefilter name "a")`, res.Query[0].Children[0].Children[0].Filter.debugString()) 2047 } 2048 2049 func TestParseFuncNested(t *testing.T) { 2050 query := ` 2051 query { 2052 me(func: gt(count(friend), 10)) { 2053 friends @filter() { 2054 name 2055 } 2056 hometown 2057 } 2058 } 2059 ` 2060 res, err := Parse(Request{Str: query}) 2061 require.NoError(t, err) 2062 require.NotNil(t, res.Query[0]) 2063 require.NotNil(t, res.Query[0].Func) 2064 require.Equal(t, res.Query[0].Func.Name, "gt") 2065 require.Equal(t, res.Query[0].Func.Args[0].Value, "10") 2066 require.Equal(t, res.Query[0].Func.IsCount, true) 2067 } 2068 2069 func TestParseFuncNested2(t *testing.T) { 2070 query := ` 2071 query { 2072 var(func:uid(1)) { 2073 a as name 2074 } 2075 me(func: eq(name, val(a))) { 2076 friends @filter() { 2077 name 2078 } 2079 hometown 2080 } 2081 } 2082 ` 2083 res, err := Parse(Request{Str: query}) 2084 require.NoError(t, err) 2085 require.NotNil(t, res.Query[1]) 2086 require.NotNil(t, res.Query[1].Func) 2087 require.Equal(t, res.Query[1].Func.Name, "eq") 2088 require.Equal(t, res.Query[1].Func.Args[0].Value, "a") 2089 require.Equal(t, res.Query[1].Func.Args[0].IsValueVar, true) 2090 require.Equal(t, res.Query[1].Func.IsCount, false) 2091 } 2092 2093 func TestParseFilter_root2(t *testing.T) { 2094 query := ` 2095 query { 2096 me(func:anyofterms(abc, "Abc")) @filter(gt(count(friends), 10)) { 2097 friends @filter() { 2098 name 2099 } 2100 hometown 2101 } 2102 } 2103 ` 2104 res, err := Parse(Request{Str: query}) 2105 require.NoError(t, err) 2106 require.NotNil(t, res.Query[0]) 2107 require.NotNil(t, res.Query[0].Filter) 2108 require.Equal(t, `(gt count(friends) "10")`, res.Query[0].Filter.debugString()) 2109 require.Equal(t, []string{"friends", "hometown"}, childAttrs(res.Query[0])) 2110 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2111 require.Nil(t, res.Query[0].Children[0].Filter) 2112 } 2113 2114 func TestParseFilter_root_Error2(t *testing.T) { 2115 // filter-by-count only support first argument as function 2116 query := ` 2117 query { 2118 me(func:anyofterms(abc, "Abc")) @filter(gt(count(friends), sum(friends))) { 2119 friends @filter() { 2120 name 2121 } 2122 hometown 2123 } 2124 } 2125 ` 2126 _, err := Parse(Request{Str: query}) 2127 require.Error(t, err) 2128 require.Contains(t, err.Error(), "Multiple functions as arguments not allowed") 2129 } 2130 2131 func TestParseFilter_simplest(t *testing.T) { 2132 query := ` 2133 query { 2134 me(func: uid(0x0a)) { 2135 friends @filter() { 2136 name @filter(namefilter(name, "a")) 2137 } 2138 gender @filter(eq(g, "a")),age @filter(neq(a, "b")) 2139 hometown 2140 } 2141 } 2142 ` 2143 res, err := Parse(Request{Str: query}) 2144 require.NoError(t, err) 2145 require.NotNil(t, res.Query[0]) 2146 require.Equal(t, []string{"friends", "gender", "age", "hometown"}, childAttrs(res.Query[0])) 2147 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2148 require.Nil(t, res.Query[0].Children[0].Filter) 2149 require.Equal(t, `(eq g "a")`, res.Query[0].Children[1].Filter.debugString()) 2150 require.Equal(t, `(neq a "b")`, res.Query[0].Children[2].Filter.debugString()) 2151 require.Equal(t, `(namefilter name "a")`, res.Query[0].Children[0].Children[0].Filter.debugString()) 2152 } 2153 2154 // Test operator precedence. and should be evaluated before or. 2155 func TestParseFilter_op(t *testing.T) { 2156 query := ` 2157 query { 2158 me(func: uid(0x0a)) { 2159 friends @filter(a(aa, "aaa") or b(bb, "bbb") 2160 and c(cc, "ccc")) { 2161 name 2162 } 2163 gender,age 2164 hometown 2165 } 2166 } 2167 ` 2168 res, err := Parse(Request{Str: query}) 2169 require.NoError(t, err) 2170 require.NotNil(t, res.Query[0]) 2171 require.Equal(t, []string{"friends", "gender", "age", "hometown"}, childAttrs(res.Query[0])) 2172 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2173 require.Equal(t, `(OR (a aa "aaa") (AND (b bb "bbb") (c cc "ccc")))`, res.Query[0].Children[0].Filter.debugString()) 2174 } 2175 2176 func TestParseFilter_opError1(t *testing.T) { 2177 query := ` 2178 query { 2179 me(func: uid(0x0a)) { 2180 friends @filter(a(aa "aaa") or b(b "bbb")) { 2181 name 2182 } 2183 gender,age 2184 hometown 2185 } 2186 } 2187 ` 2188 _, err := Parse(Request{Str: query}) 2189 require.Error(t, err) 2190 require.Contains(t, err.Error(), "Expected comma or language but got: \"aaa\"") 2191 } 2192 2193 func TestParseFilter_opNoError2(t *testing.T) { 2194 query := ` 2195 query { 2196 me(func: uid(0x0a)) { 2197 friends @filter(a(aa, "aaa") or b(b, "bbb")) { 2198 name 2199 } 2200 gender,age 2201 hometown 2202 } 2203 } 2204 ` 2205 _, err := Parse(Request{Str: query}) 2206 require.NoError(t, err) 2207 // It's valid. Makes sure TestParseFilter_opError3 fails for the expected reason. 2208 } 2209 2210 func TestParseFilter_opError3(t *testing.T) { 2211 query := ` 2212 query { 2213 me(func: uid(0x0a)) { 2214 friends @filter(a(aa, "aaa") or b(b, "bbb") and) { 2215 name 2216 } 2217 gender,age 2218 hometown 2219 } 2220 } 2221 ` 2222 _, err := Parse(Request{Str: query}) 2223 require.Error(t, err) 2224 require.Contains(t, err.Error(), "Invalid filter statement") 2225 } 2226 2227 func TestParseFilter_opNot1(t *testing.T) { 2228 query := ` 2229 query { 2230 me(func: uid(0x0a)) { 2231 friends @filter(not a(aa, "aaa")) { 2232 name 2233 } 2234 gender,age 2235 hometown 2236 } 2237 } 2238 ` 2239 res, err := Parse(Request{Str: query}) 2240 require.NoError(t, err) 2241 require.NotNil(t, res.Query[0]) 2242 require.Equal(t, []string{"friends", "gender", "age", "hometown"}, childAttrs(res.Query[0])) 2243 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2244 require.Equal(t, `(NOT (a aa "aaa"))`, res.Query[0].Children[0].Filter.debugString()) 2245 } 2246 2247 func TestParseFilter_opNot2(t *testing.T) { 2248 query := ` 2249 query { 2250 me(func: uid(0x0a)) { 2251 friends @filter(not(a(aa, "aaa") or (b(bb, "bbb"))) and c(cc, "ccc")) { 2252 name 2253 } 2254 gender,age 2255 hometown 2256 } 2257 } 2258 ` 2259 res, err := Parse(Request{Str: query}) 2260 require.NoError(t, err) 2261 require.NotNil(t, res.Query[0]) 2262 require.Equal(t, []string{"friends", "gender", "age", "hometown"}, childAttrs(res.Query[0])) 2263 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2264 require.Equal(t, `(AND (NOT (OR (a aa "aaa") (b bb "bbb"))) (c cc "ccc"))`, res.Query[0].Children[0].Filter.debugString()) 2265 } 2266 2267 // Test operator precedence. Let brackets make or evaluates before and. 2268 func TestParseFilter_op2(t *testing.T) { 2269 query := ` 2270 query { 2271 me(func: uid(0x0a)) { 2272 friends @filter((a(aa, "aaa") Or b(bb, "bbb")) 2273 and c(cc, "ccc")) { 2274 name 2275 } 2276 gender,age 2277 hometown 2278 } 2279 } 2280 ` 2281 res, err := Parse(Request{Str: query}) 2282 require.NoError(t, err) 2283 require.NotNil(t, res.Query[0]) 2284 require.Equal(t, []string{"friends", "gender", "age", "hometown"}, childAttrs(res.Query[0])) 2285 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2286 require.Equal(t, `(AND (OR (a aa "aaa") (b bb "bbb")) (c cc "ccc"))`, res.Query[0].Children[0].Filter.debugString()) 2287 } 2288 2289 // Test operator precedence. More elaborate brackets. 2290 func TestParseFilter_brac(t *testing.T) { 2291 query := ` 2292 query { 2293 me(func: uid(0x0a)) { 2294 friends @filter( a(name, "hello") or b(name, "world", "is") and (c(aa, "aaa") or (d(dd, "haha") or e(ee, "aaa"))) and f(ff, "aaa")){ 2295 name 2296 } 2297 gender,age 2298 hometown 2299 } 2300 } 2301 ` 2302 res, err := Parse(Request{Str: query}) 2303 require.NoError(t, err) 2304 require.NotNil(t, res.Query[0]) 2305 require.Equal(t, []string{"friends", "gender", "age", "hometown"}, childAttrs(res.Query[0])) 2306 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 2307 require.Equal(t, 2308 `(OR (a name "hello") (AND (AND (b name "world" "is") (OR (c aa "aaa") (OR (d dd "haha") (e ee "aaa")))) (f ff "aaa")))`, 2309 res.Query[0].Children[0].Filter.debugString()) 2310 } 2311 2312 // Test if unbalanced brac will lead to errors. 2313 func TestParseFilter_unbalancedbrac(t *testing.T) { 2314 query := ` 2315 query { 2316 me(func: uid(0x0a)) { 2317 friends @filter( () { 2318 name 2319 } 2320 gender,age 2321 hometown 2322 } 2323 } 2324 ` 2325 _, err := Parse(Request{Str: query}) 2326 require.Error(t, err) 2327 require.Contains(t, err.Error(), 2328 "Unrecognized character inside a func: U+007B '{'") 2329 } 2330 2331 func TestParseFilter_Geo1(t *testing.T) { 2332 query := ` 2333 query { 2334 me(func: uid(0x0a)) { 2335 friends @filter(near(loc, [-1.12 , 2.0123 ], 100.123 )) { 2336 name 2337 } 2338 gender,age 2339 hometown 2340 } 2341 } 2342 ` 2343 resp, err := Parse(Request{Str: query}) 2344 require.NoError(t, err) 2345 require.Equal(t, "[-1.12,2.0123]", resp.Query[0].Children[0].Filter.Func.Args[0].Value) 2346 require.Equal(t, "100.123", resp.Query[0].Children[0].Filter.Func.Args[1].Value) 2347 require.Equal(t, false, resp.Query[0].Children[0].Filter.Func.Args[0].IsValueVar) 2348 require.Equal(t, false, resp.Query[0].Children[0].Filter.Func.Args[1].IsValueVar) 2349 } 2350 2351 func TestParseFilter_Geo2(t *testing.T) { 2352 query := ` 2353 query { 2354 me(func: uid(0x0a)) { 2355 friends @filter(within(loc, [[11.2 , -2.234 ], [ -31.23, 4.3214] , [5.312, 6.53]] )) { 2356 name 2357 } 2358 gender,age 2359 hometown 2360 } 2361 } 2362 ` 2363 resp, err := Parse(Request{Str: query}) 2364 require.NoError(t, err) 2365 require.Equal(t, "[[11.2,-2.234],[-31.23,4.3214],[5.312,6.53]]", resp.Query[0].Children[0].Filter.Func.Args[0].Value) 2366 } 2367 2368 func TestParseFilter_Geo3(t *testing.T) { 2369 query := ` 2370 query { 2371 me(func: uid(0x0a)) { 2372 friends @filter(near(loc, [[1 , 2 ], [[3, 4] , [5, 6]] )) { 2373 name 2374 } 2375 gender,age 2376 hometown 2377 } 2378 } 2379 ` 2380 _, err := Parse(Request{Str: query}) 2381 require.Error(t, err) 2382 require.Contains(t, err.Error(), "Found invalid item") 2383 } 2384 2385 func TestParseFilter_Geo4(t *testing.T) { 2386 query := ` 2387 query { 2388 me(func: uid(0x0a)) { 2389 friends @filter(near(loc, [[1 , 2 ], [3, 4] , [5, 6]]] )) { 2390 name 2391 } 2392 gender,age 2393 hometown 2394 } 2395 } 2396 ` 2397 _, err := Parse(Request{Str: query}) 2398 require.Error(t, err) 2399 require.Contains(t, err.Error(), "Expected right round or comma") 2400 require.Contains(t, err.Error(), "\"]\"") 2401 } 2402 2403 // Test if empty brackets will lead to errors. 2404 func TestParseFilter_emptyargument(t *testing.T) { 2405 query := ` 2406 query { 2407 me(func: uid(0x0a)) { 2408 friends @filter(allofterms(name,,)) { 2409 name 2410 } 2411 gender,age 2412 hometown 2413 } 2414 } 2415 ` 2416 _, err := Parse(Request{Str: query}) 2417 require.Error(t, err) 2418 require.Contains(t, err.Error(), "Consecutive commas not allowed") 2419 2420 } 2421 2422 func TestParseFilter_unknowndirectiveError1(t *testing.T) { 2423 query := ` 2424 query { 2425 me(func: uid(0x0a)) { 2426 friends @filtererr { 2427 name 2428 } 2429 gender,age 2430 hometown 2431 } 2432 }` 2433 _, err := Parse(Request{Str: query}) 2434 require.Error(t, err) 2435 // We can't differentiate between @filtererr being a directive or a language. As we don't 2436 // see a () after it we assume its a language but attr which specify a language can't have 2437 // children. 2438 // The test below tests for unknown directive. 2439 require.Contains(t, err.Error(), "Cannot have children for attr: friends with lang tags:") 2440 } 2441 2442 func TestParseFilter_unknowndirectiveError2(t *testing.T) { 2443 query := ` 2444 query { 2445 me(func: uid(0x0a)) { 2446 friends @filtererr () 2447 gender,age 2448 hometown 2449 } 2450 }` 2451 _, err := Parse(Request{Str: query}) 2452 require.Error(t, err) 2453 require.Contains(t, err.Error(), "Unknown directive [filtererr]") 2454 } 2455 2456 func TestParseGeneratorError1(t *testing.T) { 2457 query := `{ 2458 me(allofterms(name, "barack")) { 2459 friends { 2460 name 2461 } 2462 gender,age 2463 hometown 2464 count(friends) 2465 } 2466 } 2467 ` 2468 _, err := Parse(Request{Str: query}) 2469 require.Error(t, err) 2470 require.Contains(t, err.Error(), "Got invalid keyword: allofterms") 2471 } 2472 2473 func TestParseGeneratorError2(t *testing.T) { 2474 query := `{ 2475 me(func: allofterms(name, "barack")) { 2476 friends(all: 5) { 2477 name 2478 } 2479 gender,age 2480 hometown 2481 count(friends) 2482 } 2483 } 2484 ` 2485 _, err := Parse(Request{Str: query}) 2486 require.Error(t, err) 2487 require.Contains(t, err.Error(), "Got invalid keyword: all") 2488 } 2489 2490 func TestParseQuotedFunctionAttributeError(t *testing.T) { 2491 query := `{ 2492 me(func: allofterms("name", "barack")) { 2493 friends { 2494 name 2495 } 2496 gender,age 2497 hometown 2498 count(friends) 2499 } 2500 } 2501 ` 2502 _, err := Parse(Request{Str: query}) 2503 require.Error(t, err) 2504 require.Contains(t, err.Error(), "Attribute in function must not be quoted") 2505 } 2506 2507 func TestParseCountAsFuncMultiple(t *testing.T) { 2508 query := `{ 2509 me(func: uid(1)) { 2510 count(friends), count(relatives) 2511 count(classmates) 2512 gender,age 2513 hometown 2514 } 2515 } 2516 ` 2517 gq, err := Parse(Request{Str: query}) 2518 require.NoError(t, err) 2519 require.Equal(t, 6, len(gq.Query[0].Children)) 2520 require.Equal(t, true, gq.Query[0].Children[0].IsCount) 2521 require.Equal(t, "friends", gq.Query[0].Children[0].Attr) 2522 require.Equal(t, true, gq.Query[0].Children[1].IsCount) 2523 require.Equal(t, "relatives", gq.Query[0].Children[1].Attr) 2524 require.Equal(t, true, gq.Query[0].Children[2].IsCount) 2525 require.Equal(t, "classmates", gq.Query[0].Children[2].Attr) 2526 } 2527 2528 func TestParseCountAsFuncMultipleError(t *testing.T) { 2529 query := `{ 2530 me(func: uid(1)) { 2531 count(friends, relatives 2532 classmates) 2533 gender,age 2534 hometown 2535 } 2536 } 2537 ` 2538 _, err := Parse(Request{Str: query}) 2539 require.Error(t, err) 2540 require.Contains(t, err.Error(), "Multiple predicates not allowed in single count") 2541 } 2542 2543 func TestParseCountAsFunc(t *testing.T) { 2544 query := `{ 2545 me(func: uid(1)) { 2546 count(friends) 2547 gender,age 2548 hometown 2549 } 2550 } 2551 ` 2552 gq, err := Parse(Request{Str: query}) 2553 require.NoError(t, err) 2554 require.Equal(t, true, gq.Query[0].Children[0].IsCount) 2555 require.Equal(t, 4, len(gq.Query[0].Children)) 2556 2557 } 2558 2559 func TestParseCountError1(t *testing.T) { 2560 query := `{ 2561 me(func: uid(1)) { 2562 count(friends 2563 gender,age 2564 hometown 2565 } 2566 } 2567 ` 2568 _, err := Parse(Request{Str: query}) 2569 require.Error(t, err) 2570 require.Contains(t, err.Error(), 2571 "Unrecognized character inside a func: U+007D '}'") 2572 } 2573 2574 func TestParseCountError2(t *testing.T) { 2575 query := `{ 2576 me(func: uid(1)) { 2577 count((friends) 2578 gender,age 2579 hometown 2580 } 2581 } 2582 ` 2583 _, err := Parse(Request{Str: query}) 2584 require.Error(t, err) 2585 require.Contains(t, err.Error(), 2586 "Unrecognized character inside a func: U+007D '}'") 2587 } 2588 2589 func TestParseCheckPwd(t *testing.T) { 2590 2591 query := `{ 2592 me(func: uid(1)) { 2593 checkpwd(password, "123456") 2594 hometown 2595 } 2596 } 2597 ` 2598 gq, err := Parse(Request{Str: query}) 2599 require.NoError(t, err) 2600 require.Equal(t, "checkpwd", gq.Query[0].Children[0].Func.Name) 2601 require.Equal(t, "123456", gq.Query[0].Children[0].Func.Args[0].Value) 2602 require.Equal(t, "password", gq.Query[0].Children[0].Attr) 2603 } 2604 2605 func TestParseComments(t *testing.T) { 2606 query := ` 2607 # Something 2608 { 2609 me(func:allofterms(name, "barack")) { 2610 friends { 2611 name 2612 } # Something 2613 gender,age 2614 hometown 2615 } 2616 } 2617 ` 2618 _, err := Parse(Request{Str: query}) 2619 require.NoError(t, err) 2620 } 2621 2622 func TestParseComments1(t *testing.T) { 2623 query := `{ 2624 #Something 2625 me(func:allofterms(name, "barack")) { 2626 friends { 2627 name # Name of my friend 2628 } 2629 gender,age 2630 hometown 2631 } 2632 } 2633 ` 2634 _, err := Parse(Request{Str: query}) 2635 require.NoError(t, err) 2636 } 2637 2638 func TestParseGenerator(t *testing.T) { 2639 query := `{ 2640 me(func:allofterms(name, "barack")) { 2641 friends { 2642 name 2643 } 2644 gender,age 2645 hometown 2646 } 2647 } 2648 ` 2649 _, err := Parse(Request{Str: query}) 2650 require.NoError(t, err) 2651 } 2652 2653 func TestParseIRIRef(t *testing.T) { 2654 query := `{ 2655 me(func: uid( 0x1)) { 2656 <http://verygood.com/what/about/you> 2657 friends @filter(allofterms(<http://verygood.com/what/about/you>, 2658 "good better bad")){ 2659 name 2660 } 2661 gender,age 2662 hometown 2663 } 2664 }` 2665 2666 gq, err := Parse(Request{Str: query}) 2667 require.NoError(t, err) 2668 require.Equal(t, 5, len(gq.Query[0].Children)) 2669 require.Equal(t, "http://verygood.com/what/about/you", gq.Query[0].Children[0].Attr) 2670 require.Equal(t, `(allofterms http://verygood.com/what/about/you "good better bad")`, 2671 gq.Query[0].Children[1].Filter.debugString()) 2672 } 2673 2674 func TestParseIRIRef2(t *testing.T) { 2675 query := `{ 2676 me(func:anyofterms(<http://helloworld.com/how/are/you>, "good better bad")) { 2677 <http://verygood.com/what/about/you> 2678 friends @filter(allofterms(<http://verygood.com/what/about/you>, 2679 "good better bad")){ 2680 name 2681 } 2682 } 2683 }` 2684 2685 gq, err := Parse(Request{Str: query}) 2686 require.NoError(t, err) 2687 require.Equal(t, 2, len(gq.Query[0].Children)) 2688 require.Equal(t, "http://verygood.com/what/about/you", gq.Query[0].Children[0].Attr) 2689 require.Equal(t, `(allofterms http://verygood.com/what/about/you "good better bad")`, 2690 gq.Query[0].Children[1].Filter.debugString()) 2691 require.Equal(t, "http://helloworld.com/how/are/you", gq.Query[0].Func.Attr) 2692 } 2693 2694 func TestParseIRIRefSpace(t *testing.T) { 2695 query := `{ 2696 me(func: uid( <http://helloworld.com/how/are/ you>)) { 2697 } 2698 }` 2699 2700 _, err := Parse(Request{Str: query}) 2701 require.Error(t, err) // because of space. 2702 require.Contains(t, err.Error(), "Unexpected character ' ' while parsing IRI") 2703 } 2704 2705 func TestParseIRIRefInvalidChar(t *testing.T) { 2706 query := `{ 2707 me(func: uid( <http://helloworld.com/how/are/^you>)) { 2708 } 2709 }` 2710 2711 _, err := Parse(Request{Str: query}) 2712 require.Error(t, err) // because of ^ 2713 require.Contains(t, err.Error(), "Unexpected character '^' while parsing IRI") 2714 } 2715 2716 func TestLangs(t *testing.T) { 2717 query := ` 2718 query { 2719 me(func: uid(1)) { 2720 name@en,name@en:ru:hu 2721 } 2722 } 2723 ` 2724 2725 gq, err := Parse(Request{Str: query}) 2726 require.NoError(t, err) 2727 require.Equal(t, 2, len(gq.Query[0].Children)) 2728 require.Equal(t, "name", gq.Query[0].Children[0].Attr) 2729 require.Equal(t, []string{"en"}, gq.Query[0].Children[0].Langs) 2730 require.Equal(t, "name", gq.Query[0].Children[1].Attr) 2731 require.Equal(t, []string{"en", "ru", "hu"}, gq.Query[0].Children[1].Langs) 2732 } 2733 2734 func TestAllLangs(t *testing.T) { 2735 query := ` 2736 query { 2737 me(func: uid(1)) { 2738 name@* 2739 } 2740 } 2741 ` 2742 2743 gq, err := Parse(Request{Str: query}) 2744 require.NoError(t, err) 2745 require.Equal(t, 1, len(gq.Query[0].Children)) 2746 require.Equal(t, "name", gq.Query[0].Children[0].Attr) 2747 require.Equal(t, []string{"*"}, gq.Query[0].Children[0].Langs) 2748 } 2749 2750 func TestLangsInvalid1(t *testing.T) { 2751 query := ` 2752 query { 2753 me(func: uid(1)) { 2754 name@en@ru 2755 } 2756 } 2757 ` 2758 2759 _, err := Parse(Request{Str: query}) 2760 require.Error(t, err) 2761 require.Contains(t, err.Error(), "Expected directive or language list, got @ru") 2762 } 2763 2764 func TestLangsInvalid2(t *testing.T) { 2765 query := ` 2766 query { 2767 me(func: uid(1)) { 2768 @en:ru 2769 } 2770 } 2771 ` 2772 2773 _, err := Parse(Request{Str: query}) 2774 require.Error(t, err) 2775 require.Contains(t, err.Error(), "Invalid use of directive.") 2776 } 2777 2778 func TestLangsInvalid3(t *testing.T) { 2779 query := ` 2780 query { 2781 me(func: uid(1)) { 2782 name@en:ru, @en:ru 2783 } 2784 } 2785 ` 2786 2787 _, err := Parse(Request{Str: query}) 2788 require.Error(t, err) 2789 require.Contains(t, err.Error(), "Expected directive or language list, got @en") 2790 } 2791 2792 func TestLangsInvalid4(t *testing.T) { 2793 query := ` 2794 query { 2795 me(func: uid(1)) { 2796 name@ 2797 } 2798 } 2799 ` 2800 2801 _, err := Parse(Request{Str: query}) 2802 require.Error(t, err) 2803 require.Contains(t, err.Error(), 2804 "Unrecognized character in lexDirective: U+000A") 2805 } 2806 2807 func TestLangsInvalid5(t *testing.T) { 2808 query := ` 2809 query { 2810 me(func: uid(1)) { 2811 name@<something.wrong> 2812 } 2813 } 2814 ` 2815 2816 _, err := Parse(Request{Str: query}) 2817 require.Error(t, err) 2818 require.Contains(t, err.Error(), 2819 "Unrecognized character in lexDirective: U+003C '<'") 2820 } 2821 2822 func TestLangsInvalid6(t *testing.T) { 2823 query := ` 2824 { 2825 me(func: uid(0x1004)) { 2826 name@hi:cn:... 2827 } 2828 } 2829 ` 2830 2831 _, err := Parse(Request{Str: query}) 2832 require.Error(t, err) 2833 require.Contains(t, err.Error(), "Expected only one dot(.) while parsing language list.") 2834 } 2835 2836 func TestLangsInvalid7(t *testing.T) { 2837 query := ` 2838 { 2839 me(func: uid(0x1004)) { 2840 name@... 2841 } 2842 } 2843 ` 2844 2845 _, err := Parse(Request{Str: query}) 2846 require.Error(t, err) 2847 require.Contains(t, err.Error(), "Expected only one dot(.) while parsing language list.") 2848 } 2849 2850 func TestLangsInvalid8(t *testing.T) { 2851 query := ` 2852 query { 2853 me(func: uid(1)) { 2854 name@*:en 2855 } 2856 } 2857 ` 2858 2859 _, err := Parse(Request{Str: query}) 2860 require.Error(t, err) 2861 require.Contains(t, err.Error(), 2862 "If * is used, no other languages are allowed in the language list") 2863 } 2864 2865 func TestLangsInvalid9(t *testing.T) { 2866 query := ` 2867 query { 2868 me(func: eqs(name@*, "Amir")) { 2869 name@en 2870 } 2871 } 2872 ` 2873 2874 _, err := Parse(Request{Str: query}) 2875 require.Error(t, err) 2876 require.Contains(t, err.Error(), 2877 "The * symbol cannot be used as a valid language inside functions") 2878 } 2879 2880 func TestLangsFilter(t *testing.T) { 2881 query := ` 2882 query { 2883 me(func: uid(0x0a)) { 2884 friends @filter(alloftext(descr@en, "something")) { 2885 name 2886 } 2887 gender,age 2888 hometown 2889 } 2890 } 2891 ` 2892 res, err := Parse(Request{Str: query}) 2893 require.NoError(t, err) 2894 require.NotNil(t, res.Query[0]) 2895 require.NotNil(t, res.Query[0].Children[0]) 2896 require.NotNil(t, res.Query[0].Children[0].Filter) 2897 require.NotNil(t, res.Query[0].Children[0].Filter.Func) 2898 require.Equal(t, "descr", res.Query[0].Children[0].Filter.Func.Attr) 2899 require.Equal(t, "en", res.Query[0].Children[0].Filter.Func.Lang) 2900 } 2901 2902 func TestLangsFilter_error1(t *testing.T) { 2903 // this query should fail, because '@lang' is used twice (and only one appearance is allowed) 2904 query := ` 2905 query { 2906 me(func: uid(0x0a)) { 2907 friends @filter(alloftext(descr@en@de, "something")) { 2908 name 2909 } 2910 gender,age 2911 hometown 2912 } 2913 } 2914 ` 2915 _, err := Parse(Request{Str: query}) 2916 require.Error(t, err) 2917 require.Contains(t, err.Error(), "Invalid usage of '@' in function argument") 2918 } 2919 2920 func TestLangsFilter_error2(t *testing.T) { 2921 // this query should fail, because there is no lang after '@' 2922 query := ` 2923 query { 2924 me(func: uid(0x0a)) { 2925 friends @filter(alloftext(descr@, "something")) { 2926 name 2927 } 2928 gender,age 2929 hometown 2930 } 2931 } 2932 ` 2933 _, err := Parse(Request{Str: query}) 2934 require.Error(t, err) 2935 require.Contains(t, err.Error(), 2936 "Unrecognized character in lexDirective: U+002C ','") 2937 } 2938 2939 func TestLangsFunction(t *testing.T) { 2940 query := ` 2941 query { 2942 me(func:alloftext(descr@en, "something")) { 2943 friends { 2944 name 2945 } 2946 gender,age 2947 hometown 2948 } 2949 } 2950 ` 2951 res, err := Parse(Request{Str: query}) 2952 require.NoError(t, err) 2953 require.NotNil(t, res.Query[0]) 2954 require.NotNil(t, res.Query[0].Func) 2955 require.Equal(t, "descr", res.Query[0].Func.Attr) 2956 require.Equal(t, "en", res.Query[0].Func.Lang) 2957 } 2958 2959 func TestLangsFunctionMultipleLangs(t *testing.T) { 2960 query := ` 2961 query { 2962 me(func:alloftext(descr@hi:en, "something")) { 2963 friends { 2964 name 2965 } 2966 gender,age 2967 hometown 2968 } 2969 } 2970 ` 2971 _, err := Parse(Request{Str: query}) 2972 require.Error(t, err) 2973 require.Contains(t, err.Error(), "Expected arg after func [alloftext]") 2974 require.Contains(t, err.Error(), "\":\"") 2975 } 2976 2977 func TestParseNormalize(t *testing.T) { 2978 query := ` 2979 query { 2980 me(func: uid( 0x3)) @normalize { 2981 friends { 2982 name 2983 } 2984 gender 2985 hometown 2986 } 2987 } 2988 ` 2989 res, err := Parse(Request{Str: query}) 2990 require.NoError(t, err) 2991 require.NotNil(t, res.Query[0]) 2992 require.True(t, res.Query[0].Normalize) 2993 } 2994 2995 func TestParseGroupbyRoot(t *testing.T) { 2996 query := ` 2997 query { 2998 me(func: uid(1, 2, 3)) @groupby(friends) { 2999 a as count(uid) 3000 } 3001 3002 groups(func: uid(a)) { 3003 uid 3004 val(a) 3005 } 3006 } 3007 ` 3008 res, err := Parse(Request{Str: query}) 3009 require.NoError(t, err) 3010 require.Equal(t, 1, len(res.Query[0].GroupbyAttrs)) 3011 require.Equal(t, "friends", res.Query[0].GroupbyAttrs[0].Attr) 3012 require.Equal(t, "a", res.Query[0].Children[0].Var) 3013 } 3014 3015 func TestParseGroupbyWithCountVar(t *testing.T) { 3016 query := ` 3017 query { 3018 me(func: uid(0x1)) { 3019 friends @groupby(friends) { 3020 a as count(uid) 3021 } 3022 hometown 3023 age 3024 } 3025 3026 groups(func: uid(a)) { 3027 uid 3028 val(a) 3029 } 3030 } 3031 ` 3032 res, err := Parse(Request{Str: query}) 3033 require.NoError(t, err) 3034 require.Equal(t, 1, len(res.Query[0].Children[0].GroupbyAttrs)) 3035 require.Equal(t, "friends", res.Query[0].Children[0].GroupbyAttrs[0].Attr) 3036 require.Equal(t, "a", res.Query[0].Children[0].Children[0].Var) 3037 } 3038 3039 func TestParseGroupbyWithMaxVar(t *testing.T) { 3040 query := ` 3041 query { 3042 me(func: uid(0x1)) { 3043 friends @groupby(friends) { 3044 a as max(first-name@en:ta) 3045 } 3046 hometown 3047 age 3048 } 3049 3050 groups(func: uid(a)) { 3051 uid 3052 val(a) 3053 } 3054 } 3055 ` 3056 res, err := Parse(Request{Str: query}) 3057 require.NoError(t, err) 3058 require.Equal(t, 1, len(res.Query[0].Children[0].GroupbyAttrs)) 3059 require.Equal(t, "friends", res.Query[0].Children[0].GroupbyAttrs[0].Attr) 3060 require.Equal(t, "first-name", res.Query[0].Children[0].Children[0].Attr) 3061 require.Equal(t, []string{"en", "ta"}, res.Query[0].Children[0].Children[0].Langs) 3062 require.Equal(t, "a", res.Query[0].Children[0].Children[0].Var) 3063 } 3064 3065 func TestParseGroupby(t *testing.T) { 3066 query := ` 3067 query { 3068 me(func: uid(0x1)) { 3069 friends @groupby(name@en) { 3070 count(uid) 3071 } 3072 hometown 3073 age 3074 } 3075 } 3076 ` 3077 res, err := Parse(Request{Str: query}) 3078 require.NoError(t, err) 3079 require.Equal(t, 1, len(res.Query[0].Children[0].GroupbyAttrs)) 3080 require.Equal(t, "name", res.Query[0].Children[0].GroupbyAttrs[0].Attr) 3081 require.Equal(t, "en", res.Query[0].Children[0].GroupbyAttrs[0].Langs[0]) 3082 } 3083 3084 func TestParseGroupbyWithAlias(t *testing.T) { 3085 query := ` 3086 query { 3087 me(func: uid(0x1)) { 3088 friends @groupby(name) { 3089 GroupCount: count(uid) 3090 } 3091 hometown 3092 age 3093 } 3094 } 3095 ` 3096 res, err := Parse(Request{Str: query}) 3097 require.NoError(t, err) 3098 require.Equal(t, 1, len(res.Query[0].Children[0].GroupbyAttrs)) 3099 require.Equal(t, "name", res.Query[0].Children[0].GroupbyAttrs[0].Attr) 3100 require.Equal(t, "GroupCount", res.Query[0].Children[0].Children[0].Alias) 3101 } 3102 3103 func TestParseGroupbyWithAliasForKey(t *testing.T) { 3104 query := ` 3105 query { 3106 me(func: uid(0x1)) { 3107 friends @groupby(Name: name, SchooL: school) { 3108 count(uid) 3109 } 3110 hometown 3111 age 3112 } 3113 } 3114 ` 3115 res, err := Parse(Request{Str: query}) 3116 require.NoError(t, err) 3117 require.Equal(t, 2, len(res.Query[0].Children[0].GroupbyAttrs)) 3118 require.Equal(t, "Name", res.Query[0].Children[0].GroupbyAttrs[0].Alias) 3119 require.Equal(t, "SchooL", res.Query[0].Children[0].GroupbyAttrs[1].Alias) 3120 } 3121 3122 func TestParseGroupbyError(t *testing.T) { 3123 // predicates not allowed inside groupby. 3124 query := ` 3125 query { 3126 me(func: uid(0x1)) { 3127 friends @groupby(name) { 3128 name 3129 count(uid) 3130 } 3131 hometown 3132 age 3133 } 3134 } 3135 ` 3136 _, err := Parse(Request{Str: query}) 3137 require.Error(t, err) 3138 require.Contains(t, err.Error(), "Only aggregator/count functions allowed inside @groupby") 3139 } 3140 3141 func TestParseFacetsError1(t *testing.T) { 3142 query := ` 3143 query { 3144 me(func: uid(0x1)) { 3145 friends @facets { 3146 name @facets(facet1,, facet2) 3147 } 3148 hometown 3149 age 3150 } 3151 } 3152 ` 3153 _, err := Parse(Request{Str: query}) 3154 require.Error(t, err) 3155 require.Contains(t, err.Error(), 3156 "Consecutive commas not allowed.") 3157 } 3158 3159 func TestParseFacetsVarError(t *testing.T) { 3160 query := ` 3161 query { 3162 me(func: uid(0x1)) { 3163 friends @facets { 3164 name @facets(facet1, b as) 3165 } 3166 hometown 3167 age 3168 } 3169 } 3170 ` 3171 _, err := Parse(Request{Str: query}) 3172 require.Error(t, err) 3173 require.Contains(t, err.Error(), "Expected name in facet list") 3174 } 3175 func TestParseFacetsError2(t *testing.T) { 3176 query := ` 3177 query { 3178 me(func: uid(0x1)) { 3179 friends @facets { 3180 name @facets(facet1 facet2) 3181 } 3182 hometown 3183 age 3184 } 3185 } 3186 ` 3187 _, err := Parse(Request{Str: query}) 3188 require.Error(t, err) 3189 require.Contains(t, err.Error(), "Expected ( after func name [facet1]") 3190 } 3191 3192 func TestParseFacetsOrderError1(t *testing.T) { 3193 query := ` 3194 query { 3195 me(func: uid(0x1)) { 3196 friends @facets(orderdesc: orderdesc: closeness) { 3197 name 3198 } 3199 } 3200 } 3201 ` 3202 _, err := Parse(Request{Str: query}) 3203 require.Error(t, err) 3204 require.Contains(t, err.Error(), "Expected ( after func name [orderdesc]") 3205 } 3206 3207 func TestParseFacetsOrderError2(t *testing.T) { 3208 query := ` 3209 query { 3210 me(func: uid(0x1)) { 3211 friends @facets(a as b as closeness) { 3212 name 3213 } 3214 } 3215 } 3216 ` 3217 _, err := Parse(Request{Str: query}) 3218 require.Error(t, err) 3219 require.Contains(t, err.Error(), "Expected ( after func name [a]") 3220 } 3221 3222 func TestParseFacetsOrderWithAlias(t *testing.T) { 3223 query := ` 3224 query { 3225 me(func: uid(0x1)) { 3226 friends @facets(orderdesc: closeness, b as some, order: abc, key, key1: val, abcd) { 3227 val(b) 3228 } 3229 } 3230 } 3231 ` 3232 res, err := Parse(Request{Str: query}) 3233 require.NoError(t, err) 3234 node := res.Query[0].Children[0].Facets 3235 require.Equal(t, 6, len(node.Param)) 3236 require.Equal(t, "order", node.Param[0].Alias) 3237 require.Equal(t, "abc", node.Param[0].Key) 3238 require.Equal(t, "abcd", node.Param[1].Key) 3239 require.Equal(t, "val", node.Param[5].Key) 3240 require.Equal(t, "key1", node.Param[5].Alias) 3241 } 3242 3243 func TestParseFacetsDuplicateVarError(t *testing.T) { 3244 query := ` 3245 query { 3246 me(func: uid(0x1)) { 3247 friends @facets(a as closeness, b as closeness) { 3248 name 3249 } 3250 } 3251 } 3252 ` 3253 _, err := Parse(Request{Str: query}) 3254 require.Error(t, err) 3255 require.Contains(t, err.Error(), "Duplicate variable mappings") 3256 } 3257 3258 func TestParseFacetsOrderVar(t *testing.T) { 3259 query := ` 3260 query { 3261 me1(func: uid(0x1)) { 3262 friends @facets(orderdesc: a as b) { 3263 name 3264 } 3265 } 3266 me2(func: uid(a)) { } 3267 } 3268 ` 3269 _, err := Parse(Request{Str: query}) 3270 require.NoError(t, err) 3271 } 3272 3273 func TestParseFacetsOrderVar2(t *testing.T) { 3274 query := ` 3275 query { 3276 me(func: uid(0x1)) { 3277 friends @facets(a as orderdesc: b) { 3278 name 3279 } 3280 } 3281 me(func: uid(a)) { 3282 3283 } 3284 } 3285 ` 3286 _, err := Parse(Request{Str: query}) 3287 require.Error(t, err) 3288 require.Contains(t, err.Error(), "Expected ( after func name [a]") 3289 } 3290 3291 func TestParseFacets(t *testing.T) { 3292 query := ` 3293 query { 3294 me(func: uid(0x1)) { 3295 friends @facets(orderdesc: closeness) { 3296 name 3297 } 3298 } 3299 } 3300 ` 3301 res, err := Parse(Request{Str: query}) 3302 require.NoError(t, err) 3303 require.NotNil(t, res.Query[0]) 3304 require.Equal(t, []string{"friends"}, childAttrs(res.Query[0])) 3305 require.NotNil(t, res.Query[0].Children[0].Facets) 3306 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 3307 require.Equal(t, "closeness", res.Query[0].Children[0].FacetOrder) 3308 require.True(t, res.Query[0].Children[0].FacetDesc) 3309 } 3310 3311 func TestParseOrderbyFacet(t *testing.T) { 3312 query := ` 3313 query { 3314 me(func: uid(0x1)) { 3315 friends @facets { 3316 name @facets(facet1) 3317 } 3318 hometown 3319 age 3320 } 3321 } 3322 ` 3323 res, err := Parse(Request{Str: query}) 3324 require.NoError(t, err) 3325 require.NotNil(t, res.Query[0]) 3326 require.Equal(t, []string{"friends", "hometown", "age"}, childAttrs(res.Query[0])) 3327 require.NotNil(t, res.Query[0].Children[0].Facets) 3328 require.Equal(t, true, res.Query[0].Children[0].Facets.AllKeys) 3329 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 3330 require.NotNil(t, res.Query[0].Children[0].Children[0].Facets) 3331 require.Equal(t, false, res.Query[0].Children[0].Children[0].Facets.AllKeys) 3332 require.Equal(t, "facet1", res.Query[0].Children[0].Children[0].Facets.Param[0].Key) 3333 } 3334 3335 func TestParseFacetsMultiple(t *testing.T) { 3336 query := ` 3337 query { 3338 me(func: uid(0x1)) { 3339 friends @facets { 3340 name @facets(key1, key2, key3) 3341 } 3342 hometown 3343 age 3344 } 3345 } 3346 ` 3347 res, err := Parse(Request{Str: query}) 3348 require.NoError(t, err) 3349 require.NotNil(t, res.Query[0]) 3350 require.Equal(t, []string{"friends", "hometown", "age"}, childAttrs(res.Query[0])) 3351 require.NotNil(t, res.Query[0].Children[0].Facets) 3352 require.Equal(t, true, res.Query[0].Children[0].Facets.AllKeys) 3353 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 3354 require.NotNil(t, res.Query[0].Children[0].Children[0].Facets) 3355 require.Equal(t, false, res.Query[0].Children[0].Children[0].Facets.AllKeys) 3356 require.Equal(t, 3, len(res.Query[0].Children[0].Children[0].Facets.Param)) 3357 } 3358 3359 func TestParseFacetsAlias(t *testing.T) { 3360 query := ` 3361 query { 3362 me(func: uid(0x1)) { 3363 friends @facets { 3364 name @facets(a1: key1, a2: key2, a3: key3) 3365 } 3366 } 3367 } 3368 ` 3369 res, err := Parse(Request{Str: query}) 3370 require.NoError(t, err) 3371 require.NotNil(t, res.Query[0]) 3372 3373 require.NotNil(t, res.Query[0].Children[0].Facets) 3374 require.Equal(t, true, res.Query[0].Children[0].Facets.AllKeys) 3375 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 3376 require.NotNil(t, res.Query[0].Children[0].Children[0].Facets) 3377 3378 node := res.Query[0].Children[0].Children[0].Facets 3379 require.Equal(t, false, node.AllKeys) 3380 require.Equal(t, 3, len(node.Param)) 3381 require.Equal(t, "a1", node.Param[0].Alias) 3382 require.Equal(t, "key1", node.Param[0].Key) 3383 require.Equal(t, "a3", node.Param[2].Alias) 3384 require.Equal(t, "key3", node.Param[2].Key) 3385 } 3386 3387 func TestParseFacetsMultipleVar(t *testing.T) { 3388 query := ` 3389 query { 3390 me(func: uid(0x1)) { 3391 friends @facets { 3392 name @facets(a as key1, key2, b as key3) 3393 } 3394 hometown 3395 age 3396 } 3397 h(func: uid(a, b)) { 3398 uid 3399 } 3400 } 3401 ` 3402 res, err := Parse(Request{Str: query}) 3403 require.NoError(t, err) 3404 require.NotNil(t, res.Query[0]) 3405 require.Equal(t, []string{"friends", "hometown", "age"}, childAttrs(res.Query[0])) 3406 require.NotNil(t, res.Query[0].Children[0].Facets) 3407 require.Equal(t, true, res.Query[0].Children[0].Facets.AllKeys) 3408 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 3409 require.NotNil(t, res.Query[0].Children[0].Children[0].Facets) 3410 require.Equal(t, false, res.Query[0].Children[0].Children[0].Facets.AllKeys) 3411 require.Equal(t, 3, len(res.Query[0].Children[0].Children[0].Facets.Param)) 3412 require.Equal(t, "a", res.Query[0].Children[0].Children[0].FacetVar["key1"]) 3413 require.Equal(t, "", res.Query[0].Children[0].Children[0].FacetVar["key2"]) 3414 require.Equal(t, "b", res.Query[0].Children[0].Children[0].FacetVar["key3"]) 3415 } 3416 3417 func TestParseFacetsMultipleRepeat(t *testing.T) { 3418 query := ` 3419 query { 3420 me(func: uid(0x1)) { 3421 friends @facets { 3422 name @facets(key1, key2, key3, key1) 3423 } 3424 hometown 3425 age 3426 } 3427 } 3428 ` 3429 res, err := Parse(Request{Str: query}) 3430 require.NoError(t, err) 3431 require.NotNil(t, res.Query[0]) 3432 require.Equal(t, []string{"friends", "hometown", "age"}, childAttrs(res.Query[0])) 3433 require.NotNil(t, res.Query[0].Children[0].Facets) 3434 require.Equal(t, true, res.Query[0].Children[0].Facets.AllKeys) 3435 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 3436 require.NotNil(t, res.Query[0].Children[0].Children[0].Facets) 3437 require.Equal(t, false, res.Query[0].Children[0].Children[0].Facets.AllKeys) 3438 require.Equal(t, 3, len(res.Query[0].Children[0].Children[0].Facets.Param)) 3439 } 3440 3441 func TestParseFacetsEmpty(t *testing.T) { 3442 query := ` 3443 query { 3444 me(func: uid(0x1)) { 3445 friends @facets() { 3446 } 3447 hometown 3448 age 3449 } 3450 } 3451 ` 3452 res, err := Parse(Request{Str: query}) 3453 require.NoError(t, err) 3454 require.NotNil(t, res.Query[0]) 3455 require.Equal(t, []string{"friends", "hometown", "age"}, childAttrs(res.Query[0])) 3456 require.NotNil(t, res.Query[0].Children[0].Facets) 3457 require.Equal(t, false, res.Query[0].Children[0].Facets.AllKeys) 3458 require.Equal(t, 0, len(res.Query[0].Children[0].Facets.Param)) 3459 } 3460 3461 func TestParseFacetsFail1(t *testing.T) { 3462 // key can not be empty.. 3463 query := ` 3464 query { 3465 me(func: uid(0x1)) { 3466 friends @facets(key1,, key2) { 3467 } 3468 hometown 3469 age 3470 } 3471 } 3472 ` 3473 _, err := Parse(Request{Str: query}) 3474 require.Error(t, err) 3475 require.Contains(t, err.Error(), 3476 "Consecutive commas not allowed.") 3477 } 3478 3479 func TestParseRepeatArgsError1(t *testing.T) { 3480 // key can not be empty.. 3481 query := ` 3482 { 3483 me(func: anyoftext(Text, "biology"), func: anyoftext(Text, "science")) { 3484 Text 3485 } 3486 } 3487 ` 3488 _, err := Parse(Request{Str: query}) 3489 require.Error(t, err) 3490 require.Contains(t, err.Error(), "Only one function allowed at root") 3491 } 3492 3493 func TestParseRepeatArgsError2(t *testing.T) { 3494 // key can not be empty.. 3495 query := ` 3496 { 3497 me(func: anyoftext(Text, "science")) { 3498 Text(first: 1, first: 4) 3499 } 3500 } 3501 ` 3502 _, err := Parse(Request{Str: query}) 3503 require.Error(t, err) 3504 require.Contains(t, err.Error(), "Got repeated key \"first\"") 3505 } 3506 3507 // Test facets parsing for filtering.. 3508 func TestFacetsFilterSimple(t *testing.T) { 3509 // all friends of 0x1 who are close to him 3510 query := ` 3511 { 3512 me(func: uid(0x1)) { 3513 name 3514 friend @facets(eq(close, true)) { 3515 name 3516 gender 3517 } 3518 } 3519 } 3520 ` 3521 3522 res, err := Parse(Request{Str: query}) 3523 require.NoError(t, err) 3524 require.NotNil(t, res.Query[0]) 3525 require.Equal(t, []string{"name", "friend"}, childAttrs(res.Query[0])) 3526 require.Nil(t, res.Query[0].Children[1].Facets) 3527 require.NotNil(t, res.Query[0].Children[1].FacetsFilter) 3528 require.Equal(t, `(eq close "true")`, 3529 res.Query[0].Children[1].FacetsFilter.debugString()) 3530 } 3531 3532 func TestFacetsFilterAll(t *testing.T) { 3533 // all friends of 0x1 who are close to him or are in his family 3534 query := ` 3535 { 3536 me(func: uid(0x1)) { 3537 name 3538 friend @facets(eq(close, true) or eq(family, true)) @facets(close, family, since) { 3539 name @facets 3540 gender 3541 } 3542 } 3543 } 3544 ` 3545 3546 res, err := Parse(Request{Str: query}) 3547 require.NoError(t, err) 3548 require.NotNil(t, res.Query[0]) 3549 require.Equal(t, []string{"name", "friend"}, childAttrs(res.Query[0])) 3550 require.NotNil(t, res.Query[0].Children[1].Facets) 3551 require.Equal(t, "close", res.Query[0].Children[1].Facets.Param[0].Key) 3552 require.Equal(t, "family", res.Query[0].Children[1].Facets.Param[1].Key) 3553 require.Equal(t, "since", res.Query[0].Children[1].Facets.Param[2].Key) 3554 require.NotNil(t, res.Query[0].Children[1].FacetsFilter) 3555 require.Equal(t, `(OR (eq close "true") (eq family "true"))`, 3556 res.Query[0].Children[1].FacetsFilter.debugString()) 3557 3558 require.Equal(t, []string{"name", "gender"}, childAttrs(res.Query[0].Children[1])) 3559 nameChild := res.Query[0].Children[1].Children[0] 3560 require.NotNil(t, nameChild) 3561 require.NotNil(t, nameChild.Facets) 3562 require.Nil(t, nameChild.FacetsFilter) 3563 genderChild := res.Query[0].Children[1].Children[1] 3564 require.NotNil(t, genderChild) 3565 require.Nil(t, genderChild.Facets) 3566 require.Nil(t, genderChild.FacetsFilter) 3567 } 3568 3569 func TestFacetsFilterFail(t *testing.T) { 3570 // multiple @facets and @facets(close, since) are not allowed. 3571 query := ` 3572 { 3573 me(func: uid(0x1)) { 3574 name 3575 friend @facets @facets(close, since) { 3576 name 3577 gender 3578 } 3579 } 3580 } 3581 ` 3582 3583 _, err := Parse(Request{Str: query}) 3584 require.Error(t, err) 3585 require.Contains(t, err.Error(), "Only one facets allowed") 3586 } 3587 3588 func TestFacetsFilterFail2(t *testing.T) { 3589 // multiple facets-filter not allowed 3590 query := ` 3591 { 3592 me(func: uid(0x1)) { 3593 name 3594 friend @facets(eq(close, true)) @facets(eq(family, true)) { 3595 name 3596 gender 3597 } 3598 } 3599 } 3600 ` 3601 3602 _, err := Parse(Request{Str: query}) 3603 require.Error(t, err) 3604 require.Contains(t, err.Error(), "Only one facets filter allowed") 3605 } 3606 3607 func TestFacetsFilterFail3(t *testing.T) { 3608 // vars are not allowed in facets filtering. 3609 query := ` 3610 { 3611 K as var(func: uid(0x0a)) { 3612 L AS friends 3613 } 3614 me(func: uid(K)) { 3615 friend @facets(uid(L)) { 3616 name 3617 } 3618 } 3619 } 3620 ` 3621 3622 _, err := Parse(Request{Str: query}) 3623 require.Error(t, err) 3624 require.Contains(t, err.Error(), "variables are not allowed in facets filter") 3625 } 3626 3627 func TestFacetsFilterFailRoot(t *testing.T) { 3628 query := ` 3629 { 3630 me(func: uid(0x1)) @facets(eq(some-facet, true)) { 3631 friend { 3632 name 3633 } 3634 } 3635 } 3636 ` 3637 3638 _, err := Parse(Request{Str: query}) 3639 require.Error(t, err) 3640 require.Contains(t, err.Error(), "Unknown directive [facets]") 3641 } 3642 3643 func TestFacetsFilterAtValue(t *testing.T) { 3644 // gql parses facets at value level as well. 3645 query := ` 3646 { 3647 me(func: uid(0x1)) { 3648 friend { 3649 name @facets(eq(some.facet, true)) 3650 } 3651 } 3652 } 3653 ` 3654 3655 res, err := Parse(Request{Str: query}) 3656 require.NoError(t, err) 3657 require.Equal(t, []string{"name"}, childAttrs(res.Query[0].Children[0])) 3658 nameChild := res.Query[0].Children[0].Children[0] 3659 require.NotNil(t, nameChild) 3660 require.NotNil(t, nameChild.FacetsFilter) 3661 require.Equal(t, `(eq some.facet "true")`, nameChild.FacetsFilter.debugString()) 3662 } 3663 3664 func TestParseQueryWithAttrLang(t *testing.T) { 3665 query := ` 3666 { 3667 me(func: uid(0x1)) { 3668 name 3669 friend(first:5, orderasc: name@en:fr) { 3670 name@en 3671 } 3672 } 3673 } 3674 ` 3675 res, err := Parse(Request{Str: query}) 3676 require.NoError(t, err) 3677 require.NotNil(t, res.Query) 3678 require.Equal(t, 1, len(res.Query)) 3679 require.Equal(t, "name", res.Query[0].Children[1].Order[0].Attr) 3680 require.Equal(t, []string{"en", "fr"}, res.Query[0].Children[1].Order[0].Langs) 3681 } 3682 3683 func TestParseQueryWithAttrLang2(t *testing.T) { 3684 query := ` 3685 { 3686 me(func:regexp(name, /^[a-zA-z]*[^Kk ]?[Nn]ight/), orderasc: name@en, first:5) { 3687 name@en 3688 name@de 3689 name@it 3690 } 3691 } 3692 ` 3693 res, err := Parse(Request{Str: query}) 3694 require.NoError(t, err) 3695 require.NotNil(t, res.Query) 3696 require.Equal(t, 1, len(res.Query)) 3697 require.Equal(t, "name", res.Query[0].Order[0].Attr) 3698 require.Equal(t, []string{"en"}, res.Query[0].Order[0].Langs) 3699 } 3700 3701 func TestParseRegexp1(t *testing.T) { 3702 query := ` 3703 { 3704 me(func: uid(0x1)) { 3705 name 3706 friend @filter(regexp(name@en, /case INSENSITIVE regexp with \/ escaped value/i)) { 3707 name@en 3708 } 3709 } 3710 } 3711 ` 3712 res, err := Parse(Request{Str: query}) 3713 require.NoError(t, err) 3714 require.NotNil(t, res.Query) 3715 require.Equal(t, 1, len(res.Query)) 3716 require.Equal(t, "case INSENSITIVE regexp with / escaped value", 3717 res.Query[0].Children[1].Filter.Func.Args[0].Value) 3718 require.Equal(t, "i", res.Query[0].Children[1].Filter.Func.Args[1].Value) 3719 } 3720 3721 func TestParseRegexp2(t *testing.T) { 3722 query := ` 3723 { 3724 me(func:regexp(name@en, /another\/compilicated ("") regexp('')/)) { 3725 name 3726 } 3727 } 3728 ` 3729 res, err := Parse(Request{Str: query}) 3730 require.NoError(t, err) 3731 require.NotNil(t, res.Query) 3732 require.Equal(t, 1, len(res.Query)) 3733 require.Equal(t, "another/compilicated (\"\") regexp('')", 3734 res.Query[0].Func.Args[0].Value) 3735 require.Equal(t, "", res.Query[0].Func.Args[1].Value) 3736 } 3737 3738 func TestParseRegexp3(t *testing.T) { 3739 query := ` 3740 { 3741 me(func:allofterms(name, "barack")) @filter(regexp(secret, /whitehouse[0-9]{1,4}/fLaGs)) { 3742 name 3743 } 3744 } 3745 ` 3746 res, err := Parse(Request{Str: query}) 3747 require.NoError(t, err) 3748 require.NotNil(t, res.Query) 3749 require.Equal(t, 1, len(res.Query)) 3750 require.Equal(t, "whitehouse[0-9]{1,4}", res.Query[0].Filter.Func.Args[0].Value) 3751 require.Equal(t, "fLaGs", res.Query[0].Filter.Func.Args[1].Value) 3752 } 3753 3754 func TestParseRegexp4(t *testing.T) { 3755 query := ` 3756 { 3757 me(func:regexp(name@en, /pattern/123)) { 3758 name 3759 } 3760 } 3761 ` 3762 _, err := Parse(Request{Str: query}) 3763 // only [a-zA-Z] characters can be used as flags 3764 require.Error(t, err) 3765 require.Contains(t, err.Error(), "Expected comma or language but got: 123") 3766 } 3767 3768 func TestParseRegexp5(t *testing.T) { 3769 query := ` 3770 { 3771 me(func:regexp(name@en, /pattern/flag123)) { 3772 name 3773 } 3774 } 3775 ` 3776 _, err := Parse(Request{Str: query}) 3777 // only [a-zA-Z] characters can be used as flags 3778 require.Error(t, err) 3779 require.Contains(t, err.Error(), "Expected comma or language but got: 123") 3780 } 3781 3782 func TestParseRegexp6(t *testing.T) { 3783 query := ` 3784 { 3785 me(func:regexp(name@en, /pattern\/)) { 3786 name 3787 } 3788 } 3789 ` 3790 _, err := Parse(Request{Str: query}) 3791 require.Error(t, err) 3792 require.Contains(t, err.Error(), 3793 "Unclosed regexp") 3794 } 3795 3796 func TestMain(m *testing.M) { 3797 os.Exit(m.Run()) 3798 } 3799 3800 func TestCountAtRoot(t *testing.T) { 3801 query := `{ 3802 me(func: uid( 1)) { 3803 count(uid) 3804 count(enemy) 3805 } 3806 }` 3807 _, err := Parse(Request{Str: query}) 3808 require.NoError(t, err) 3809 } 3810 3811 func TestCountAtRootErr(t *testing.T) { 3812 query := `{ 3813 me(func: uid( 1)) { 3814 count(enemy) { 3815 name 3816 } 3817 } 3818 }` 3819 _, err := Parse(Request{Str: query}) 3820 require.Error(t, err) 3821 require.Contains(t, err.Error(), "Cannot have children attributes when asking for count") 3822 } 3823 3824 func TestCountAtRootErr2(t *testing.T) { 3825 query := `{ 3826 me(func: uid( 1)) { 3827 count() 3828 } 3829 }` 3830 _, err := Parse(Request{Str: query}) 3831 require.Error(t, err) 3832 require.Contains(t, err.Error(), "Cannot use count(), please use count(uid)") 3833 } 3834 3835 func TestHasFuncAtRoot(t *testing.T) { 3836 query := `{ 3837 me(func: has(name@en)) { 3838 name 3839 } 3840 }` 3841 _, err := Parse(Request{Str: query}) 3842 require.NoError(t, err) 3843 } 3844 3845 func TestHasFilterAtRoot(t *testing.T) { 3846 query := `{ 3847 me(func: allofterms(name, "Steven Tom")) @filter(has(director.film)) { 3848 name 3849 } 3850 }` 3851 _, err := Parse(Request{Str: query}) 3852 require.NoError(t, err) 3853 } 3854 3855 func TestHasFilterAtChild(t *testing.T) { 3856 query := `{ 3857 me(func: anyofterms(name, "Steven Tom")) { 3858 name 3859 director.film @filter(has(genre)) { 3860 } 3861 } 3862 }` 3863 _, err := Parse(Request{Str: query}) 3864 require.NoError(t, err) 3865 } 3866 3867 // this test tests parsing of EOF inside '...' 3868 func TestDotsEOF(t *testing.T) { 3869 query := `{ 3870 me(func: uid( 0x1)) { 3871 name 3872 ..` 3873 _, err := Parse(Request{Str: query}) 3874 require.Error(t, err) 3875 require.Contains(t, err.Error(), "Unclosed action") 3876 } 3877 3878 func TestMathWithoutVarAlias(t *testing.T) { 3879 query := `{ 3880 f(func: anyofterms(name, "Rick Michonne Andrea")) { 3881 ageVar as age 3882 math(ageVar *2) 3883 } 3884 }` 3885 _, err := Parse(Request{Str: query}) 3886 require.Error(t, err) 3887 require.Contains(t, err.Error(), "Function math should be used with a variable or have an alias") 3888 } 3889 3890 func TestMathDiv0(t *testing.T) { 3891 tests := []struct { 3892 in string 3893 hasError bool 3894 }{ 3895 {`{f(func: uid(1)){x:math(1+1)}}`, false}, 3896 {`{f(func: uid(1)){x:math(1/0)}}`, true}, 3897 {`{f(func: uid(1)){x:math(1/-0)}}`, true}, 3898 {`{f(func: uid(1)){x:math(1/ln(1))}}`, true}, 3899 {`{f(func: uid(1)){x:math(1/sqrt(0))}}`, true}, 3900 {`{f(func: uid(1)){x:math(1/floor(0))}}`, true}, 3901 {`{f(func: uid(1)){x:math(1/floor(0.5))}}`, true}, 3902 {`{f(func: uid(1)){x:math(1/floor(1.01))}}`, false}, 3903 {`{f(func: uid(1)){x:math(1/ceil(0))}}`, true}, 3904 {`{f(func: uid(1)){x:math(1%0}}`, true}, 3905 {`{f(func: uid(1)){x:math(1%floor(0)}}`, true}, 3906 {`{f(func: uid(1)){x:math(1 + 0)}}`, false}, 3907 } 3908 for _, tc := range tests { 3909 _, err := Parse(Request{Str: tc.in}) 3910 if tc.hasError { 3911 require.Error(t, err, "Expected an error for %q", tc.in) 3912 } else { 3913 require.NoError(t, err, "Unexpected error for %q: %s", tc.in, err) 3914 } 3915 } 3916 } 3917 3918 func TestMultipleEqual(t *testing.T) { 3919 query := `{ 3920 me(func: eq(name,["Steven Spielberg", "Tom Hanks"])) { 3921 name 3922 } 3923 }` 3924 3925 gql, err := Parse(Request{Str: query}) 3926 require.NoError(t, err) 3927 require.Equal(t, 2, len(gql.Query[0].Func.Args)) 3928 require.Equal(t, "Tom Hanks", gql.Query[0].Func.Args[1].Value) 3929 } 3930 3931 func TestParseEqArg(t *testing.T) { 3932 query := ` 3933 { 3934 me(func: uid(1, 20)) @filter(eq(name, ["And\"rea", "Bob"])) { 3935 name 3936 } 3937 } 3938 ` 3939 gql, err := Parse(Request{Str: query}) 3940 require.NoError(t, err) 3941 require.Equal(t, 2, len(gql.Query[0].Filter.Func.Args)) 3942 } 3943 3944 // TestParserFuzz replays inputs that were identified by go-fuzz to cause crash 3945 // in the past. Used for regression testing. 3946 // We don't care here about return value, only about correct handling of 3947 // incorrect input. 3948 func TestParserFuzz(t *testing.T) { 3949 tests := []struct { 3950 name string 3951 in string 3952 }{ 3953 {"test001", "{e(){@filter(q(/"}, 3954 {"test002", "{e(){@filter(p(%"}, 3955 {"test003", "{e(){@filter(0(/\\0"}, 3956 {"test004", "query #"}, 3957 {"test005", "{e(){{@filter(q(/"}, 3958 {"test006", "{e(func:0(0(0,/"}, 3959 {"test007", "{e(func:uid()){@filter(0(/\\"}, 3960 {"test008", "{e(){@filter(0(/\\0/"}, 3961 {"test009", "{e(){@filter(p(/\\"}, 3962 {"test010", "{m(func:0(0(0(0,/"}, 3963 {"test011", "{e(){@filter(0(%0"}, 3964 {"test012", "{e(func:uid()){@filter(p(%"}, 3965 {"test013", "{e(orderasc:val(0)){{min(val(0)0("}, 3966 {"test014", "query{e(func:uid(val(0)"}, 3967 {"test015", "{e(){@filter(0(%000"}, 3968 {"test016", "{e(){@filter(0(%"}, 3969 {"test017", "{e(){{@filter(0(/"}, 3970 {"test018", "{e(func:uid(0))@filter(p(/\\"}, 3971 {"test019", "{e(func:uid()){@filter(p(/\\"}, 3972 {"test020", "{e(){@filter(p(/\\00"}, 3973 {"test021", "{e(func:uid(0)){@filter(0(%"}, 3974 {"test022", "{e(){@filter(0(/"}, 3975 {"test023", "{e(func:uid()){@filter(p(/"}, 3976 {"test024", "{s(func:uid(val(0)"}, 3977 {"test025", "{e()@filter(0(%"}, 3978 {"test026", "{e(func:uid(0)){@filter(0(/\\"}, 3979 {"test027", "{e(){@filter(0(%"}, 3980 {"test028", "{e(){@filter(0(%00"}, 3981 {"test029", "{e(func:uid(0)){@filter(p(/\\e/i)){e}}}"}, 3982 {"test030", "{e(func:uid(0)){@filter(p(%//i))00"}, 3983 {"test031", "{e()@filter(p(/�Is))}"}, 3984 {"test032", "{e(){@filter(0(0,/"}, 3985 {"test033", "{e(func:uid()){@filter(0(/"}, 3986 {"test034", "{e()@filter(0(/"}, 3987 {"test035", "{e(func:uid(0)){@filter(p(/\\"}, 3988 {"test036", "{e(func:uid())@filter(0(%"}, 3989 {"test037", "{e(func:uid(0)){@filter(0(%"}, 3990 {"test038", "{e(func:uid(0))@filter(p(/\\0/"}, 3991 {"test039", "{e(func:uid(0)){@filter(p(/\\e/i)){e}00"}, 3992 {"test040", "{e(){@filter(0(-"}, 3993 {"test041", "{e(func:uid(0)){@filter(0(%0"}, 3994 {"test042", "{e()@filter(q(/"}, 3995 {"test043", "{e(func:uid(0)){@filter(p(%"}, 3996 {"test044", "{e()@filter(p(/"}, 3997 {"test045", "{e(func:uid())@filter(0(/"}, 3998 {"test046", "{e(func:uid(0)){@filter(p(/\\e/"}, 3999 {"test047", "{e(func:uid()){@filter(0(%"}, 4000 {"test048", "{e()@filter(0(0,/"}, 4001 {"test049", "{e(){{@filter(0(0,/"}, 4002 {"test050", "{e(func:uid(0)){@filter(p(/"}, 4003 {"test051", "{e()@filter(0(-"}, 4004 {"test052", "{e(func:uid(0)){@filter(0(/"}, 4005 {"test053", "{e(func:uid())@filter(p(%"}, 4006 {"test054", "{e(orderasc:val(0)){min(val(0)0("}, 4007 {"test055", "{e(){@filter(p(/"}, 4008 {"test056", "{e(func:uid())@filter(p(/"}, 4009 {"test057", "a<><\\�"}, 4010 {"test058", "L<\\𝌀"}, 4011 {"test059", "{d(after:<>0)}"}, 4012 {"test060", "{e(orderasc:#"}, 4013 } 4014 4015 for _, test := range tests { 4016 t.Run(test.name, func(t *testing.T) { 4017 defer func() { 4018 if r := recover(); r != nil { 4019 t.Errorf("parser panic caused by test: '%s', input: '%s': %v\n%s", test.name, test.in, r, debug.Stack()) 4020 } 4021 }() 4022 4023 Parse(Request{Str: test.in}) 4024 }) 4025 } 4026 } 4027 4028 func TestParseEqArg2(t *testing.T) { 4029 query := ` 4030 { 4031 me(func: eq(age, [1, 20])) @filter(eq(name, ["And\"rea", "Bob"])) { 4032 name 4033 } 4034 } 4035 ` 4036 gql, err := Parse(Request{Str: query}) 4037 require.NoError(t, err) 4038 require.Equal(t, 2, len(gql.Query[0].Filter.Func.Args)) 4039 require.Equal(t, 2, len(gql.Query[0].Func.Args)) 4040 } 4041 4042 func TestFilterError(t *testing.T) { 4043 query := ` 4044 { 4045 me(func: uid(1, 3 , 5, 7)) { @filter(uid(3, 7)) 4046 name 4047 } 4048 } 4049 ` 4050 _, err := Parse(Request{Str: query}) 4051 require.Error(t, err) 4052 } 4053 4054 func TestFilterError2(t *testing.T) { 4055 query := ` 4056 { 4057 me(func: uid(1, 3 , 5, 7)) { 4058 name @filter(eq(name, "abc")) @filter(eq(name2, "abc")) 4059 } 4060 } 4061 ` 4062 _, err := Parse(Request{Str: query}) 4063 require.Error(t, err) 4064 } 4065 4066 func TestDoubleGroupByError(t *testing.T) { 4067 query := ` 4068 { 4069 me(func: uid(1, 3 , 5, 7)) { 4070 name @groupby(abc) @groupby(bcd) 4071 } 4072 } 4073 ` 4074 _, err := Parse(Request{Str: query}) 4075 require.Error(t, err) 4076 } 4077 4078 func TestFilterError3(t *testing.T) { 4079 query := ` 4080 { 4081 me(func: uid(1, 3 , 5, 7)) { 4082 expand(_all_) @filter(eq(name, "abc")) 4083 } 4084 } 4085 ` 4086 _, err := Parse(Request{Str: query}) 4087 require.Error(t, err) 4088 } 4089 4090 func TestFilterUid(t *testing.T) { 4091 query := ` 4092 { 4093 me(func: uid(1, 3 , 5, 7)) @filter(uid(3, 7)) { 4094 name 4095 } 4096 } 4097 ` 4098 gql, err := Parse(Request{Str: query}) 4099 require.NoError(t, err) 4100 require.Equal(t, []uint64{1, 3, 5, 7}, gql.Query[0].UID) 4101 require.Equal(t, []uint64{3, 7}, gql.Query[0].Filter.Func.UID) 4102 } 4103 4104 func TestIdErr(t *testing.T) { 4105 query := ` 4106 { 4107 me(id: [1, 3 , 5, 7]) @filter(uid(3, 7)) { 4108 name 4109 } 4110 } 4111 ` 4112 _, err := Parse(Request{Str: query}) 4113 require.Error(t, err) 4114 require.Contains(t, err.Error(), "Got invalid keyword: id") 4115 } 4116 4117 func TestFilterVarErr(t *testing.T) { 4118 query := ` 4119 { 4120 x as m(func: allofterms(name, "Pawan Rawal")) 4121 } 4122 { 4123 me(func: uid(1, 3 , 5, 7)) @filter(var(x)) { 4124 name 4125 } 4126 } 4127 ` 4128 _, err := Parse(Request{Str: query}) 4129 require.Error(t, err) 4130 require.Contains(t, err.Error(), "Unexpected var()") 4131 } 4132 4133 func TestEqUidFunctionErr(t *testing.T) { 4134 query := ` 4135 { 4136 me(func: eq(path_id, uid(x))) { 4137 name 4138 } 4139 } 4140 ` 4141 _, err := Parse(Request{Str: query}) 4142 require.Error(t, err) 4143 require.Contains(t, err.Error(), "Only val/count/len allowed as function within another. Got: uid") 4144 } 4145 4146 func TestAggRoot1(t *testing.T) { 4147 query := ` 4148 { 4149 var(func: anyofterms(name, "Rick Michonne Andrea")) { 4150 a as age 4151 } 4152 4153 me() { 4154 sum(val(a)) 4155 avg(val(a)) 4156 } 4157 } 4158 ` 4159 gql, err := Parse(Request{Str: query}) 4160 require.NoError(t, err) 4161 require.Equal(t, "me", gql.Query[1].Alias) 4162 require.Equal(t, true, gql.Query[1].IsEmpty) 4163 } 4164 4165 func TestAggRootError(t *testing.T) { 4166 query := ` 4167 { 4168 var(func: anyofterms(name, "Rick Michonne Andrea")) { 4169 a as age 4170 } 4171 4172 me() { 4173 sum(val(a)) 4174 avg(val(a)) 4175 friend @filter(anyofterms(name, "Hey")) { 4176 name 4177 } 4178 } 4179 } 4180 ` 4181 _, err := Parse(Request{Str: query}) 4182 require.Error(t, err) 4183 require.Contains(t, err.Error(), "Only aggregation/math functions allowed inside empty blocks. Got: friend") 4184 } 4185 4186 func TestAggRootError2(t *testing.T) { 4187 query := ` 4188 { 4189 var(func: anyofterms(name, "Rick Michonne Andrea")) { 4190 a as age 4191 } 4192 4193 me() { 4194 avg(val(a)) 4195 name 4196 } 4197 } 4198 ` 4199 _, err := Parse(Request{Str: query}) 4200 require.Error(t, err) 4201 require.Contains(t, err.Error(), "Only aggregation/math functions allowed inside empty blocks. Got: name") 4202 } 4203 4204 func TestAggRootError3(t *testing.T) { 4205 query := ` 4206 { 4207 var(func: anyofterms(name, "Rick Michonne Andrea")) { 4208 a as age 4209 } 4210 4211 me() { 4212 avg 4213 } 4214 } 4215 ` 4216 _, err := Parse(Request{Str: query}) 4217 require.Error(t, err) 4218 require.Contains(t, err.Error(), "Only aggregation/math functions allowed inside empty blocks. Got: avg") 4219 } 4220 4221 func TestEmptyFunction(t *testing.T) { 4222 query := ` 4223 { 4224 director(func:allofterms()) { 4225 name@en 4226 director.film (orderdesc: initial_release_date) { 4227 name@en 4228 initial_release_date 4229 } 4230 } 4231 }` 4232 4233 _, err := Parse(Request{Str: query}) 4234 require.Error(t, err) 4235 require.Contains(t, err.Error(), "Got empty attr for function: [allofterms]") 4236 } 4237 4238 func TestOrder1(t *testing.T) { 4239 query := ` 4240 { 4241 me(func: uid(1), orderdesc: name, orderasc: age) { 4242 name 4243 } 4244 } 4245 ` 4246 gq, err := Parse(Request{Str: query}) 4247 require.NoError(t, err) 4248 require.Equal(t, 2, len(gq.Query[0].Order)) 4249 require.Equal(t, "name", gq.Query[0].Order[0].Attr) 4250 require.Equal(t, true, gq.Query[0].Order[0].Desc) 4251 require.Equal(t, "age", gq.Query[0].Order[1].Attr) 4252 require.Equal(t, false, gq.Query[0].Order[1].Desc) 4253 } 4254 4255 func TestOrder2(t *testing.T) { 4256 query := ` 4257 { 4258 me(func: uid(0x01)) { 4259 friend(orderasc: alias, orderdesc: name) @filter(lt(alias, "Pat")) { 4260 alias 4261 } 4262 } 4263 } 4264 ` 4265 gq, err := Parse(Request{Str: query}) 4266 require.NoError(t, err) 4267 curp := gq.Query[0].Children[0] 4268 require.Equal(t, 2, len(curp.Order)) 4269 require.Equal(t, "alias", curp.Order[0].Attr) 4270 require.Equal(t, false, curp.Order[0].Desc) 4271 require.Equal(t, "name", curp.Order[1].Attr) 4272 require.Equal(t, true, curp.Order[1].Desc) 4273 } 4274 4275 func TestMultipleOrderError(t *testing.T) { 4276 query := ` 4277 { 4278 me(func: uid(0x01)) { 4279 friend(orderasc: alias, orderdesc: alias) { 4280 alias 4281 } 4282 } 4283 } 4284 ` 4285 _, err := Parse(Request{Str: query}) 4286 require.Error(t, err) 4287 require.Contains(t, err.Error(), "Sorting by an attribute: [alias] can only be done once") 4288 } 4289 4290 func TestMultipleOrderError2(t *testing.T) { 4291 query := ` 4292 { 4293 me(func: uid(0x01),orderasc: alias, orderdesc: alias) { 4294 friend { 4295 alias 4296 } 4297 } 4298 } 4299 ` 4300 _, err := Parse(Request{Str: query}) 4301 require.Error(t, err) 4302 require.Contains(t, err.Error(), "Sorting by an attribute: [alias] can only be done once") 4303 } 4304 4305 func TestEqArgWithDollar(t *testing.T) { 4306 // This is a fix for #1444. 4307 query := ` 4308 { 4309 ab(func: eq(name@en, "$pringfield (or, How)")) { 4310 uid 4311 } 4312 } 4313 ` 4314 gql, err := Parse(Request{Str: query}) 4315 require.NoError(t, err) 4316 require.Equal(t, gql.Query[0].Func.Args[0].Value, `$pringfield (or, How)`) 4317 } 4318 4319 func TestLangWithDash(t *testing.T) { 4320 query := `{ 4321 q(func: uid(1)) { 4322 text@en-us 4323 } 4324 }` 4325 4326 gql, err := Parse(Request{Str: query}) 4327 require.NoError(t, err) 4328 require.Equal(t, []string{"en-us"}, gql.Query[0].Children[0].Langs) 4329 } 4330 4331 func TestOrderByVarAndPred(t *testing.T) { 4332 query := `{ 4333 q(func: uid(1), orderasc: name, orderdesc: val(n)) { 4334 } 4335 4336 var(func: uid(0x0a)) { 4337 friends { 4338 n AS name 4339 } 4340 } 4341 4342 }` 4343 _, err := Parse(Request{Str: query}) 4344 require.Error(t, err) 4345 require.Contains(t, err.Error(), "Multiple sorting only allowed by predicates.") 4346 4347 query = `{ 4348 q(func: uid(1)) { 4349 } 4350 4351 var(func: uid(0x0a)) { 4352 friends (orderasc: name, orderdesc: val(n)) { 4353 n AS name 4354 } 4355 } 4356 4357 }` 4358 _, err = Parse(Request{Str: query}) 4359 require.Error(t, err) 4360 require.Contains(t, err.Error(), "Multiple sorting only allowed by predicates.") 4361 4362 query = `{ 4363 q(func: uid(1)) { 4364 } 4365 4366 var(func: uid(0x0a)) { 4367 friends (orderasc: name, orderdesc: genre) { 4368 name 4369 } 4370 } 4371 4372 }` 4373 _, err = Parse(Request{Str: query}) 4374 require.NoError(t, err) 4375 } 4376 4377 func TestInvalidValUsage(t *testing.T) { 4378 query := ` 4379 { 4380 me(func: uid(0x01)) { 4381 val(uid) { 4382 nope 4383 } 4384 } 4385 } 4386 ` 4387 _, err := Parse(Request{Str: query}) 4388 require.Error(t, err) 4389 require.Contains(t, err.Error(), "Query syntax invalid.") 4390 } 4391 4392 func TestOrderWithLang(t *testing.T) { 4393 query := ` 4394 { 4395 me(func: uid(0x1), orderasc: name@en:fr:., orderdesc: lastname@ci, orderasc: salary) { 4396 name 4397 } 4398 } 4399 ` 4400 res, err := Parse(Request{Str: query}) 4401 require.NoError(t, err) 4402 require.NotNil(t, res.Query) 4403 require.Equal(t, 1, len(res.Query)) 4404 orders := res.Query[0].Order 4405 require.Equal(t, "name", orders[0].Attr) 4406 require.Equal(t, []string{"en", "fr", "."}, orders[0].Langs) 4407 require.Equal(t, "lastname", orders[1].Attr) 4408 require.Equal(t, []string{"ci"}, orders[1].Langs) 4409 require.Equal(t, "salary", orders[2].Attr) 4410 require.Equal(t, 0, len(orders[2].Langs)) 4411 } 4412 4413 func TestParseLangTagAfterStringInRoot(t *testing.T) { 4414 // This is a fix for #1499. 4415 query := ` 4416 { 4417 q(func: anyofterms(name, "Hello"@en)) { 4418 uid 4419 } 4420 } 4421 ` 4422 _, err := Parse(Request{Str: query}) 4423 require.Error(t, err) 4424 require.Contains(t, err.Error(), "Invalid usage of '@' in function argument") 4425 } 4426 4427 func TestParseLangTagAfterStringInFilter(t *testing.T) { 4428 // This is a fix for #1499. 4429 query := ` 4430 { 4431 q(func: uid(0x01)) @filter(eq(name, "Hello"@en)) { 4432 uid 4433 } 4434 } 4435 ` 4436 _, err := Parse(Request{Str: query}) 4437 require.Error(t, err) 4438 require.Contains(t, err.Error(), "Invalid usage of '@' in function argument") 4439 } 4440 4441 func parseNquads(b []byte) ([]*api.NQuad, error) { 4442 var lexer lex.Lexer 4443 var nqs []*api.NQuad 4444 for _, line := range bytes.Split(b, []byte{'\n'}) { 4445 nq, err := chunker.ParseRDF(string(line), &lexer) 4446 if err == chunker.ErrEmpty { 4447 continue 4448 } 4449 if err != nil { 4450 return nil, err 4451 } 4452 nqs = append(nqs, &nq) 4453 } 4454 return nqs, nil 4455 } 4456 4457 func TestParseMutation(t *testing.T) { 4458 m := ` 4459 { 4460 set { 4461 <name> <is> <something> . 4462 <hometown> <is> <san/francisco> . 4463 } 4464 delete { 4465 <name> <is> <something-else> . 4466 } 4467 } 4468 ` 4469 req, err := ParseMutation(m) 4470 require.NoError(t, err) 4471 mu := req.Mutations[0] 4472 require.NotNil(t, mu) 4473 sets, err := parseNquads(mu.SetNquads) 4474 require.NoError(t, err) 4475 require.EqualValues(t, &api.NQuad{ 4476 Subject: "name", Predicate: "is", ObjectId: "something"}, 4477 sets[0]) 4478 require.EqualValues(t, &api.NQuad{ 4479 Subject: "hometown", Predicate: "is", ObjectId: "san/francisco"}, 4480 sets[1]) 4481 dels, err := parseNquads(mu.DelNquads) 4482 require.NoError(t, err) 4483 require.EqualValues(t, &api.NQuad{ 4484 Subject: "name", Predicate: "is", ObjectId: "something-else"}, 4485 dels[0]) 4486 } 4487 4488 func TestParseMutationTooManyBlocks(t *testing.T) { 4489 tests := []struct { 4490 m string 4491 errStr string 4492 }{ 4493 {m: ` 4494 { 4495 set { _:a1 <reg> "a1 content" . } 4496 }{ 4497 set { _:b2 <reg> "b2 content" . } 4498 }`, 4499 errStr: "Unrecognized character in lexText", 4500 }, 4501 {m: `{set { _:a1 <reg> "a1 content" . }} something`, 4502 errStr: "Invalid operation type: something", 4503 }, 4504 {m: ` 4505 # comments are ok 4506 { 4507 set { _:a1 <reg> "a1 content" . } # comments are ok 4508 } # comments are ok`, 4509 }, 4510 } 4511 for _, tc := range tests { 4512 mu, err := ParseMutation(tc.m) 4513 if tc.errStr != "" { 4514 require.Contains(t, err.Error(), tc.errStr) 4515 require.Nil(t, mu) 4516 } else { 4517 require.NoError(t, err) 4518 } 4519 } 4520 } 4521 4522 func TestParseMissingGraphQLVar(t *testing.T) { 4523 for _, q := range []string{ 4524 "{ q(func: eq(name, $a)) { name }}", 4525 "query { q(func: eq(name, $a)) { name }}", 4526 "query foo { q(func: eq(name, $a)) { name }}", 4527 "query foo () { q(func: eq(name, $a)) { name }}", 4528 "query foo ($b: string) { q(func: eq(name, $a)) { name }}", 4529 "query foo ($a: string) { q(func: eq(name, $b)) { name }}", 4530 } { 4531 r := Request{ 4532 Str: q, 4533 Variables: map[string]string{"$a": "alice"}, 4534 } 4535 _, err := Parse(r) 4536 t.Log(q) 4537 t.Log(err) 4538 require.Error(t, err) 4539 } 4540 } 4541 4542 func TestParseGraphQLVarPaginationRoot(t *testing.T) { 4543 for _, q := range []string{ 4544 "query test($a: int = 2){ q(func: uid(0x1), first: $a) { name }}", 4545 "query test($a: int = 2){ q(func: uid(0x1), offset: $a) { name }}", 4546 "query test($a: int = 2){ q(func: uid(0x1), orderdesc: name, first: $a) { name }}", 4547 "query test($a: int = 2){ q(func: uid(0x1), orderdesc: name, offset: $a) { name }}", 4548 "query test($a: int = 2){ q(func: eq(name, \"abc\"), orderdesc: name, first: $a) { name }}", 4549 "query test($a: int = 2){ q(func: eq(name, \"abc\"), orderdesc: name, offset: $a) { name }}", 4550 } { 4551 r := Request{ 4552 Str: q, 4553 Variables: map[string]string{"$a": "3"}, 4554 } 4555 gq, err := Parse(r) 4556 t.Log(q) 4557 t.Log(err) 4558 require.NoError(t, err) 4559 args := gq.Query[0].Args 4560 require.True(t, args["first"] == "3" || args["offset"] == "3") 4561 } 4562 } 4563 4564 func TestParseGraphQLVarPaginationChild(t *testing.T) { 4565 for _, q := range []string{ 4566 "query test($a: int = 2){ q(func: uid(0x1)) { friend(first: $a) }}", 4567 "query test($a: int = 2){ q(func: uid(0x1)) { friend(offset: $a) }}", 4568 "query test($a: int = 2){ q(func: uid(0x1), orderdesc: name) { friend(first: $a) }}", 4569 "query test($a: int = 2){ q(func: uid(0x1), orderdesc: name) { friend(offset: $a) }}", 4570 "query test($a: int = 2){ q(func: eq(name, \"abc\"), orderdesc: name) { friend(first: $a) }}", 4571 "query test($a: int = 2){ q(func: eq(name, \"abc\"), orderdesc: name) { friend(offset: $a) }}", 4572 } { 4573 r := Request{ 4574 Str: q, 4575 Variables: map[string]string{"$a": "3"}, 4576 } 4577 gq, err := Parse(r) 4578 t.Log(q) 4579 t.Log(err) 4580 require.NoError(t, err) 4581 args := gq.Query[0].Children[0].Args 4582 require.True(t, args["first"] == "3" || args["offset"] == "3") 4583 } 4584 } 4585 4586 func TestParseGraphQLVarPaginationRootMultiple(t *testing.T) { 4587 q := `query test($a: int, $b: int, $after: string){ 4588 q(func: uid(0x1), first: $a, offset: $b, after: $after, orderasc: name) { 4589 friend 4590 } 4591 }` 4592 4593 r := Request{ 4594 Str: q, 4595 Variables: map[string]string{"$a": "3", "$b": "5", "$after": "0x123"}, 4596 } 4597 gq, err := Parse(r) 4598 require.NoError(t, err) 4599 args := gq.Query[0].Args 4600 require.Equal(t, args["first"], "3") 4601 require.Equal(t, args["offset"], "5") 4602 require.Equal(t, args["after"], "0x123") 4603 require.Equal(t, gq.Query[0].Order[0].Attr, "name") 4604 } 4605 4606 func TestParseGraphQLVarArray(t *testing.T) { 4607 tests := []struct { 4608 q string 4609 vars map[string]string 4610 args int 4611 }{ 4612 {q: `query test($a: string){q(func: eq(name, [$a])) {name}}`, 4613 vars: map[string]string{"$a": "srfrog"}, args: 1}, 4614 {q: `query test($a: string, $b: string){q(func: eq(name, [$a, $b])) {name}}`, 4615 vars: map[string]string{"$a": "srfrog", "$b": "horseman"}, args: 2}, 4616 {q: `query test($a: string, $b: string, $c: string){q(func: eq(name, [$a, $b, $c])) {name}}`, 4617 vars: map[string]string{"$a": "srfrog", "$b": "horseman", "$c": "missbug"}, args: 3}, 4618 // mixed var and value 4619 {q: `query test($a: string){q(func: eq(name, [$a, "mrtrout"])) {name}}`, 4620 vars: map[string]string{"$a": "srfrog"}, args: 2}, 4621 {q: `query test($a: string){q(func: eq(name, ["mrtrout", $a])) {name}}`, 4622 vars: map[string]string{"$a": "srfrog"}, args: 2}, 4623 } 4624 for _, tc := range tests { 4625 gq, err := Parse(Request{Str: tc.q, Variables: tc.vars}) 4626 require.NoError(t, err) 4627 require.Equal(t, 1, len(gq.Query)) 4628 require.Equal(t, "eq", gq.Query[0].Func.Name) 4629 require.Equal(t, tc.args, len(gq.Query[0].Func.Args)) 4630 found := false 4631 for _, val := range tc.vars { 4632 for _, arg := range gq.Query[0].Func.Args { 4633 if val == arg.Value { 4634 found = true 4635 break 4636 } 4637 } 4638 } 4639 require.True(t, found, "vars not matched: %v", tc.vars) 4640 } 4641 } 4642 4643 func TestParseGraphQLValueArray(t *testing.T) { 4644 q := ` 4645 { 4646 q(func: eq(name, ["srfrog", "horseman"])) { 4647 name 4648 } 4649 }` 4650 gq, err := Parse(Request{Str: q}) 4651 require.NoError(t, err) 4652 require.Equal(t, 1, len(gq.Query)) 4653 require.Equal(t, "eq", gq.Query[0].Func.Name) 4654 require.Equal(t, 2, len(gq.Query[0].Func.Args)) 4655 require.Equal(t, "srfrog", gq.Query[0].Func.Args[0].Value) 4656 require.Equal(t, "horseman", gq.Query[0].Func.Args[1].Value) 4657 } 4658 4659 func TestParseGraphQLMixedVarArray(t *testing.T) { 4660 q := ` 4661 query test($a: string, $b: string, $c: string){ 4662 q(func: eq(name, ["uno", $a, $b, "cuatro", $c])) { 4663 name 4664 } 4665 }` 4666 r := Request{ 4667 Str: q, 4668 Variables: map[string]string{"$a": "dos", "$b": "tres", "$c": "cinco"}, 4669 } 4670 gq, err := Parse(r) 4671 require.NoError(t, err) 4672 require.Equal(t, 1, len(gq.Query)) 4673 require.Equal(t, "eq", gq.Query[0].Func.Name) 4674 require.Equal(t, 5, len(gq.Query[0].Func.Args)) 4675 require.Equal(t, "uno", gq.Query[0].Func.Args[0].Value) 4676 require.Equal(t, "dos", gq.Query[0].Func.Args[1].Value) 4677 require.Equal(t, "tres", gq.Query[0].Func.Args[2].Value) 4678 require.Equal(t, "cuatro", gq.Query[0].Func.Args[3].Value) 4679 require.Equal(t, "cinco", gq.Query[0].Func.Args[4].Value) 4680 } 4681 4682 func TestLineAndColumnNumberInErrorOutput(t *testing.T) { 4683 q := ` 4684 query { 4685 me(func: uid(0x0a)) { 4686 friends @filter(alloftext(descr@, "something")) { 4687 name 4688 } 4689 gender,age 4690 hometown 4691 } 4692 }` 4693 _, err := Parse(Request{Str: q}) 4694 require.Error(t, err) 4695 require.Contains(t, err.Error(), 4696 "line 4 column 35: Unrecognized character in lexDirective: U+002C ','") 4697 } 4698 4699 func TestTypeFunction(t *testing.T) { 4700 q := ` 4701 query { 4702 me(func: type(Person)) { 4703 name 4704 } 4705 }` 4706 gq, err := Parse(Request{Str: q}) 4707 require.NoError(t, err) 4708 require.Equal(t, 1, len(gq.Query)) 4709 require.Equal(t, "type", gq.Query[0].Func.Name) 4710 require.Equal(t, 1, len(gq.Query[0].Func.Args)) 4711 require.Equal(t, "Person", gq.Query[0].Func.Args[0].Value) 4712 } 4713 4714 func TestTypeFunctionError1(t *testing.T) { 4715 q := ` 4716 query { 4717 me(func: type(Person, School)) { 4718 name 4719 } 4720 }` 4721 _, err := Parse(Request{Str: q}) 4722 require.Error(t, err) 4723 require.Contains(t, err.Error(), "type function only supports one argument") 4724 } 4725 4726 func TestTypeInFilter(t *testing.T) { 4727 q := ` 4728 query { 4729 me(func: uid(0x01)) @filter(type(Person)) { 4730 name 4731 } 4732 }` 4733 gq, err := Parse(Request{Str: q}) 4734 require.NoError(t, err) 4735 require.Equal(t, 1, len(gq.Query)) 4736 require.Equal(t, "uid", gq.Query[0].Func.Name) 4737 require.Equal(t, 1, len(gq.Query[0].Children)) 4738 require.Equal(t, "name", gq.Query[0].Children[0].Attr) 4739 require.Equal(t, "type", gq.Query[0].Filter.Func.Name) 4740 require.Equal(t, 1, len(gq.Query[0].Filter.Func.Args)) 4741 require.Equal(t, "Person", gq.Query[0].Filter.Func.Args[0].Value) 4742 } 4743 4744 func TestTypeFilterInPredicate(t *testing.T) { 4745 q := ` 4746 query { 4747 me(func: uid(0x01)) { 4748 friend @filter(type(Person)) { 4749 name 4750 } 4751 } 4752 }` 4753 gq, err := Parse(Request{Str: q}) 4754 require.NoError(t, err) 4755 require.Equal(t, 1, len(gq.Query)) 4756 require.Equal(t, "uid", gq.Query[0].Func.Name) 4757 require.Equal(t, 1, len(gq.Query[0].Children)) 4758 require.Equal(t, "friend", gq.Query[0].Children[0].Attr) 4759 4760 require.Equal(t, "type", gq.Query[0].Children[0].Filter.Func.Name) 4761 require.Equal(t, 1, len(gq.Query[0].Children[0].Filter.Func.Args)) 4762 require.Equal(t, "Person", gq.Query[0].Children[0].Filter.Func.Args[0].Value) 4763 4764 require.Equal(t, 1, len(gq.Query[0].Children[0].Children)) 4765 require.Equal(t, "name", gq.Query[0].Children[0].Children[0].Attr) 4766 } 4767 4768 func TestTypeInPredicate(t *testing.T) { 4769 q := ` 4770 query { 4771 me(func: uid(0x01)) { 4772 friend @type(Person) { 4773 name 4774 } 4775 } 4776 }` 4777 gq, err := Parse(Request{Str: q}) 4778 require.NoError(t, err) 4779 require.Equal(t, 1, len(gq.Query)) 4780 require.Equal(t, "uid", gq.Query[0].Func.Name) 4781 require.Equal(t, 1, len(gq.Query[0].Children)) 4782 require.Equal(t, "friend", gq.Query[0].Children[0].Attr) 4783 4784 require.Equal(t, "type", gq.Query[0].Children[0].Filter.Func.Name) 4785 require.Equal(t, 1, len(gq.Query[0].Children[0].Filter.Func.Args)) 4786 require.Equal(t, "Person", gq.Query[0].Children[0].Filter.Func.Args[0].Value) 4787 4788 require.Equal(t, 1, len(gq.Query[0].Children[0].Children)) 4789 require.Equal(t, "name", gq.Query[0].Children[0].Children[0].Attr) 4790 } 4791 4792 func TestMultipleTypeDirectives(t *testing.T) { 4793 q := ` 4794 query { 4795 me(func: uid(0x01)) { 4796 friend @type(Person) { 4797 pet @type(Animal) { 4798 name 4799 } 4800 } 4801 } 4802 }` 4803 gq, err := Parse(Request{Str: q}) 4804 require.NoError(t, err) 4805 require.Equal(t, 1, len(gq.Query)) 4806 require.Equal(t, "uid", gq.Query[0].Func.Name) 4807 require.Equal(t, 1, len(gq.Query[0].Children)) 4808 require.Equal(t, "friend", gq.Query[0].Children[0].Attr) 4809 4810 require.Equal(t, "type", gq.Query[0].Children[0].Filter.Func.Name) 4811 require.Equal(t, 1, len(gq.Query[0].Children[0].Filter.Func.Args)) 4812 require.Equal(t, "Person", gq.Query[0].Children[0].Filter.Func.Args[0].Value) 4813 4814 require.Equal(t, 1, len(gq.Query[0].Children[0].Children)) 4815 require.Equal(t, "pet", gq.Query[0].Children[0].Children[0].Attr) 4816 4817 require.Equal(t, "type", gq.Query[0].Children[0].Children[0].Filter.Func.Name) 4818 require.Equal(t, 1, len(gq.Query[0].Children[0].Children[0].Filter.Func.Args)) 4819 require.Equal(t, "Animal", gq.Query[0].Children[0].Children[0].Filter.Func.Args[0].Value) 4820 }