github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/query/query3_test.go (about)

     1  /*
     2   * Copyright 2018 Dgraph Labs, Inc. and Contributors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package query
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/require"
    27  	"google.golang.org/grpc/metadata"
    28  )
    29  
    30  func TestRecurseError(t *testing.T) {
    31  	query := `
    32  		{
    33  			me(func: uid(0x01)) @recurse(loop: true) {
    34  				nonexistent_pred
    35  				friend
    36  				name
    37  			}
    38  		}`
    39  
    40  	_, err := processQuery(context.Background(), t, query)
    41  	require.Error(t, err)
    42  	require.Contains(t, err.Error(), "Depth must be > 0 when loop is true for recurse query")
    43  }
    44  
    45  func TestRecurseNestedError1(t *testing.T) {
    46  	query := `
    47  		{
    48  			me(func: uid(0x01)) @recurse {
    49  				friend {
    50  					name
    51  				}
    52  				name
    53  			}
    54  		}`
    55  
    56  	_, err := processQuery(context.Background(), t, query)
    57  	require.Error(t, err)
    58  	require.Contains(t, err.Error(),
    59  		"recurse queries require that all predicates are specified in one level")
    60  }
    61  
    62  func TestRecurseNestedError2(t *testing.T) {
    63  	query := `
    64  		{
    65  			me(func: uid(0x01)) @recurse {
    66  				friend {
    67  					pet {
    68  						name
    69  					}
    70  				}
    71  			}
    72  		}`
    73  
    74  	_, err := processQuery(context.Background(), t, query)
    75  	require.Error(t, err)
    76  	require.Contains(t, err.Error(),
    77  		"recurse queries require that all predicates are specified in one level")
    78  }
    79  
    80  func TestRecurseQuery(t *testing.T) {
    81  
    82  	query := `
    83  		{
    84  			me(func: uid(0x01)) @recurse {
    85  				nonexistent_pred
    86  				friend
    87  				name
    88  			}
    89  		}`
    90  	js := processQueryNoErr(t, query)
    91  	require.JSONEq(t,
    92  		`{"data": {"me":[{"name":"Michonne", "friend":[{"name":"Rick Grimes", "friend":[{"name":"Michonne"}]},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea", "friend":[{"name":"Glenn Rhee"}]}]}]}}`, js)
    93  }
    94  
    95  func TestRecurseExpand(t *testing.T) {
    96  
    97  	query := `
    98  		{
    99  			me(func: uid(32)) @recurse {
   100  				expand(_all_)
   101  			}
   102  		}`
   103  	js := processQueryNoErr(t, query)
   104  	require.JSONEq(t, `{"data":{"me":[{"school":[{"name":"San Mateo High School","district":[{"name":"San Mateo School District","county":[{"state":[{"name":"California","abbr":"CA"}],"name":"San Mateo County"}]}]}]}]}}`, js)
   105  }
   106  
   107  func TestRecurseExpandRepeatedPredError(t *testing.T) {
   108  
   109  	query := `
   110  		{
   111  			me(func: uid(32)) @recurse {
   112  				name
   113  				expand(_all_)
   114  			}
   115  		}`
   116  
   117  	_, err := processQuery(context.Background(), t, query)
   118  	require.Error(t, err)
   119  	require.Contains(t, err.Error(), "Repeated subgraph: [name] while using expand()")
   120  }
   121  
   122  func TestRecurseQueryOrder(t *testing.T) {
   123  
   124  	query := `
   125  		{
   126  			me(func: uid(0x01)) @recurse {
   127  				friend(orderdesc: dob)
   128  				dob
   129  				name
   130  			}
   131  		}`
   132  	js := processQueryNoErr(t, query)
   133  	require.JSONEq(t,
   134  		`{"data": {"me":[{"dob":"1910-01-01T00:00:00Z","friend":[{"dob":"1910-01-02T00:00:00Z","friend":[{"dob":"1910-01-01T00:00:00Z","name":"Michonne"}],"name":"Rick Grimes"},{"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"},{"dob":"1909-01-10T00:00:00Z","name":"Daryl Dixon"},{"dob":"1901-01-15T00:00:00Z","friend":[{"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"}],"name":"Andrea"}],"name":"Michonne"}]}}`,
   135  		js)
   136  }
   137  
   138  func TestRecurseQueryAllowLoop(t *testing.T) {
   139  
   140  	query := `
   141  		{
   142  			me(func: uid(0x01)) @recurse {
   143  				friend
   144  				dob
   145  				name
   146  			}
   147  		}`
   148  	js := processQueryNoErr(t, query)
   149  	require.JSONEq(t, `{"data":{"me":[{"friend":[{"friend":[{"dob":"1910-01-01T00:00:00Z","name":"Michonne"}],"dob":"1910-01-02T00:00:00Z","name":"Rick Grimes"},{"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"},{"dob":"1909-01-10T00:00:00Z","name":"Daryl Dixon"},{"friend":[{"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"}],"dob":"1901-01-15T00:00:00Z","name":"Andrea"}],"dob":"1910-01-01T00:00:00Z","name":"Michonne"}]}}`, js)
   150  }
   151  
   152  func TestRecurseQueryAllowLoop2(t *testing.T) {
   153  
   154  	query := `
   155  		{
   156  			me(func: uid(0x01)) @recurse(depth: 4,loop: true) {
   157  				friend
   158  				dob
   159  				name
   160  			}
   161  		}`
   162  	js := processQueryNoErr(t, query)
   163  	require.JSONEq(t, `{"data":{"me":[{"friend":[{"friend":[{"friend":[{"dob":"1910-01-02T00:00:00Z","name":"Rick Grimes"},{"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"},{"dob":"1909-01-10T00:00:00Z","name":"Daryl Dixon"},{"dob":"1901-01-15T00:00:00Z","name":"Andrea"}],"dob":"1910-01-01T00:00:00Z","name":"Michonne"}],"dob":"1910-01-02T00:00:00Z","name":"Rick Grimes"},{"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"},{"dob":"1909-01-10T00:00:00Z","name":"Daryl Dixon"},{"friend":[{"dob":"1909-05-05T00:00:00Z","name":"Glenn Rhee"}],"dob":"1901-01-15T00:00:00Z","name":"Andrea"}],"dob":"1910-01-01T00:00:00Z","name":"Michonne"}]}}`, js)
   164  }
   165  
   166  func TestRecurseQueryLimitDepth1(t *testing.T) {
   167  
   168  	query := `
   169  		{
   170  			me(func: uid(0x01)) @recurse(depth: 2) {
   171  				friend
   172  				name
   173  			}
   174  		}`
   175  	js := processQueryNoErr(t, query)
   176  	require.JSONEq(t,
   177  		`{"data": {"me":[{"name":"Michonne", "friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}]}}`, js)
   178  }
   179  
   180  func TestRecurseQueryLimitDepth2(t *testing.T) {
   181  
   182  	query := `
   183  		{
   184  			me(func: uid(0x01)) @recurse(depth: 2) {
   185  				uid
   186  				non_existent
   187  				friend
   188  				name
   189  			}
   190  		}`
   191  	js := processQueryNoErr(t, query)
   192  	require.JSONEq(t,
   193  		`{"data": {"me":[{"uid":"0x1","friend":[{"uid":"0x17","name":"Rick Grimes"},{"uid":"0x18","name":"Glenn Rhee"},{"uid":"0x19","name":"Daryl Dixon"},{"uid":"0x1f","name":"Andrea"},{"uid":"0x65"}],"name":"Michonne"}]}}`, js)
   194  }
   195  
   196  func TestRecurseVariable(t *testing.T) {
   197  
   198  	query := `
   199  			{
   200  				var(func: uid(0x01)) @recurse {
   201  					a as friend
   202  				}
   203  
   204  				me(func: uid(a)) {
   205  					name
   206  				}
   207  			}
   208  		`
   209  
   210  	js := processQueryNoErr(t, query)
   211  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"},{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`, js)
   212  }
   213  
   214  func TestRecurseVariableUid(t *testing.T) {
   215  
   216  	query := `
   217  			{
   218  				var(func: uid(0x01)) @recurse {
   219  					friend
   220  					a as uid
   221  				}
   222  
   223  				me(func: uid(a)) {
   224  					name
   225  				}
   226  			}
   227  		`
   228  
   229  	js := processQueryNoErr(t, query)
   230  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"},{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`, js)
   231  }
   232  
   233  func TestRecurseVariableVar(t *testing.T) {
   234  
   235  	query := `
   236  			{
   237  				var(func: uid(0x01)) @recurse {
   238  					friend
   239  					school
   240  					a as name
   241  				}
   242  
   243  				me(func: uid(a)) {
   244  					name
   245  				}
   246  			}
   247  		`
   248  
   249  	js := processQueryNoErr(t, query)
   250  	require.JSONEq(t, `{"data":{"me":[{"name":"Michonne"},{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"},{"name":"School A"},{"name":"School B"}]}}`, js)
   251  }
   252  
   253  func TestRecurseVariable2(t *testing.T) {
   254  
   255  	query := `
   256  			{
   257  
   258  				var(func: uid(0x1)) @recurse {
   259  					f2 as friend
   260  					f as follow
   261  				}
   262  
   263  				me(func: uid(f)) {
   264  					name
   265  				}
   266  
   267  				me2(func: uid(f2)) {
   268  					name
   269  				}
   270  			}
   271  	`
   272  	js := processQueryNoErr(t, query)
   273  	require.JSONEq(t, `{"data": {"me":[{"name":"Glenn Rhee"},{"name":"Andrea"},{"name":"Alice"},{"name":"Bob"},{"name":"Matt"},{"name":"John"}],"me2":[{"name":"Michonne"},{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`, js)
   274  }
   275  
   276  func TestShortestPath_ExpandError(t *testing.T) {
   277  
   278  	query := `
   279  		{
   280  			A as shortest(from:0x01, to:101) {
   281  				expand(_all_)
   282  			}
   283  
   284  			me(func: uid( A)) {
   285  				name
   286  			}
   287  		}`
   288  
   289  	_, err := processQuery(context.Background(), t, query)
   290  	require.Error(t, err)
   291  }
   292  
   293  func TestShortestPath_NoPath(t *testing.T) {
   294  
   295  	query := `
   296  		{
   297  			A as shortest(from:0x01, to:101) {
   298  				path
   299  				follow
   300  			}
   301  
   302  			me(func: uid(A)) {
   303  				name
   304  			}
   305  		}`
   306  	js := processQueryNoErr(t, query)
   307  	require.JSONEq(t, `{"data": {"me": []}}`, js)
   308  }
   309  
   310  func TestKShortestPath_NoPath(t *testing.T) {
   311  
   312  	query := `
   313  		{
   314  			A as shortest(from:0x01, to:101, numpaths: 2) {
   315  				path
   316  				nonexistent_pred
   317  				follow
   318  			}
   319  
   320  			me(func: uid(A)) {
   321  				name
   322  			}
   323  		}`
   324  	js := processQueryNoErr(t, query)
   325  	require.JSONEq(t, `{"data": {"me": []}}`, js)
   326  }
   327  
   328  func TestKShortestPathWeighted(t *testing.T) {
   329  
   330  	query := `
   331  		{
   332  			shortest(from: 1, to:1001, numpaths: 4) {
   333  				path @facets(weight)
   334  			}
   335  		}`
   336  	// We only get one path in this case as the facet is present only in one path.
   337  	js := processQueryNoErr(t, query)
   338  	require.JSONEq(t,
   339  		`{"data":{"_path_":[{"uid":"0x1","_weight_":0.3,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3e9","path|weight":0.100000},"path|weight":0.100000},"path|weight":0.100000}}]}}`,
   340  		js)
   341  }
   342  
   343  func TestKShortestPathWeightedMinMaxNoEffect(t *testing.T) {
   344  
   345  	query := `
   346  		{
   347  			shortest(from: 1, to:1001, numpaths: 4, minweight:0, maxweight: 1000) {
   348  				path @facets(weight)
   349  			}
   350  		}`
   351  	// We only get one path in this case as the facet is present only in one path.
   352  	// The path meets the weight requirements so it does not get filtered.
   353  	js := processQueryNoErr(t, query)
   354  	require.JSONEq(t,
   355  		`{"data":{"_path_":[{"uid":"0x1","_weight_":0.3,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3e9","path|weight":0.100000},"path|weight":0.100000},"path|weight":0.100000}}]}}`,
   356  		js)
   357  }
   358  
   359  func TestKShortestPathWeightedMinWeight(t *testing.T) {
   360  
   361  	query := `
   362  		{
   363  			shortest(from: 1, to:1001, numpaths: 4, minweight: 3) {
   364  				path @facets(weight)
   365  			}
   366  		}`
   367  	// We get no paths as the only path does not match the weight requirements.
   368  	js := processQueryNoErr(t, query)
   369  	require.JSONEq(t, `{"data":{}}`, js)
   370  }
   371  
   372  func TestKShortestPathWeightedMaxWeight(t *testing.T) {
   373  
   374  	query := `
   375  		{
   376  			shortest(from: 1, to:1001, numpaths: 4, maxweight: 0.1) {
   377  				path @facets(weight)
   378  			}
   379  		}`
   380  	// We get no paths as the only path does not match the weight requirements.
   381  	js := processQueryNoErr(t, query)
   382  	require.JSONEq(t, `{"data":{}}`, js)
   383  }
   384  
   385  func TestKShortestPathWeighted_LimitDepth(t *testing.T) {
   386  
   387  	query := `
   388  		{
   389  			shortest(from: 1, to:1001, depth:1, numpaths: 4) {
   390  				path @facets(weight)
   391  			}
   392  		}`
   393  	// We only get one path in this case as the facet is present only in one path.
   394  	js := processQueryNoErr(t, query)
   395  	require.JSONEq(t,
   396  		`{"data": {}}`,
   397  		js)
   398  }
   399  
   400  func TestKShortestPathWeighted1(t *testing.T) {
   401  
   402  	query := `
   403  		{
   404  			shortest(from: 1, to:1003, numpaths: 3) {
   405  				path @facets(weight)
   406  			}
   407  		}`
   408  	js := processQueryNoErr(t, query)
   409  	require.JSONEq(t,
   410  		`{"data":{"_path_":[
   411  			{"uid":"0x1","_weight_":1,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3e9","path":{"uid":"0x3ea","path":{"uid":"0x3eb","path|weight":0.600000},"path|weight":0.100000},"path|weight":0.100000},"path|weight":0.100000},"path|weight":0.100000}},
   412  			{"uid":"0x1","_weight_":1.5,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3ea","path":{"uid":"0x3eb","path|weight":0.600000},"path|weight":0.700000},"path|weight":0.100000},"path|weight":0.100000}},
   413  			{"uid":"0x1","_weight_":1.8,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3e9","path":{"uid":"0x3eb","path|weight":1.500000},"path|weight":0.100000},"path|weight":0.100000},"path|weight":0.100000}}]}}`,
   414  		js)
   415  }
   416  
   417  func TestKShortestPathWeighted1MinMaxWeight(t *testing.T) {
   418  
   419  	query := `
   420  		{
   421  			shortest(from: 1, to:1003, numpaths: 3, minweight: 1.3, maxweight: 1.5) {
   422  				path @facets(weight)
   423  			}
   424  		}`
   425  	js := processQueryNoErr(t, query)
   426  	require.JSONEq(t,
   427  		`{"data":{"_path_":[{"uid":"0x1","_weight_":1.5,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3ea","path":{"uid":"0x3eb","path|weight":0.600000},"path|weight":0.700000},"path|weight":0.100000},"path|weight":0.100000}}]}}`,
   428  		js)
   429  }
   430  
   431  func TestTwoShortestPath(t *testing.T) {
   432  
   433  	query := `
   434  		{
   435  			A as shortest(from: 1, to:1002, numpaths: 2) {
   436  				path
   437  			}
   438  
   439  			me(func: uid( A)) {
   440  				name
   441  			}
   442  		}`
   443  	js := processQueryNoErr(t, query)
   444  	require.JSONEq(t,
   445  		`{"data": {"_path_":[
   446  			{"uid":"0x1","_weight_":3,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3ea"}}}},
   447  			{"uid":"0x1","_weight_":4,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3e9","path":{"uid":"0x3ea"}}}}}],
   448  		"me":[{"name":"Michonne"},{"name":"Andrea"},{"name":"Alice"},{"name":"Matt"}]}}`,
   449  		js)
   450  }
   451  
   452  func TestTwoShortestPathMaxWeight(t *testing.T) {
   453  
   454  	query := `
   455  		{
   456  			A as shortest(from: 1, to:1002, numpaths: 2, maxweight:1) {
   457  				path
   458  			}
   459  
   460  			me(func: uid( A)) {
   461  				name
   462  			}
   463  		}`
   464  	js := processQueryNoErr(t, query)
   465  	require.JSONEq(t, `{"data": {"me":[]}}`, js)
   466  }
   467  
   468  func TestTwoShortestPathMinWeight(t *testing.T) {
   469  
   470  	query := `
   471  		{
   472  			A as shortest(from: 1, to:1002, numpaths: 2, minweight:10) {
   473  				path
   474  			}
   475  
   476  			me(func: uid( A)) {
   477  				name
   478  			}
   479  		}`
   480  	js := processQueryNoErr(t, query)
   481  	require.JSONEq(t, `{"data": {"me":[]}}`, js)
   482  }
   483  
   484  func TestShortestPath(t *testing.T) {
   485  	query := `
   486  		{
   487  			A as shortest(from:0x01, to:31) {
   488  				friend
   489  			}
   490  
   491  			me(func: uid( A)) {
   492  				name
   493  			}
   494  		}`
   495  	js := processQueryNoErr(t, query)
   496  	require.JSONEq(t,
   497  		`{"data": {"_path_":[{"uid":"0x1", "_weight_": 1, "friend":{"uid":"0x1f"}}],"me":[{"name":"Michonne"},{"name":"Andrea"}]}}`,
   498  		js)
   499  }
   500  
   501  func TestShortestPathRev(t *testing.T) {
   502  
   503  	query := `
   504  		{
   505  			A as shortest(from:23, to:1) {
   506  				friend
   507  			}
   508  
   509  			me(func: uid( A)) {
   510  				name
   511  			}
   512  		}`
   513  	js := processQueryNoErr(t, query)
   514  	require.JSONEq(t,
   515  		`{"data": {"_path_":[{"uid":"0x17","_weight_":1, "friend":{"uid":"0x1"}}],"me":[{"name":"Rick Grimes"},{"name":"Michonne"}]}}`,
   516  		js)
   517  }
   518  
   519  // Regression test for https://github.com/dgraph-io/dgraph/issues/3657.
   520  func TestShortestPathPassword(t *testing.T) {
   521  	query := `
   522  		{
   523  			A as shortest(from:0x01, to:31) {
   524  				password
   525  				friend
   526  			}
   527  
   528  			me(func: uid( A)) {
   529  				name
   530  			}
   531  		}`
   532  	js := processQueryNoErr(t, query)
   533  	require.JSONEq(t,
   534  		`{"data": {"_path_":[{"uid":"0x1", "_weight_": 1, "friend":{"uid":"0x1f"}}],
   535  			"me":[{"name":"Michonne"},{"name":"Andrea"}]}}`, js)
   536  }
   537  
   538  func TestShortestPathWithUidVariable(t *testing.T) {
   539  	query := `
   540  	{
   541  		a as var(func: uid(0x01))
   542  		b as var(func: uid(31))
   543  
   544  		shortest(from: uid(a), to: uid(b)) {
   545  			password
   546  			friend
   547  		}
   548  	}`
   549  	js := processQueryNoErr(t, query)
   550  	require.JSONEq(t,
   551  		`{"data": {"_path_":[{"uid":"0x1", "_weight_": 1, "friend":{"uid":"0x1f"}}]}}`, js)
   552  }
   553  
   554  func TestShortestPathWithUidVariableAndFunc(t *testing.T) {
   555  	query := `
   556  	{
   557  		a as var(func: eq(name, "Michonne"))
   558  		b as var(func: eq(name, "Andrea"))
   559  
   560  		shortest(from: uid(a), to: uid(b)) {
   561  			password
   562  			friend
   563  		}
   564  	}`
   565  	js := processQueryNoErr(t, query)
   566  	require.JSONEq(t,
   567  		`{"data": {"_path_":[{"uid":"0x1", "_weight_": 1, "friend":{"uid":"0x1f"}}]}}`, js)
   568  }
   569  
   570  func TestShortestPathWithUidVariableError(t *testing.T) {
   571  	query := `
   572  	{
   573  		a as var(func: eq(name, "Alice"))
   574  		b as var(func: eq(name, "Andrea"))
   575  
   576  		shortest(from: uid(a), to: uid(b)) {
   577  			password
   578  			friend
   579  		}
   580  	}`
   581  
   582  	_, err := processQuery(context.Background(), t, query)
   583  	require.Error(t, err)
   584  }
   585  
   586  func TestShortestPathWithUidVariableNoMatch(t *testing.T) {
   587  	query := `
   588  	{
   589  		a as var(func: eq(name, "blah blah"))
   590  		b as var(func: eq(name, "foo bar"))
   591  
   592  		shortest(from: uid(a), to: uid(b)) {
   593  			password
   594  			friend
   595  		}
   596  	}`
   597  	js := processQueryNoErr(t, query)
   598  	require.JSONEq(t, `{"data":{}}`, js)
   599  }
   600  
   601  func TestShortestPathWithUidVariableNoMatchForFrom(t *testing.T) {
   602  	query := `
   603  	{
   604  		a as var(func: eq(name, "blah blah"))
   605  		b as var(func: eq(name, "Michonne"))
   606  
   607  		shortest(from: uid(a), to: uid(b)) {
   608  			password
   609  			friend
   610  		}
   611  	}`
   612  	js := processQueryNoErr(t, query)
   613  	require.JSONEq(t, `{"data":{}}`, js)
   614  }
   615  
   616  func TestFacetVarRetrieval(t *testing.T) {
   617  
   618  	query := `
   619  		{
   620  			var(func: uid(1)) {
   621  				path @facets(f as weight)
   622  			}
   623  
   624  			me(func: uid( 24)) {
   625  				val(f)
   626  			}
   627  		}`
   628  	js := processQueryNoErr(t, query)
   629  	require.JSONEq(t,
   630  		`{"data": {"me":[{"val(f)":0.200000}]}}`,
   631  		js)
   632  }
   633  
   634  func TestFacetVarRetrieveOrder(t *testing.T) {
   635  
   636  	query := `
   637  		{
   638  			var(func: uid(1)) {
   639  				path @facets(f as weight)
   640  			}
   641  
   642  			me(func: uid(f), orderasc: val(f)) {
   643  				name
   644  				nonexistent_pred
   645  				val(f)
   646  			}
   647  		}`
   648  	js := processQueryNoErr(t, query)
   649  	require.JSONEq(t,
   650  		`{"data": {"me":[{"name":"Andrea","val(f)":0.100000},{"name":"Glenn Rhee","val(f)":0.200000}]}}`,
   651  		js)
   652  }
   653  
   654  func TestShortestPathWeightsMultiFacet_Error(t *testing.T) {
   655  
   656  	query := `
   657  		{
   658  			A as shortest(from:1, to:1002) {
   659  				path @facets(weight, weight1)
   660  			}
   661  
   662  			me(func: uid( A)) {
   663  				name
   664  			}
   665  		}`
   666  
   667  	_, err := processQuery(context.Background(), t, query)
   668  	require.Error(t, err)
   669  }
   670  
   671  func TestShortestPathWeights(t *testing.T) {
   672  
   673  	query := `
   674  		{
   675  			A as shortest(from:1, to:1002) {
   676  				path @facets(weight)
   677  			}
   678  
   679  			me(func: uid( A)) {
   680  				name
   681  			}
   682  		}`
   683  	js := processQueryNoErr(t, query)
   684  	require.JSONEq(t,
   685  		`{"data":{"me":[{"name":"Michonne"},{"name":"Andrea"},{"name":"Alice"},{"name":"Bob"},{"name":"Matt"}],"_path_":[{"uid":"0x1","_weight_":0.4,"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3e9","path":{"uid":"0x3ea","path|weight":0.100000},"path|weight":0.100000},"path|weight":0.100000},"path|weight":0.100000}}]}}`,
   686  		js)
   687  }
   688  
   689  func TestShortestPath2(t *testing.T) {
   690  
   691  	query := `
   692  		{
   693  			A as shortest(from:0x01, to:1000) {
   694  				path
   695  			}
   696  
   697  			me(func: uid( A)) {
   698  				name
   699  			}
   700  		}`
   701  	js := processQueryNoErr(t, query)
   702  	require.JSONEq(t,
   703  		`{"data": {"_path_":[{"uid":"0x1","_weight_":2,"path":{"uid":"0x1f","path":{"uid":"0x3e8"}}}],"me":[{"name":"Michonne"},{"name":"Andrea"},{"name":"Alice"}]}}
   704  `,
   705  		js)
   706  }
   707  
   708  func TestShortestPath4(t *testing.T) {
   709  
   710  	query := `
   711  		{
   712  			A as shortest(from:1, to:1003) {
   713  				path
   714  				follow
   715  			}
   716  
   717  			me(func: uid( A)) {
   718  				name
   719  			}
   720  		}`
   721  	js := processQueryNoErr(t, query)
   722  	require.JSONEq(t,
   723  		`{"data": {"_path_":[{"uid":"0x1","_weight_":3,"follow":{"uid":"0x1f","follow":{"uid":"0x3e9","follow":{"uid":"0x3eb"}}}}],"me":[{"name":"Michonne"},{"name":"Andrea"},{"name":"Bob"},{"name":"John"}]}}`,
   724  		js)
   725  }
   726  
   727  func TestShortestPath_filter(t *testing.T) {
   728  
   729  	query := `
   730  		{
   731  			A as shortest(from:1, to:1002) {
   732  				path @filter(not anyofterms(name, "alice"))
   733  				follow
   734  			}
   735  
   736  			me(func: uid(A)) {
   737  				name
   738  			}
   739  		}`
   740  	js := processQueryNoErr(t, query)
   741  	require.JSONEq(t,
   742  		`{"data": {"_path_":[{"uid":"0x1","_weight_":3,"follow":{"uid":"0x1f","follow":{"uid":"0x3e9","path":{"uid":"0x3ea"}}}}],"me":[{"name":"Michonne"},{"name":"Andrea"},{"name":"Bob"},{"name":"Matt"}]}}`,
   743  		js)
   744  }
   745  
   746  func TestShortestPath_filter2(t *testing.T) {
   747  
   748  	query := `
   749  		{
   750  			A as shortest(from:1, to:1002) {
   751  				path @filter(not anyofterms(name, "alice"))
   752  				follow @filter(not anyofterms(name, "bob"))
   753  			}
   754  
   755  			me(func: uid(A)) {
   756  				name
   757  			}
   758  		}`
   759  	js := processQueryNoErr(t, query)
   760  	require.JSONEq(t, `{"data": { "me": []}}`, js)
   761  }
   762  
   763  func TestTwoShortestPathVariable(t *testing.T) {
   764  
   765  	query := `
   766  		{
   767  			a as var(func: uid(1))
   768  			b as var(func: uid(1002))
   769  
   770  			A as shortest(from: uid(a), to: uid(b), numpaths: 2) {
   771  				path
   772  			}
   773  
   774  			me(func: uid(A)) {
   775  				name
   776  			}
   777  		}`
   778  	js := processQueryNoErr(t, query)
   779  	require.JSONEq(t,
   780  		`{"data": {"_path_":[
   781  			{"uid":"0x1","_weight_":3,"path":{"uid":"0x1f","path":{"uid":"0x3e8",
   782  			"path":{"uid":"0x3ea"}}}}, {"uid":"0x1","_weight_":4,
   783  			"path":{"uid":"0x1f","path":{"uid":"0x3e8","path":{"uid":"0x3e9",
   784  			"path":{"uid":"0x3ea"}}}}}], "me":[{"name":"Michonne"},{"name":"Andrea"}
   785  			,{"name":"Alice"},{"name":"Matt"}]}}`,
   786  		js)
   787  }
   788  
   789  func TestUseVarsFilterMultiId(t *testing.T) {
   790  
   791  	query := `
   792  		{
   793  			var(func: uid(0x01)) {
   794  				L as friend {
   795  					friend
   796  				}
   797  			}
   798  
   799  			var(func: uid(31)) {
   800  				G as friend
   801  			}
   802  
   803  			friend(func:anyofterms(name, "Michonne Andrea Glenn")) @filter(uid(G, L)) {
   804  				name
   805  			}
   806  		}
   807  	`
   808  	js := processQueryNoErr(t, query)
   809  	require.JSONEq(t,
   810  		`{"data": {"friend":[{"name":"Glenn Rhee"},{"name":"Andrea"}]}}`,
   811  		js)
   812  }
   813  
   814  func TestUseVarsMultiFilterId(t *testing.T) {
   815  
   816  	query := `
   817  		{
   818  			var(func: uid(0x01)) {
   819  				L as friend
   820  			}
   821  
   822  			var(func: uid(31)) {
   823  				G as friend
   824  			}
   825  
   826  			friend(func: uid(L)) @filter(uid(G)) {
   827  				name
   828  			}
   829  		}
   830  	`
   831  	js := processQueryNoErr(t, query)
   832  	require.JSONEq(t,
   833  		`{"data": {"friend":[{"name":"Glenn Rhee"}]}}`,
   834  		js)
   835  }
   836  
   837  func TestUseVarsCascade(t *testing.T) {
   838  
   839  	query := `
   840  		{
   841  			var(func: uid(0x01)) @cascade {
   842  				L as friend {
   843  				  friend
   844  				}
   845  			}
   846  
   847  			me(func: uid(L)) {
   848  				name
   849  			}
   850  		}
   851  	`
   852  	js := processQueryNoErr(t, query)
   853  	require.JSONEq(t,
   854  		`{"data": {"me":[{"name":"Rick Grimes"}, {"name":"Andrea"} ]}}`,
   855  		js)
   856  }
   857  
   858  func TestUseVars(t *testing.T) {
   859  
   860  	query := `
   861  		{
   862  			var(func: uid(0x01)) {
   863  				L as friend
   864  			}
   865  
   866  			me(func: uid(L)) {
   867  				name
   868  			}
   869  		}
   870  	`
   871  	js := processQueryNoErr(t, query)
   872  	require.JSONEq(t,
   873  		`{"data": {"me":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}]}}`,
   874  		js)
   875  }
   876  
   877  func TestGetUIDCount(t *testing.T) {
   878  
   879  	query := `
   880  		{
   881  			me(func: uid(0x01)) {
   882  				name
   883  				uid
   884  				gender
   885  				alive
   886  				count(friend)
   887  			}
   888  		}
   889  	`
   890  	js := processQueryNoErr(t, query)
   891  	require.JSONEq(t,
   892  		`{"data": {"me":[{"uid":"0x1","alive":true,"count(friend)":5,"gender":"female","name":"Michonne"}]}}`,
   893  		js)
   894  }
   895  
   896  func TestDebug1(t *testing.T) {
   897  
   898  	// Alright. Now we have everything set up. Let's create the query.
   899  	query := `
   900  		{
   901  			me(func: uid(0x01)) {
   902  				name
   903  				gender
   904  				alive
   905  				count(friend)
   906  			}
   907  		}
   908  	`
   909  
   910  	md := metadata.Pairs("debug", "true")
   911  	ctx := context.Background()
   912  	ctx = metadata.NewOutgoingContext(ctx, md)
   913  
   914  	buf, _ := processQuery(ctx, t, query)
   915  
   916  	var mp map[string]interface{}
   917  	require.NoError(t, json.Unmarshal([]byte(buf), &mp))
   918  
   919  	data := mp["data"].(map[string]interface{})
   920  	resp := data["me"]
   921  	uid := resp.([]interface{})[0].(map[string]interface{})["uid"].(string)
   922  	require.EqualValues(t, "0x1", uid)
   923  }
   924  
   925  func TestDebug2(t *testing.T) {
   926  
   927  	query := `
   928  		{
   929  			me(func: uid(0x01)) {
   930  				name
   931  				gender
   932  				alive
   933  				count(friend)
   934  			}
   935  		}
   936  	`
   937  
   938  	js := processQueryNoErr(t, query)
   939  	var mp map[string]interface{}
   940  	require.NoError(t, json.Unmarshal([]byte(js), &mp))
   941  
   942  	resp := mp["data"].(map[string]interface{})["me"]
   943  	uid, ok := resp.([]interface{})[0].(map[string]interface{})["uid"].(string)
   944  	require.False(t, ok, "No uid expected but got one %s", uid)
   945  }
   946  
   947  func TestDebug3(t *testing.T) {
   948  
   949  	// Alright. Now we have everything set up. Let's create the query.
   950  	query := `
   951  		{
   952  			me(func: uid(1, 24)) @filter(ge(dob, "1910-01-01")) {
   953  				name
   954  			}
   955  		}
   956  	`
   957  	md := metadata.Pairs("debug", "true")
   958  	ctx := context.Background()
   959  	ctx = metadata.NewOutgoingContext(ctx, md)
   960  
   961  	buf, err := processQuery(ctx, t, query)
   962  	require.NoError(t, err)
   963  
   964  	var mp map[string]interface{}
   965  	require.NoError(t, json.Unmarshal([]byte(buf), &mp))
   966  
   967  	resp := mp["data"].(map[string]interface{})["me"]
   968  	require.NotNil(t, resp)
   969  	require.EqualValues(t, 1, len(resp.([]interface{})))
   970  	uid := resp.([]interface{})[0].(map[string]interface{})["uid"].(string)
   971  	require.EqualValues(t, "0x1", uid)
   972  }
   973  
   974  func TestCount(t *testing.T) {
   975  
   976  	// Alright. Now we have everything set up. Let's create the query.
   977  	query := `
   978  		{
   979  			me(func: uid(0x01)) {
   980  				name
   981  				gender
   982  				alive
   983  				count(friend)
   984  			}
   985  		}
   986  	`
   987  
   988  	js := processQueryNoErr(t, query)
   989  	require.JSONEq(t,
   990  		`{"data": {"me":[{"alive":true,"count(friend)":5,"gender":"female","name":"Michonne"}]}}`,
   991  		js)
   992  }
   993  func TestCountAlias(t *testing.T) {
   994  
   995  	// Alright. Now we have everything set up. Let's create the query.
   996  	query := `
   997  		{
   998  			me(func: uid(0x01)) {
   999  				name
  1000  				gender
  1001  				alive
  1002  				friendCount: count(friend)
  1003  			}
  1004  		}
  1005  	`
  1006  
  1007  	js := processQueryNoErr(t, query)
  1008  	require.JSONEq(t,
  1009  		`{"data": {"me":[{"alive":true,"friendCount":5,"gender":"female","name":"Michonne"}]}}`,
  1010  		js)
  1011  }
  1012  
  1013  func TestCountError1(t *testing.T) {
  1014  	// Alright. Now we have everything set up. Let's create the query.
  1015  	query := `
  1016  		{
  1017  			me(func: uid( 0x01)) {
  1018  				count(friend {
  1019  					name
  1020  				})
  1021  				name
  1022  				gender
  1023  				alive
  1024  			}
  1025  		}
  1026  	`
  1027  	_, err := processQuery(context.Background(), t, query)
  1028  	require.Error(t, err)
  1029  }
  1030  
  1031  func TestCountError2(t *testing.T) {
  1032  	// Alright. Now we have everything set up. Let's create the query.
  1033  	query := `
  1034  		{
  1035  			me(func: uid( 0x01)) {
  1036  				count(friend {
  1037  					c {
  1038  						friend
  1039  					}
  1040  				})
  1041  				name
  1042  				gender
  1043  				alive
  1044  			}
  1045  		}
  1046  	`
  1047  	_, err := processQuery(context.Background(), t, query)
  1048  	require.Error(t, err)
  1049  }
  1050  
  1051  func TestCountError3(t *testing.T) {
  1052  	// Alright. Now we have everything set up. Let's create the query.
  1053  	query := `
  1054  		{
  1055  			me(func: uid( 0x01)) {
  1056  				count(friend
  1057  				name
  1058  				gender
  1059  				alive
  1060  			}
  1061  		}
  1062  	`
  1063  	_, err := processQuery(context.Background(), t, query)
  1064  	require.Error(t, err)
  1065  }
  1066  
  1067  func TestMultiCountSort(t *testing.T) {
  1068  
  1069  	// Alright. Now we have everything set up. Let's create the query.
  1070  	query := `
  1071  	{
  1072  		f as var(func: anyofterms(name, "michonne rick andrea")) {
  1073  		 	n as count(friend)
  1074  		}
  1075  
  1076  		countorder(func: uid(f), orderasc: val(n)) {
  1077  			name
  1078  			count(friend)
  1079  		}
  1080  	}
  1081  `
  1082  	js := processQueryNoErr(t, query)
  1083  	require.JSONEq(t,
  1084  		`{"data": {"countorder":[{"count(friend)":0,"name":"Andrea With no friends"},{"count(friend)":1,"name":"Rick Grimes"},{"count(friend)":1,"name":"Andrea"},{"count(friend)":5,"name":"Michonne"}]}}`,
  1085  		js)
  1086  }
  1087  
  1088  func TestMultiLevelAgg(t *testing.T) {
  1089  
  1090  	// Alright. Now we have everything set up. Let's create the query.
  1091  	query := `
  1092  	{
  1093  		sumorder(func: anyofterms(name, "michonne rick andrea")) {
  1094  			name
  1095  			friend {
  1096  				s as count(friend)
  1097  			}
  1098  			sum(val(s))
  1099  		}
  1100  	}
  1101  `
  1102  	js := processQueryNoErr(t, query)
  1103  	require.JSONEq(t,
  1104  		`{"data": {"sumorder":[{"friend":[{"count(friend)":1},{"count(friend)":0},{"count(friend)":0},{"count(friend)":1},{"count(friend)":0}],"name":"Michonne","sum(val(s))":2},{"friend":[{"count(friend)":5}],"name":"Rick Grimes","sum(val(s))":5},{"friend":[{"count(friend)":0}],"name":"Andrea","sum(val(s))":0},{"name":"Andrea With no friends"}]}}`,
  1105  		js)
  1106  }
  1107  
  1108  func TestMultiLevelAgg1(t *testing.T) {
  1109  
  1110  	// Alright. Now we have everything set up. Let's create the query.
  1111  	query := `
  1112  	{
  1113  		var(func: anyofterms(name, "michonne rick andrea")) @filter(gt(count(friend), 0)){
  1114  			friend {
  1115  				s as count(friend)
  1116  			}
  1117  			ss as sum(val(s))
  1118  		}
  1119  
  1120  		sumorder(func: uid(ss), orderasc: val(ss)) {
  1121  			name
  1122  			val(ss)
  1123  		}
  1124  	}
  1125  `
  1126  	js := processQueryNoErr(t, query)
  1127  	require.JSONEq(t,
  1128  		`{"data": {"sumorder":[{"name":"Andrea","val(ss)":0},{"name":"Michonne","val(ss)":2},{"name":"Rick Grimes","val(ss)":5}]}}`,
  1129  		js)
  1130  }
  1131  
  1132  func TestMultiLevelAgg1Error(t *testing.T) {
  1133  
  1134  	// Alright. Now we have everything set up. Let's create the query.
  1135  	query := `
  1136  	{
  1137  		var(func: anyofterms(name, "michonne rick andrea")) @filter(gt(count(friend), 0)){
  1138  			friend {
  1139  				s as count(friend)
  1140  				ss as sum(val(s))
  1141  			}
  1142  		}
  1143  
  1144  		sumorder(func: uid(ss), orderasc: val(ss)) {
  1145  			name
  1146  			val(ss)
  1147  		}
  1148  	}
  1149  `
  1150  	_, err := processQuery(context.Background(), t, query)
  1151  	require.Error(t, err)
  1152  }
  1153  
  1154  func TestMultiAggSort(t *testing.T) {
  1155  
  1156  	// Alright. Now we have everything set up. Let's create the query.
  1157  	query := `
  1158  	{
  1159  		f as var(func: anyofterms(name, "michonne rick andrea")) {
  1160  			name
  1161  			friend {
  1162  				x as dob
  1163  			}
  1164  			mindob as min(val(x))
  1165  			maxdob as max(val(x))
  1166  		}
  1167  
  1168  		maxorder(func: uid(f), orderasc: val(maxdob)) {
  1169  			name
  1170  			val(maxdob)
  1171  		}
  1172  
  1173  		minorder(func: uid(f), orderasc: val(mindob)) {
  1174  			name
  1175  			val(mindob)
  1176  		}
  1177  	}
  1178  `
  1179  	js := processQueryNoErr(t, query)
  1180  	require.JSONEq(t,
  1181  		`{"data": {"maxorder":[{"name":"Andrea","val(maxdob)":"1909-05-05T00:00:00Z"},{"name":"Rick Grimes","val(maxdob)":"1910-01-01T00:00:00Z"},{"name":"Michonne","val(maxdob)":"1910-01-02T00:00:00Z"}],"minorder":[{"name":"Michonne","val(mindob)":"1901-01-15T00:00:00Z"},{"name":"Andrea","val(mindob)":"1909-05-05T00:00:00Z"},{"name":"Rick Grimes","val(mindob)":"1910-01-01T00:00:00Z"}]}}`,
  1182  		js)
  1183  }
  1184  
  1185  func TestMinMulti(t *testing.T) {
  1186  
  1187  	// Alright. Now we have everything set up. Let's create the query.
  1188  	query := `
  1189  	{
  1190  		me(func: anyofterms(name, "michonne rick andrea")) {
  1191  			name
  1192  			friend {
  1193  				x as dob
  1194  			}
  1195  			min(val(x))
  1196  			max(val(x))
  1197  		}
  1198  	}
  1199  `
  1200  	js := processQueryNoErr(t, query)
  1201  	require.JSONEq(t,
  1202  		`{"data": {"me":[{"friend":[{"dob":"1910-01-02T00:00:00Z"},{"dob":"1909-05-05T00:00:00Z"},{"dob":"1909-01-10T00:00:00Z"},{"dob":"1901-01-15T00:00:00Z"}],"max(val(x))":"1910-01-02T00:00:00Z","min(val(x))":"1901-01-15T00:00:00Z","name":"Michonne"},{"friend":[{"dob":"1910-01-01T00:00:00Z"}],"max(val(x))":"1910-01-01T00:00:00Z","min(val(x))":"1910-01-01T00:00:00Z","name":"Rick Grimes"},{"friend":[{"dob":"1909-05-05T00:00:00Z"}],"max(val(x))":"1909-05-05T00:00:00Z","min(val(x))":"1909-05-05T00:00:00Z","name":"Andrea"},{"name":"Andrea With no friends"}]}}`,
  1203  		js)
  1204  }
  1205  
  1206  func TestMinMultiAlias(t *testing.T) {
  1207  
  1208  	// Alright. Now we have everything set up. Let's create the query.
  1209  	query := `
  1210  	{
  1211  		me(func: anyofterms(name, "michonne rick andrea")) {
  1212  			name
  1213  			friend {
  1214  				x as dob
  1215  			}
  1216  			mindob: min(val(x))
  1217  			maxdob: max(val(x))
  1218  		}
  1219  	}
  1220  `
  1221  	js := processQueryNoErr(t, query)
  1222  	require.JSONEq(t,
  1223  		`{"data": {"me":[{"friend":[{"dob":"1910-01-02T00:00:00Z"},{"dob":"1909-05-05T00:00:00Z"},{"dob":"1909-01-10T00:00:00Z"},{"dob":"1901-01-15T00:00:00Z"}],"maxdob":"1910-01-02T00:00:00Z","mindob":"1901-01-15T00:00:00Z","name":"Michonne"},{"friend":[{"dob":"1910-01-01T00:00:00Z"}],"maxdob":"1910-01-01T00:00:00Z","mindob":"1910-01-01T00:00:00Z","name":"Rick Grimes"},{"friend":[{"dob":"1909-05-05T00:00:00Z"}],"maxdob":"1909-05-05T00:00:00Z","mindob":"1909-05-05T00:00:00Z","name":"Andrea"},{"name":"Andrea With no friends"}]}}`,
  1224  		js)
  1225  }
  1226  
  1227  func TestMinSchema(t *testing.T) {
  1228  
  1229  	// Alright. Now we have everything set up. Let's create the query.
  1230  	query := `
  1231                  {
  1232                          me(func: uid(0x01)) {
  1233                                  name
  1234                                  gender
  1235                                  alive
  1236                                  friend {
  1237  									x as survival_rate
  1238                                  }
  1239  								min(val(x))
  1240                          }
  1241                  }
  1242          `
  1243  	js := processQueryNoErr(t, query)
  1244  	require.JSONEq(t,
  1245  		`{"data": {"me":[{"name":"Michonne","gender":"female","alive":true,"friend":[{"survival_rate":1.600000},{"survival_rate":1.600000},{"survival_rate":1.600000},{"survival_rate":1.600000}],"min(val(x))":1.600000}]}}`,
  1246  		js)
  1247  
  1248  	setSchema(`survival_rate: int .`)
  1249  
  1250  	js = processQueryNoErr(t, query)
  1251  	require.JSONEq(t,
  1252  		`{"data": {"me":[{"name":"Michonne","gender":"female","alive":true,"friend":[{"survival_rate":1},{"survival_rate":1},{"survival_rate":1},{"survival_rate":1}],"min(val(x))":1}]}}`,
  1253  		js)
  1254  	setSchema(`survival_rate: float .`)
  1255  }
  1256  
  1257  func TestAvg(t *testing.T) {
  1258  
  1259  	query := `
  1260  	{
  1261  		me(func: uid(0x01)) {
  1262  			name
  1263  			gender
  1264  			alive
  1265  			friend {
  1266  				x as shadow_deep
  1267  			}
  1268  			avg(val(x))
  1269  		}
  1270  	}
  1271  `
  1272  	js := processQueryNoErr(t, query)
  1273  	require.JSONEq(t,
  1274  		`{"data": {"me":[{"alive":true,"avg(val(x))":9.000000,"friend":[{"shadow_deep":4},{"shadow_deep":14}],"gender":"female","name":"Michonne"}]}}`,
  1275  		js)
  1276  }
  1277  
  1278  func TestSum(t *testing.T) {
  1279  
  1280  	query := `
  1281                  {
  1282                          me(func: uid(0x01)) {
  1283                                  name
  1284                                  gender
  1285                                  alive
  1286                                  friend {
  1287                                      x as shadow_deep
  1288                                  }
  1289  								sum(val(x))
  1290                          }
  1291                  }
  1292          `
  1293  	js := processQueryNoErr(t, query)
  1294  	require.JSONEq(t,
  1295  		`{"data": {"me":[{"alive":true,"friend":[{"shadow_deep":4},{"shadow_deep":14}],"gender":"female","name":"Michonne","sum(val(x))":18}]}}`,
  1296  		js)
  1297  }
  1298  
  1299  func TestQueryPassword(t *testing.T) {
  1300  
  1301  	// Password is not fetchable
  1302  	query := `
  1303                  {
  1304                          me(func: uid(0x01)) {
  1305                                  name
  1306                                  password
  1307                          }
  1308                  }
  1309  	`
  1310  	js := processQueryNoErr(t, query)
  1311  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"}]}}`, js)
  1312  }
  1313  
  1314  func TestPasswordExpandAll1(t *testing.T) {
  1315  	query := `
  1316      {
  1317          me(func: uid(0x01)) {
  1318  			expand(_all_)
  1319  		}
  1320      }
  1321  	`
  1322  	js := processQueryNoErr(t, query)
  1323  	require.JSONEq(t, `{"data":{"me":[{"name":"Michonne"}]}}`, js)
  1324  }
  1325  
  1326  func TestPasswordExpandAll2(t *testing.T) {
  1327  	query := `
  1328      {
  1329          me(func: uid(0x01)) {
  1330  			expand(_all_)
  1331  			checkpwd(password, "12345")
  1332  		}
  1333      }
  1334  	`
  1335  	js := processQueryNoErr(t, query)
  1336  	require.JSONEq(t, `{"data":{"me":[{"name":"Michonne", "checkpwd(password)":false}]}}`, js)
  1337  }
  1338  
  1339  func TestPasswordExpandError(t *testing.T) {
  1340  	query := `
  1341      {
  1342          me(func: uid(0x01)) {
  1343  			expand(_all_)
  1344  			password
  1345  		}
  1346      }
  1347  	`
  1348  
  1349  	_, err := processQuery(context.Background(), t, query)
  1350  	require.Contains(t, err.Error(), "Repeated subgraph: [password]")
  1351  }
  1352  
  1353  func TestCheckPassword(t *testing.T) {
  1354  	query := `
  1355                  {
  1356                          me(func: uid(0x01)) {
  1357                                  name
  1358                                  checkpwd(password, "123456")
  1359                          }
  1360                  }
  1361  	`
  1362  	js := processQueryNoErr(t, query)
  1363  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","checkpwd(password)":true}]}}`, js)
  1364  }
  1365  
  1366  func TestCheckPasswordIncorrect(t *testing.T) {
  1367  	query := `
  1368                  {
  1369                          me(func: uid(0x01)) {
  1370                                  name
  1371                                  checkpwd(password, "654123")
  1372                          }
  1373                  }
  1374  	`
  1375  	js := processQueryNoErr(t, query)
  1376  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","checkpwd(password)":false}]}}`, js)
  1377  }
  1378  
  1379  // ensure, that old and deprecated form is not allowed
  1380  func TestCheckPasswordParseError(t *testing.T) {
  1381  	query := `
  1382                  {
  1383                          me(func: uid(0x01)) {
  1384                                  name
  1385                                  checkpwd("654123")
  1386                          }
  1387                  }
  1388  	`
  1389  	_, err := processQuery(context.Background(), t, query)
  1390  	require.Error(t, err)
  1391  }
  1392  
  1393  func TestCheckPasswordDifferentAttr1(t *testing.T) {
  1394  
  1395  	query := `
  1396                  {
  1397                          me(func: uid(23)) {
  1398                                  name
  1399                                  checkpwd(pass, "654321")
  1400                          }
  1401                  }
  1402  	`
  1403  	js := processQueryNoErr(t, query)
  1404  	require.JSONEq(t, `{"data": {"me":[{"name":"Rick Grimes","checkpwd(pass)":true}]}}`, js)
  1405  }
  1406  
  1407  func TestCheckPasswordDifferentAttr2(t *testing.T) {
  1408  
  1409  	query := `
  1410                  {
  1411                          me(func: uid(23)) {
  1412                                  name
  1413                                  checkpwd(pass, "invalid")
  1414                          }
  1415                  }
  1416  	`
  1417  	js := processQueryNoErr(t, query)
  1418  	require.JSONEq(t, `{"data": {"me":[{"name":"Rick Grimes","checkpwd(pass)":false}]}}`, js)
  1419  }
  1420  
  1421  func TestCheckPasswordInvalidAttr(t *testing.T) {
  1422  
  1423  	query := `
  1424                  {
  1425                          me(func: uid(0x1)) {
  1426                                  name
  1427                                  checkpwd(pass, "123456")
  1428                          }
  1429                  }
  1430  	`
  1431  	js := processQueryNoErr(t, query)
  1432  	// for id:0x1 there is no pass attribute defined (there's only password attribute)
  1433  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","checkpwd(pass)":false}]}}`, js)
  1434  }
  1435  
  1436  // test for old version of checkpwd with hardcoded attribute name
  1437  func TestCheckPasswordQuery1(t *testing.T) {
  1438  
  1439  	query := `
  1440                  {
  1441                          me(func: uid(0x1)) {
  1442                                  name
  1443                                  password
  1444                          }
  1445                  }
  1446  	`
  1447  	js := processQueryNoErr(t, query)
  1448  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne"}]}}`, js)
  1449  }
  1450  
  1451  // test for improved version of checkpwd with custom attribute name
  1452  func TestCheckPasswordQuery2(t *testing.T) {
  1453  
  1454  	query := `
  1455                  {
  1456                          me(func: uid(23)) {
  1457                                  name
  1458                                  pass
  1459                          }
  1460                  }
  1461  	`
  1462  	js := processQueryNoErr(t, query)
  1463  	require.JSONEq(t, `{"data": {"me":[{"name":"Rick Grimes"}]}}`, js)
  1464  }
  1465  
  1466  // test for improved version of checkpwd with alias for unknown attribute
  1467  func TestCheckPasswordQuery3(t *testing.T) {
  1468  
  1469  	query := `
  1470                  {
  1471                          me(func: uid(23)) {
  1472                                  name
  1473  								secret: checkpwd(pass, "123456")
  1474                          }
  1475                  }
  1476  	`
  1477  	js := processQueryNoErr(t, query)
  1478  	require.JSONEq(t, `{"data": {"me":[{"name":"Rick Grimes","secret":false}]}}`, js)
  1479  }
  1480  
  1481  // test for improved version of checkpwd with alias for known attribute
  1482  func TestCheckPasswordQuery4(t *testing.T) {
  1483  
  1484  	query := `
  1485                  {
  1486                          me(func: uid(0x01)) {
  1487                                  name
  1488  								secreto: checkpwd(password, "123456")
  1489                          }
  1490                  }
  1491  	`
  1492  	js := processQueryNoErr(t, query)
  1493  	require.JSONEq(t, `{"data": {"me":[{"name":"Michonne","secreto":true}]}}`, js)
  1494  }
  1495  
  1496  func TestToSubgraphInvalidFnName(t *testing.T) {
  1497  	query := `
  1498                  {
  1499                          me(func:invalidfn1(name, "some cool name")) {
  1500                                  name
  1501                                  gender
  1502                                  alive
  1503                          }
  1504                  }
  1505          `
  1506  	_, err := processQuery(context.Background(), t, query)
  1507  	require.Error(t, err)
  1508  	require.Contains(t, err.Error(), "Function name: invalidfn1 is not valid.")
  1509  }
  1510  
  1511  func TestToSubgraphInvalidFnName2(t *testing.T) {
  1512  	query := `
  1513                  {
  1514                          me(func:anyofterms(name, "some cool name")) {
  1515                                  name
  1516                                  friend @filter(invalidfn2(name, "some name")) {
  1517                                         name
  1518                                  }
  1519                          }
  1520                  }
  1521          `
  1522  	_, err := processQuery(context.Background(), t, query)
  1523  	require.Error(t, err)
  1524  }
  1525  
  1526  func TestToSubgraphInvalidFnName3(t *testing.T) {
  1527  	query := `
  1528                  {
  1529                          me(func:anyofterms(name, "some cool name")) {
  1530                                  name
  1531                                  friend @filter(anyofterms(name, "Andrea") or
  1532                                                 invalidfn3(name, "Andrea Rhee")){
  1533                                          name
  1534                                  }
  1535                          }
  1536                  }
  1537          `
  1538  	_, err := processQuery(context.Background(), t, query)
  1539  	require.Error(t, err)
  1540  }
  1541  
  1542  func TestToSubgraphInvalidFnName4(t *testing.T) {
  1543  	query := `
  1544                  {
  1545                          f as var(func:invalidfn4(name, "Michonne Rick Glenn")) {
  1546                                  name
  1547                          }
  1548                          you(func:anyofterms(name, "Michonne")) {
  1549                                  friend @filter(uid(f)) {
  1550                                          name
  1551                                  }
  1552                          }
  1553                  }
  1554          `
  1555  	_, err := processQuery(context.Background(), t, query)
  1556  	require.Error(t, err)
  1557  	require.Contains(t, err.Error(), "Function name: invalidfn4 is not valid.")
  1558  }
  1559  
  1560  func TestToSubgraphInvalidArgs1(t *testing.T) {
  1561  	query := `
  1562                  {
  1563                          me(func: uid(0x01)) {
  1564                                  name
  1565                                  gender
  1566                                  friend(disorderasc: dob) @filter(le(dob, "1909-03-20")) {
  1567                                          name
  1568                                  }
  1569                          }
  1570                  }
  1571          `
  1572  	_, err := processQuery(context.Background(), t, query)
  1573  	require.Error(t, err)
  1574  	require.Contains(t, err.Error(), "Got invalid keyword: disorderasc")
  1575  }
  1576  
  1577  func TestToSubgraphInvalidArgs2(t *testing.T) {
  1578  	query := `
  1579                  {
  1580                          me(func: uid(0x01)) {
  1581                                  name
  1582                                  gender
  1583                                  friend(offset:1, invalidorderasc:1) @filter(anyofterms(name, "Andrea")) {
  1584                                          name
  1585                                  }
  1586                          }
  1587                  }
  1588          `
  1589  	_, err := processQuery(context.Background(), t, query)
  1590  	require.Error(t, err)
  1591  	require.Contains(t, err.Error(), "Got invalid keyword: invalidorderasc")
  1592  }
  1593  
  1594  func TestToFastJSON(t *testing.T) {
  1595  
  1596  	// Alright. Now we have everything set up. Let's create the query.
  1597  	query := `
  1598  		{
  1599  			me(func: uid(0x01)) {
  1600  				name
  1601  				gender
  1602  				alive
  1603  				friend {
  1604  					name
  1605  				}
  1606  			}
  1607  		}
  1608  	`
  1609  
  1610  	js := processQueryNoErr(t, query)
  1611  	require.JSONEq(t,
  1612  		`{"data": {"me":[{"alive":true,"friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"},{"name":"Daryl Dixon"},{"name":"Andrea"}],"gender":"female","name":"Michonne"}]}}`,
  1613  		js)
  1614  }
  1615  
  1616  func TestFieldAlias(t *testing.T) {
  1617  
  1618  	// Alright. Now we have everything set up. Let's create the query.
  1619  	query := `
  1620  		{
  1621  			me(func: uid(0x01)) {
  1622  				MyName:name
  1623  				gender
  1624  				alive
  1625  				Buddies:friend {
  1626  					BudName:name
  1627  				}
  1628  			}
  1629  		}
  1630  	`
  1631  
  1632  	js := processQueryNoErr(t, query)
  1633  	require.JSONEq(t,
  1634  		`{"data": {"me":[{"alive":true,"Buddies":[{"BudName":"Rick Grimes"},{"BudName":"Glenn Rhee"},{"BudName":"Daryl Dixon"},{"BudName":"Andrea"}],"gender":"female","MyName":"Michonne"}]}}`,
  1635  		js)
  1636  }
  1637  
  1638  func TestToFastJSONFilter(t *testing.T) {
  1639  
  1640  	query := `
  1641  		{
  1642  			me(func: uid(0x01)) {
  1643  				name
  1644  				gender
  1645  				friend @filter(anyofterms(name, "Andrea SomethingElse")) {
  1646  					name
  1647  				}
  1648  			}
  1649  		}
  1650  	`
  1651  
  1652  	js := processQueryNoErr(t, query)
  1653  	require.JSONEq(t,
  1654  		`{"data": {"me":[{"name":"Michonne","gender":"female","friend":[{"name":"Andrea"}]}]}}`,
  1655  		js)
  1656  }
  1657  
  1658  func TestToFastJSONFilterMissBrac(t *testing.T) {
  1659  
  1660  	query := `
  1661  		{
  1662  			me(func: uid(0x01)) {
  1663  				name
  1664  				gender
  1665  				friend @filter(anyofterms(name, "Andrea SomethingElse") {
  1666  					name
  1667  				}
  1668  			}
  1669  		}
  1670  	`
  1671  	_, err := processQuery(context.Background(), t, query)
  1672  	require.Error(t, err)
  1673  }
  1674  
  1675  func TestToFastJSONFilterallofterms(t *testing.T) {
  1676  
  1677  	query := `
  1678  		{
  1679  			me(func: uid(0x01)) {
  1680  				name
  1681  				gender
  1682  				friend @filter(allofterms(name, "Andrea SomethingElse")) {
  1683  					name
  1684  				}
  1685  			}
  1686  		}
  1687  	`
  1688  
  1689  	js := processQueryNoErr(t, query)
  1690  	require.JSONEq(t,
  1691  		`{"data": {"me":[{"name":"Michonne","gender":"female"}]}}`, js)
  1692  }
  1693  
  1694  func TestInvalidStringIndex(t *testing.T) {
  1695  	// no FTS index defined for name
  1696  
  1697  	query := `
  1698  		{
  1699  			me(func: uid(0x01)) {
  1700  				name
  1701  				gender
  1702  				friend @filter(alloftext(name, "Andrea SomethingElse")) {
  1703  					name
  1704  				}
  1705  			}
  1706  		}
  1707  	`
  1708  
  1709  	_, err := processQuery(context.Background(), t, query)
  1710  	require.Error(t, err)
  1711  }
  1712  
  1713  func TestValidFullTextIndex(t *testing.T) {
  1714  	// no FTS index defined for name
  1715  
  1716  	query := `
  1717  		{
  1718  			me(func: uid(0x01)) {
  1719  				name
  1720  				friend @filter(alloftext(alias, "BOB")) {
  1721  					alias
  1722  				}
  1723  			}
  1724  		}
  1725  	`
  1726  
  1727  	js := processQueryNoErr(t, query)
  1728  	require.JSONEq(t,
  1729  		`{"data": {"me":[{"name":"Michonne", "friend":[{"alias":"Bob Joe"}]}]}}`, js)
  1730  }
  1731  
  1732  // dob (date of birth) is not a string
  1733  func TestFilterRegexError(t *testing.T) {
  1734  
  1735  	query := `
  1736      {
  1737        me(func: uid(0x01)) {
  1738          name
  1739          friend @filter(regexp(dob, /^[a-z A-Z]+$/)) {
  1740            name
  1741          }
  1742        }
  1743      }
  1744  `
  1745  
  1746  	_, err := processQuery(context.Background(), t, query)
  1747  	require.Error(t, err)
  1748  }
  1749  
  1750  func TestFilterRegex1(t *testing.T) {
  1751  
  1752  	query := `
  1753      {
  1754        me(func: uid(0x01)) {
  1755          name
  1756          friend @filter(regexp(name, /^[Glen Rh]+$/)) {
  1757            name
  1758          }
  1759        }
  1760      }
  1761  `
  1762  
  1763  	js := processQueryNoErr(t, query)
  1764  	require.JSONEq(t,
  1765  		`{"data": {"me":[{"name":"Michonne", "friend":[{"name":"Glenn Rhee"}]}]}}`, js)
  1766  }
  1767  
  1768  func TestFilterRegex2(t *testing.T) {
  1769  
  1770  	query := `
  1771      {
  1772        me(func: uid(0x01)) {
  1773          name
  1774          friend @filter(regexp(name, /^[^ao]+$/)) {
  1775            name
  1776          }
  1777        }
  1778      }
  1779  `
  1780  
  1781  	js := processQueryNoErr(t, query)
  1782  	require.JSONEq(t,
  1783  		`{"data": {"me":[{"name":"Michonne", "friend":[{"name":"Rick Grimes"},{"name":"Glenn Rhee"}]}]}}`, js)
  1784  }
  1785  
  1786  func TestFilterRegex3(t *testing.T) {
  1787  
  1788  	query := `
  1789      {
  1790        me(func: uid(0x01)) {
  1791          name
  1792          friend @filter(regexp(name, /^Rick/)) {
  1793            name
  1794          }
  1795        }
  1796      }
  1797  `
  1798  
  1799  	js := processQueryNoErr(t, query)
  1800  	require.JSONEq(t,
  1801  		`{"data": {"me":[{"name":"Michonne", "friend":[{"name":"Rick Grimes"}]}]}}`, js)
  1802  }
  1803  
  1804  func TestFilterRegex4(t *testing.T) {
  1805  
  1806  	query := `
  1807      {
  1808        me(func: uid(0x01)) {
  1809          name
  1810          friend @filter(regexp(name, /((en)|(xo))n/)) {
  1811            name
  1812          }
  1813        }
  1814      }
  1815  `
  1816  
  1817  	js := processQueryNoErr(t, query)
  1818  	require.JSONEq(t,
  1819  		`{"data": {"me":[{"name":"Michonne", "friend":[{"name":"Glenn Rhee"},{"name":"Daryl Dixon"} ]}]}}`, js)
  1820  }
  1821  
  1822  func TestFilterRegex5(t *testing.T) {
  1823  
  1824  	query := `
  1825      {
  1826        me(func: uid(0x01)) {
  1827          name
  1828          friend @filter(regexp(name, /^[a-zA-z]*[^Kk ]?[Nn]ight/)) {
  1829            name
  1830          }
  1831        }
  1832      }
  1833  `
  1834  
  1835  	js := processQueryNoErr(t, query)
  1836  	require.JSONEq(t,
  1837  		`{"data": {"me":[{"name":"Michonne"}]}}`, js)
  1838  }
  1839  
  1840  func TestFilterRegex6(t *testing.T) {
  1841  	query := `
  1842      {
  1843  	  me(func: uid(0x1234)) {
  1844  		pattern @filter(regexp(value, /miss((issippi)|(ouri))/)) {
  1845  			value
  1846  		}
  1847        }
  1848      }
  1849  `
  1850  
  1851  	js := processQueryNoErr(t, query)
  1852  	require.JSONEq(t,
  1853  		`{"data": {"me":[{"pattern":[{"value":"mississippi"}, {"value":"missouri"}]}]}}`, js)
  1854  }
  1855  
  1856  func TestFilterRegex7(t *testing.T) {
  1857  
  1858  	query := `
  1859      {
  1860  	  me(func: uid(0x1234)) {
  1861  		pattern @filter(regexp(value, /[aeiou]mission/)) {
  1862  			value
  1863  		}
  1864        }
  1865      }
  1866  `
  1867  
  1868  	js := processQueryNoErr(t, query)
  1869  	require.JSONEq(t,
  1870  		`{"data": {"me":[{"pattern":[{"value":"omission"}, {"value":"dimission"}]}]}}`, js)
  1871  }
  1872  
  1873  func TestFilterRegex8(t *testing.T) {
  1874  
  1875  	query := `
  1876      {
  1877  	  me(func: uid(0x1234)) {
  1878  		pattern @filter(regexp(value, /^(trans)?mission/)) {
  1879  			value
  1880  		}
  1881        }
  1882      }
  1883  `
  1884  
  1885  	js := processQueryNoErr(t, query)
  1886  	require.JSONEq(t,
  1887  		`{"data": {"me":[{"pattern":[{"value":"mission"}, {"value":"missionary"}, {"value":"transmission"}]}]}}`, js)
  1888  }
  1889  
  1890  func TestFilterRegex9(t *testing.T) {
  1891  
  1892  	query := `
  1893      {
  1894  	  me(func: uid(0x1234)) {
  1895  		pattern @filter(regexp(value, /s.{2,5}mission/)) {
  1896  			value
  1897  		}
  1898        }
  1899      }
  1900  `
  1901  
  1902  	js := processQueryNoErr(t, query)
  1903  	require.JSONEq(t,
  1904  		`{"data": {"me":[{"pattern":[{"value":"submission"}, {"value":"subcommission"}, {"value":"discommission"}]}]}}`, js)
  1905  }
  1906  
  1907  func TestFilterRegex10(t *testing.T) {
  1908  
  1909  	query := `
  1910      {
  1911  	  me(func: uid(0x1234)) {
  1912  		pattern @filter(regexp(value, /[^m]iss/)) {
  1913  			value
  1914  		}
  1915        }
  1916      }
  1917  `
  1918  
  1919  	js := processQueryNoErr(t, query)
  1920  	require.JSONEq(t,
  1921  		`{"data": {"me":[{"pattern":[{"value":"mississippi"}, {"value":"whissle"}]}]}}`, js)
  1922  }
  1923  
  1924  func TestFilterRegex11(t *testing.T) {
  1925  
  1926  	query := `
  1927      {
  1928  	  me(func: uid(0x1234)) {
  1929  		pattern @filter(regexp(value, /SUB[cm]/i)) {
  1930  			value
  1931  		}
  1932        }
  1933      }
  1934  `
  1935  
  1936  	js := processQueryNoErr(t, query)
  1937  	require.JSONEq(t,
  1938  		`{"data": {"me":[{"pattern":[{"value":"submission"}, {"value":"subcommission"}]}]}}`, js)
  1939  }
  1940  
  1941  // case insensitive mode may be turned on with modifier:
  1942  // http://www.regular-expressions.info/modifiers.html - this is completely legal
  1943  func TestFilterRegex12(t *testing.T) {
  1944  
  1945  	query := `
  1946      {
  1947  	  me(func: uid(0x1234)) {
  1948  		pattern @filter(regexp(value, /(?i)SUB[cm]/)) {
  1949  			value
  1950  		}
  1951        }
  1952      }
  1953  `
  1954  
  1955  	js := processQueryNoErr(t, query)
  1956  	require.JSONEq(t,
  1957  		`{"data": {"me":[{"pattern":[{"value":"submission"}, {"value":"subcommission"}]}]}}`, js)
  1958  }
  1959  
  1960  // case insensitive mode may be turned on and off with modifier:
  1961  // http://www.regular-expressions.info/modifiers.html - this is completely legal
  1962  func TestFilterRegex13(t *testing.T) {
  1963  
  1964  	query := `
  1965      {
  1966  	  me(func: uid(0x1234)) {
  1967  		pattern @filter(regexp(value, /(?i)SUB[cm](?-i)ISSION/)) {
  1968  			value
  1969  		}
  1970        }
  1971      }
  1972  `
  1973  
  1974  	// no results are returned, becaues case insensive mode is turned off before 'ISSION'
  1975  	js := processQueryNoErr(t, query)
  1976  	require.JSONEq(t, `{"data": {"me": []}}`, js)
  1977  }
  1978  
  1979  // invalid regexp modifier
  1980  func TestFilterRegex14(t *testing.T) {
  1981  
  1982  	query := `
  1983      {
  1984  	  me(func: uid(0x1234)) {
  1985  		pattern @filter(regexp(value, /pattern/x)) {
  1986  			value
  1987  		}
  1988        }
  1989      }
  1990  `
  1991  
  1992  	_, err := processQuery(context.Background(), t, query)
  1993  	require.Error(t, err)
  1994  }
  1995  
  1996  // multi-lang - simple
  1997  func TestFilterRegex15(t *testing.T) {
  1998  
  1999  	query := `
  2000  		{
  2001  			me(func:regexp(name@ru, /Барсук/)) {
  2002  				name@ru
  2003  			}
  2004  		}
  2005  	`
  2006  	js := processQueryNoErr(t, query)
  2007  	require.JSONEq(t,
  2008  		`{"data": {"me":[{"name@ru":"Барсук"}]}}`,
  2009  		js)
  2010  }
  2011  
  2012  // multi-lang - test for bug (#945) - multi-byte runes
  2013  func TestFilterRegex16(t *testing.T) {
  2014  
  2015  	query := `
  2016  		{
  2017  			me(func:regexp(name@ru, /^артём/i)) {
  2018  				name@ru
  2019  			}
  2020  		}
  2021  	`
  2022  	js := processQueryNoErr(t, query)
  2023  	require.JSONEq(t,
  2024  		`{"data": {"me":[{"name@ru":"Артём Ткаченко"}]}}`,
  2025  		js)
  2026  }
  2027  
  2028  func TestFilterRegex17(t *testing.T) {
  2029  	query := `
  2030  		{
  2031  			me(func:regexp(name, "")) {
  2032  				name
  2033  			}
  2034  		}
  2035  	`
  2036  	_, err := processQuery(context.Background(), t, query)
  2037  	require.Error(t, err)
  2038  	require.Contains(t, err.Error(), "Function 'regexp' requires 2 arguments,")
  2039  }
  2040  
  2041  func TestTypeFunction(t *testing.T) {
  2042  	query := `
  2043  		{
  2044  			me(func: type(Person)) {
  2045  				uid
  2046  			}
  2047  		}
  2048  	`
  2049  	js := processQueryNoErr(t, query)
  2050  	require.JSONEq(t,
  2051  		`{"data": {"me":[{"uid":"0x2"}, {"uid":"0x3"}, {"uid":"0x4"}]}}`,
  2052  		js)
  2053  }
  2054  
  2055  func TestTypeFunctionUnknownType(t *testing.T) {
  2056  	query := `
  2057  		{
  2058  			me(func: type(UnknownType)) {
  2059  				uid
  2060  			}
  2061  		}
  2062  	`
  2063  	js := processQueryNoErr(t, query)
  2064  	require.JSONEq(t, `{"data": {"me":[]}}`, js)
  2065  }
  2066  
  2067  func TestTypeFilter(t *testing.T) {
  2068  	query := `
  2069  		{
  2070  			me(func: uid(0x2)) @filter(type(Person)) {
  2071  				uid
  2072  			}
  2073  		}
  2074  	`
  2075  	js := processQueryNoErr(t, query)
  2076  	require.JSONEq(t,
  2077  		`{"data": {"me":[{"uid" :"0x2"}]}}`,
  2078  		js)
  2079  }
  2080  
  2081  func TestTypeFilterUnknownType(t *testing.T) {
  2082  	query := `
  2083  		{
  2084  			me(func: uid(0x2)) @filter(type(UnknownType)) {
  2085  				uid
  2086  			}
  2087  		}
  2088  	`
  2089  	js := processQueryNoErr(t, query)
  2090  	require.JSONEq(t, `{"data": {"me":[]}}`, js)
  2091  }
  2092  
  2093  func TestTypeDirectiveInPredicate(t *testing.T) {
  2094  	query := `
  2095  		{
  2096  			me(func: uid(0x2)) {
  2097  				enemy @type(Person) {
  2098  					name
  2099  				}
  2100  			}
  2101  		}
  2102  	`
  2103  	js := processQueryNoErr(t, query)
  2104  	require.JSONEq(t, `{"data": {"me":[{"enemy":[{"name":"Margaret"}, {"name":"Leonard"}]}]}}`, js)
  2105  }
  2106  
  2107  func TestMultipleTypeDirectivesInPredicate(t *testing.T) {
  2108  	query := `
  2109  		{
  2110  			me(func: uid(0x2)) {
  2111  				enemy @type(Person) {
  2112  					name
  2113  					pet @type(Animal) {
  2114  						name
  2115  					}
  2116  				}
  2117  			}
  2118  		}
  2119  	`
  2120  	js := processQueryNoErr(t, query)
  2121  	require.JSONEq(t, `{"data": {"me":[{"enemy":[{"name":"Margaret", "pet":[{"name":"Bear"}]}, {"name":"Leonard"}]}]}}`, js)
  2122  }
  2123  
  2124  func TestMaxPredicateSize(t *testing.T) {
  2125  	// Create a string that has more than than 2^16 chars.
  2126  	var b strings.Builder
  2127  	for i := 0; i < 10000; i++ {
  2128  		b.WriteString("abcdefg")
  2129  	}
  2130  	largePred := b.String()
  2131  
  2132  	query := fmt.Sprintf(`
  2133  		{
  2134  			me(func: uid(0x2)) {
  2135  				%s {
  2136  					name
  2137  				}
  2138  			}
  2139  		}
  2140  	`, largePred)
  2141  
  2142  	_, err := processQuery(context.Background(), t, query)
  2143  	require.Error(t, err)
  2144  	require.Contains(t, err.Error(), "Predicate name length cannot be bigger than 2^16")
  2145  }
  2146  
  2147  func TestQueryUnknownType(t *testing.T) {
  2148  	query := `schema(type: UnknownType) {}`
  2149  	js := processQueryNoErr(t, query)
  2150  	require.JSONEq(t, `{"data": {}}`, js)
  2151  }
  2152  
  2153  func TestQuerySingleType(t *testing.T) {
  2154  	query := `schema(type: Person) {}`
  2155  	js := processQueryNoErr(t, query)
  2156  	require.JSONEq(t, `{"data": {"types":[{"name":"Person",
  2157  		"fields":[{"name":"name", "type":"string"}, {"name":"pet", "type":"Animal"}]}]}}`,
  2158  		js)
  2159  }
  2160  
  2161  func TestQueryMultipleTypes(t *testing.T) {
  2162  	query := `schema(type: [Person, Animal]) {}`
  2163  	js := processQueryNoErr(t, query)
  2164  	require.JSONEq(t, `{"data": {"types":[{"name":"Animal",
  2165  		"fields":[{"name":"name", "type":"string"}]},
  2166  	{"name":"Person", "fields":[{"name":"name", "type": "string"},
  2167  		{"name":"pet", "type":"Animal"}]}]}}`, js)
  2168  }