github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/contrib/integration/testtxn/main_test.go (about) 1 /* 2 * Copyright 2017-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 main_test 18 19 import ( 20 "bytes" 21 "context" 22 "fmt" 23 "log" 24 "os" 25 "sort" 26 "strconv" 27 "strings" 28 "sync" 29 "testing" 30 "time" 31 32 "github.com/dgraph-io/dgo" 33 "github.com/dgraph-io/dgo/protos/api" 34 "github.com/dgraph-io/dgraph/testutil" 35 "github.com/dgraph-io/dgraph/x" 36 "github.com/stretchr/testify/assert" 37 "github.com/stretchr/testify/require" 38 "google.golang.org/grpc" 39 ) 40 41 type state struct { 42 dg *dgo.Dgraph 43 } 44 45 var s state 46 var addr string = testutil.SockAddr 47 48 func TestMain(m *testing.M) { 49 log.SetFlags(log.LstdFlags | log.Lshortfile) 50 testutil.AssignUids(200) 51 dg := testutil.DgraphClientWithGroot(testutil.SockAddr) 52 s.dg = dg 53 54 r := m.Run() 55 os.Exit(r) 56 } 57 58 // readTs == startTs 59 func TestTxnRead1(t *testing.T) { 60 op := &api.Operation{} 61 op.DropAll = true 62 require.NoError(t, s.dg.Alter(context.Background(), op)) 63 64 txn := s.dg.NewTxn() 65 mu := &api.Mutation{} 66 mu.SetJson = []byte(`{"name": "Manish"}`) 67 assigned, err := txn.Mutate(context.Background(), mu) 68 if err != nil { 69 log.Fatalf("Error while running mutation: %v\n", err) 70 } 71 if len(assigned.Uids) != 1 { 72 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 73 } 74 uid := retrieveUids(assigned.Uids)[0] 75 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 76 resp, err := txn.Query(context.Background(), q) 77 if err != nil { 78 log.Fatalf("Error while running query: %v\n", err) 79 } 80 x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) 81 require.NoError(t, txn.Commit(context.Background())) 82 } 83 84 // readTs < commitTs 85 func TestTxnRead2(t *testing.T) { 86 txn := s.dg.NewTxn() 87 88 mu := &api.Mutation{} 89 mu.SetJson = []byte(`{"name": "Manish"}`) 90 assigned, err := txn.Mutate(context.Background(), mu) 91 if err != nil { 92 log.Fatalf("Error while running mutation: %v\n", err) 93 } 94 if len(assigned.Uids) != 1 { 95 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 96 } 97 var uid string 98 for _, u := range assigned.Uids { 99 uid = u 100 } 101 102 txn2 := s.dg.NewTxn() 103 104 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 105 resp, err := txn2.Query(context.Background(), q) 106 if err != nil { 107 log.Fatalf("Error while running query: %v\n", err) 108 } 109 x.AssertTruef(bytes.Equal(resp.Json, []byte("{\"me\":[]}")), "%s", resp.Json) 110 require.NoError(t, txn.Commit(context.Background())) 111 } 112 113 // readTs > commitTs 114 func TestTxnRead3(t *testing.T) { 115 op := &api.Operation{} 116 op.DropAttr = "name" 117 attempts := 0 118 for attempts < 10 { 119 if err := s.dg.Alter(context.Background(), op); err == nil { 120 break 121 } 122 attempts++ 123 } 124 125 txn := s.dg.NewTxn() 126 127 mu := &api.Mutation{} 128 mu.SetJson = []byte(`{"name": "Manish"}`) 129 assigned, err := txn.Mutate(context.Background(), mu) 130 if err != nil { 131 log.Fatalf("Error while running mutation: %v\n", err) 132 } 133 if len(assigned.Uids) != 1 { 134 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 135 } 136 var uid string 137 for _, u := range assigned.Uids { 138 uid = u 139 } 140 141 require.NoError(t, txn.Commit(context.Background())) 142 txn = s.dg.NewTxn() 143 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 144 resp, err := txn.Query(context.Background(), q) 145 if err != nil { 146 log.Fatalf("Error while running query: %v\n", err) 147 } 148 x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) 149 } 150 151 // readTs > commitTs 152 func TestTxnRead4(t *testing.T) { 153 txn := s.dg.NewTxn() 154 155 mu := &api.Mutation{} 156 mu.SetJson = []byte(`{"name": "Manish"}`) 157 assigned, err := txn.Mutate(context.Background(), mu) 158 if err != nil { 159 log.Fatalf("Error while running mutation: %v\n", err) 160 } 161 if len(assigned.Uids) != 1 { 162 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 163 } 164 var uid string 165 for _, u := range assigned.Uids { 166 uid = u 167 } 168 169 require.NoError(t, txn.Commit(context.Background())) 170 txn2 := s.dg.NewTxn() 171 172 txn3 := s.dg.NewTxn() 173 mu = &api.Mutation{} 174 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Manish2"}`, uid)) 175 assigned, err = txn3.Mutate(context.Background(), mu) 176 if err != nil { 177 log.Fatalf("Error while running mutation: %v\n", err) 178 } 179 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 180 resp, err := txn2.Query(context.Background(), q) 181 if err != nil { 182 log.Fatalf("Error while running query: %v\n", err) 183 } 184 x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) 185 186 require.NoError(t, txn3.Commit(context.Background())) 187 188 txn4 := s.dg.NewTxn() 189 q = fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 190 resp, err = txn4.Query(context.Background(), q) 191 if err != nil { 192 log.Fatalf("Error while running query: %v\n", err) 193 } 194 x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish2\"}]}"))) 195 } 196 197 func TestTxnRead5(t *testing.T) { 198 txn := s.dg.NewTxn() 199 200 mu := &api.Mutation{} 201 mu.SetJson = []byte(`{"name": "Manish"}`) 202 assigned, err := txn.Mutate(context.Background(), mu) 203 if err != nil { 204 log.Fatalf("Error while running mutation: %v\n", err) 205 } 206 if len(assigned.Uids) != 1 { 207 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 208 } 209 var uid string 210 for _, u := range assigned.Uids { 211 uid = u 212 } 213 214 require.NoError(t, txn.Commit(context.Background())) 215 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 216 // We don't supply startTs, it should be fetched from zero by dgraph alpha. 217 req := api.Request{ 218 Query: q, 219 } 220 221 conn, err := grpc.Dial(addr, grpc.WithInsecure()) 222 if err != nil { 223 log.Fatal(err) 224 } 225 dc := api.NewDgraphClient(conn) 226 227 resp, err := dc.Query(context.Background(), &req) 228 if err != nil { 229 log.Fatalf("Error while running query: %v\n", err) 230 } 231 x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) 232 x.AssertTrue(resp.Txn.StartTs > 0) 233 234 mu = &api.Mutation{} 235 mu.SetJson = []byte(fmt.Sprintf("{\"uid\": \"%s\", \"name\": \"Manish2\"}", uid)) 236 237 muReq := api.Request{ 238 Mutations: []*api.Mutation{mu}, 239 CommitNow: true, 240 } 241 res, err := dc.Query(context.Background(), &muReq) 242 if err != nil { 243 log.Fatalf("Error while running mutation: %v\n", err) 244 } 245 x.AssertTrue(res.Txn.StartTs > 0) 246 resp, err = dc.Query(context.Background(), &req) 247 if err != nil { 248 log.Fatalf("Error while running query: %v\n", err) 249 } 250 x.AssertTrue(bytes.Equal(resp.Json, []byte(`{"me":[{"name":"Manish2"}]}`))) 251 } 252 253 func TestConflict(t *testing.T) { 254 op := &api.Operation{} 255 op.DropAll = true 256 require.NoError(t, s.dg.Alter(context.Background(), op)) 257 258 txn := s.dg.NewTxn() 259 260 mu := &api.Mutation{} 261 mu.SetJson = []byte(`{"name": "Manish"}`) 262 assigned, err := txn.Mutate(context.Background(), mu) 263 if err != nil { 264 log.Fatalf("Error while running mutation: %v\n", err) 265 } 266 if len(assigned.Uids) != 1 { 267 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 268 } 269 var uid string 270 for _, u := range assigned.Uids { 271 uid = u 272 } 273 274 txn2 := s.dg.NewTxn() 275 mu = &api.Mutation{} 276 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Manish"}`, uid)) 277 x.Check2(txn2.Mutate(context.Background(), mu)) 278 279 require.NoError(t, txn.Commit(context.Background())) 280 err = txn2.Commit(context.Background()) 281 x.AssertTrue(err != nil) 282 283 txn = s.dg.NewTxn() 284 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 285 resp, err := txn.Query(context.Background(), q) 286 if err != nil { 287 log.Fatalf("Error while running query: %v\n", err) 288 } 289 x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) 290 } 291 292 func TestConflictTimeout(t *testing.T) { 293 var uid string 294 txn := s.dg.NewTxn() 295 { 296 mu := &api.Mutation{} 297 mu.SetJson = []byte(`{"name": "Manish"}`) 298 assigned, err := txn.Mutate(context.Background(), mu) 299 if err != nil { 300 log.Fatalf("Error while running mutation: %v\n", err) 301 } 302 if len(assigned.Uids) != 1 { 303 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 304 } 305 for _, u := range assigned.Uids { 306 uid = u 307 } 308 } 309 310 txn2 := s.dg.NewTxn() 311 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 312 _, err := txn2.Query(context.Background(), q) 313 require.NoError(t, err) 314 315 mu := &api.Mutation{} 316 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Jan the man"}`, uid)) 317 _, err = txn2.Mutate(context.Background(), mu) 318 if err == nil { 319 require.NoError(t, txn2.Commit(context.Background())) 320 } 321 322 err = txn.Commit(context.Background()) 323 x.AssertTrue(err != nil) 324 325 txn3 := s.dg.NewTxn() 326 q = fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 327 _, err = txn3.Query(context.Background(), q) 328 require.NoError(t, err) 329 } 330 331 func TestConflictTimeout2(t *testing.T) { 332 var uid string 333 txn := s.dg.NewTxn() 334 { 335 336 mu := &api.Mutation{} 337 mu.SetJson = []byte(`{"name": "Manish"}`) 338 assigned, err := txn.Mutate(context.Background(), mu) 339 if err != nil { 340 log.Fatalf("Error while running mutation: %v\n", err) 341 } 342 if len(assigned.Uids) != 1 { 343 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 344 } 345 for _, u := range assigned.Uids { 346 uid = u 347 } 348 } 349 350 txn2 := s.dg.NewTxn() 351 mu := &api.Mutation{} 352 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Jan the man"}`, uid)) 353 x.Check2(txn2.Mutate(context.Background(), mu)) 354 355 require.NoError(t, txn.Commit(context.Background())) 356 err := txn2.Commit(context.Background()) 357 x.AssertTrue(err != nil) 358 359 txn3 := s.dg.NewTxn() 360 mu = &api.Mutation{} 361 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Jan the man"}`, uid)) 362 assigned, err := txn3.Mutate(context.Background(), mu) 363 if err == nil { 364 require.NoError(t, txn3.Commit(context.Background())) 365 } 366 for _, u := range assigned.Uids { 367 uid = u 368 } 369 370 txn4 := s.dg.NewTxn() 371 q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) 372 _, err = txn4.Query(context.Background(), q) 373 require.NoError(t, err) 374 } 375 376 func TestIgnoreIndexConflict(t *testing.T) { 377 op := &api.Operation{} 378 op.DropAll = true 379 require.NoError(t, s.dg.Alter(context.Background(), op)) 380 381 op = &api.Operation{} 382 op.Schema = `name: string @index(exact) .` 383 if err := s.dg.Alter(context.Background(), op); err != nil { 384 log.Fatal(err) 385 } 386 387 txn := s.dg.NewTxn() 388 mu := &api.Mutation{} 389 mu.SetJson = []byte(`{"name": "Manish"}`) 390 assigned, err := txn.Mutate(context.Background(), mu) 391 if err != nil { 392 log.Fatalf("Error while running mutation: %v\n", err) 393 } 394 if len(assigned.Uids) != 1 { 395 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 396 } 397 var uid1, uid2 string 398 for _, u := range assigned.Uids { 399 uid1 = u 400 } 401 402 txn2 := s.dg.NewTxn() 403 mu = &api.Mutation{} 404 mu.SetJson = []byte(`{"name": "Manish"}`) 405 assigned, err = txn2.Mutate(context.Background(), mu) 406 if err != nil { 407 log.Fatalf("Error while running mutation: %v\n", err) 408 } 409 if len(assigned.Uids) != 1 { 410 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 411 } 412 for _, u := range assigned.Uids { 413 uid2 = u 414 } 415 416 require.NoError(t, txn.Commit(context.Background())) 417 require.NoError(t, txn2.Commit(context.Background())) 418 419 txn = s.dg.NewTxn() 420 q := `{ me(func: eq(name, "Manish")) { uid }}` 421 resp, err := txn.Query(context.Background(), q) 422 if err != nil { 423 log.Fatalf("Error while running query: %v\n", err) 424 } 425 expectedResp := []byte(fmt.Sprintf(`{"me":[{"uid":"%s"},{"uid":"%s"}]}`, uid1, uid2)) 426 require.Equal(t, expectedResp, resp.Json) 427 } 428 429 func TestReadIndexKeySameTxn(t *testing.T) { 430 op := &api.Operation{} 431 op.DropAll = true 432 require.NoError(t, s.dg.Alter(context.Background(), op)) 433 434 op = &api.Operation{} 435 op.Schema = `name: string @index(exact) .` 436 if err := s.dg.Alter(context.Background(), op); err != nil { 437 log.Fatal(err) 438 } 439 440 txn := s.dg.NewTxn() 441 442 mu := &api.Mutation{ 443 CommitNow: true, 444 SetJson: []byte(`{"name": "Manish"}`), 445 } 446 assigned, err := txn.Mutate(context.Background(), mu) 447 if err != nil { 448 log.Fatalf("Error while running mutation: %v\n", err) 449 } 450 if len(assigned.Uids) != 1 { 451 log.Fatalf("Error. Nothing assigned. %+v\n", assigned) 452 } 453 var uid string 454 for _, u := range assigned.Uids { 455 uid = u 456 } 457 458 txn = s.dg.NewTxn() 459 defer txn.Discard(context.Background()) 460 q := `{ me(func: le(name, "Manish")) { uid }}` 461 resp, err := txn.Query(context.Background(), q) 462 if err != nil { 463 log.Fatalf("Error while running query: %v\n", err) 464 } 465 expectedResp := []byte(fmt.Sprintf(`{"me":[{"uid":"%s"}]}`, uid)) 466 x.AssertTrue(bytes.Equal(resp.Json, expectedResp)) 467 } 468 469 func TestEmailUpsert(t *testing.T) { 470 op := &api.Operation{} 471 op.DropAll = true 472 require.NoError(t, s.dg.Alter(context.Background(), op)) 473 474 op = &api.Operation{} 475 op.Schema = `email: string @index(exact) @upsert .` 476 if err := s.dg.Alter(context.Background(), op); err != nil { 477 log.Fatal(err) 478 } 479 480 txn1 := s.dg.NewTxn() 481 mu := &api.Mutation{} 482 mu.SetJson = []byte(`{"uid": "_:user1", "email": "email@email.org"}`) 483 _, err := txn1.Mutate(context.Background(), mu) 484 assert.Nil(t, err) 485 486 txn2 := s.dg.NewTxn() 487 mu = &api.Mutation{} 488 mu.SetJson = []byte(`{"uid": "_:user2", "email": "email@email.org"}`) 489 _, err = txn2.Mutate(context.Background(), mu) 490 assert.Nil(t, err) 491 492 txn3 := s.dg.NewTxn() 493 mu = &api.Mutation{} 494 mu.SetJson = []byte(`{"uid": "_:user3", "email": "email3@email.org"}`) 495 _, err = txn3.Mutate(context.Background(), mu) 496 assert.Nil(t, err) 497 498 require.NoError(t, txn1.Commit(context.Background())) 499 require.NotNil(t, txn2.Commit(context.Background())) 500 require.NoError(t, txn3.Commit(context.Background())) 501 } 502 503 // TestFriendList tests that we are not able to set a node to node edge between 504 // the same nodes concurrently. 505 func TestFriendList(t *testing.T) { 506 op := &api.Operation{} 507 op.DropAll = true 508 require.NoError(t, s.dg.Alter(context.Background(), op)) 509 510 op = &api.Operation{} 511 op.Schema = ` 512 friend: [uid] @reverse .` 513 if err := s.dg.Alter(context.Background(), op); err != nil { 514 log.Fatal(err) 515 } 516 517 txn1 := s.dg.NewTxn() 518 mu := &api.Mutation{} 519 mu.SetJson = []byte(`{"uid": "0x01", "friend": [{"uid": "0x02"}]}`) 520 _, err := txn1.Mutate(context.Background(), mu) 521 assert.Nil(t, err) 522 523 txn2 := s.dg.NewTxn() 524 mu = &api.Mutation{} 525 mu.SetJson = []byte(`{"uid": "0x01", "friend": [{"uid": "0x02"}]}`) 526 _, err = txn2.Mutate(context.Background(), mu) 527 assert.Nil(t, err) 528 529 txn3 := s.dg.NewTxn() 530 mu = &api.Mutation{} 531 mu.SetJson = []byte(`{"uid": "0x01", "friend": [{"uid": "0x03"}]}`) 532 _, err = txn3.Mutate(context.Background(), mu) 533 assert.Nil(t, err) 534 535 require.NoError(t, txn1.Commit(context.Background())) 536 require.NotNil(t, txn2.Commit(context.Background())) 537 require.NoError(t, txn3.Commit(context.Background())) 538 } 539 540 // TestNameSet tests that we are not able to set a property edge for the same 541 // subject id concurrently. 542 func TestNameSet(t *testing.T) { 543 op := &api.Operation{} 544 op.DropAll = true 545 require.NoError(t, s.dg.Alter(context.Background(), op)) 546 547 op = &api.Operation{} 548 op.Schema = `name: string .` 549 if err := s.dg.Alter(context.Background(), op); err != nil { 550 log.Fatal(err) 551 } 552 553 txn1 := s.dg.NewTxn() 554 mu := &api.Mutation{} 555 mu.SetJson = []byte(`{"uid": "0x01", "name": "manish"}`) 556 _, err := txn1.Mutate(context.Background(), mu) 557 assert.Nil(t, err) 558 559 txn2 := s.dg.NewTxn() 560 mu = &api.Mutation{} 561 mu.SetJson = []byte(`{"uid": "0x01", "name": "contributor"}`) 562 _, err = txn2.Mutate(context.Background(), mu) 563 assert.Nil(t, err) 564 565 require.NoError(t, txn1.Commit(context.Background())) 566 require.NotNil(t, txn2.Commit(context.Background())) 567 } 568 569 // retrieve the uids in the uidMap in the order of ascending keys 570 func retrieveUids(uidMap map[string]string) []string { 571 keys := make([]string, 0, len(uidMap)) 572 for key := range uidMap { 573 keys = append(keys, key) 574 } 575 576 sort.Slice(keys, func(i, j int) bool { 577 num1 := strings.Split(keys[i], ".")[2] 578 579 num2 := strings.Split(keys[j], ".")[2] 580 n1, err := strconv.Atoi(num1) 581 x.Check(err) 582 n2, err := strconv.Atoi(num2) 583 x.Check(err) 584 return n1 < n2 585 }) 586 587 uids := make([]string, 0, len(uidMap)) 588 for _, k := range keys { 589 uids = append(uids, uidMap[k]) 590 } 591 return uids 592 } 593 594 func TestSPStar(t *testing.T) { 595 op := &api.Operation{} 596 op.DropAll = true 597 require.NoError(t, s.dg.Alter(context.Background(), op)) 598 599 op = &api.Operation{} 600 op.Schema = `friend: [uid] .` 601 require.NoError(t, s.dg.Alter(context.Background(), op)) 602 603 txn := s.dg.NewTxn() 604 mu := &api.Mutation{} 605 mu.SetJson = []byte(`{"name": "Manish", "friend": [{"name": "Jan"}]}`) 606 assigned, err := txn.Mutate(context.Background(), mu) 607 require.Equal(t, 2, len(assigned.Uids)) 608 uid1 := retrieveUids(assigned.Uids)[0] 609 require.NoError(t, err) 610 require.Equal(t, 2, len(assigned.Uids)) 611 require.NoError(t, txn.Commit(context.Background())) 612 613 txn = s.dg.NewTxn() 614 mu = &api.Mutation{} 615 dgo.DeleteEdges(mu, uid1, "friend") 616 assigned, err = txn.Mutate(context.Background(), mu) 617 require.NoError(t, err) 618 require.Equal(t, 0, len(assigned.Uids)) 619 620 mu = &api.Mutation{} 621 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s" ,"name": "Manish", "friend": [{"name": "Jan2"}]}`, uid1)) 622 assigned, err = txn.Mutate(context.Background(), mu) 623 require.NoError(t, err) 624 require.Equal(t, 1, len(assigned.Uids)) 625 uid2 := retrieveUids(assigned.Uids)[0] 626 627 q := fmt.Sprintf(`{ 628 me(func: uid(%s)) { 629 uid 630 friend { 631 uid 632 name 633 } 634 } 635 }`, uid1) 636 637 resp, err := txn.Query(context.Background(), q) 638 require.NoError(t, err) 639 expectedResp := fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan2", "uid":"%s"}]}]}`, uid1, uid2) 640 require.JSONEq(t, expectedResp, string(resp.Json)) 641 } 642 643 func TestSPStar2(t *testing.T) { 644 op := &api.Operation{} 645 op.DropAll = true 646 require.NoError(t, s.dg.Alter(context.Background(), op)) 647 648 op = &api.Operation{} 649 op.Schema = `friend: [uid] .` 650 require.NoError(t, s.dg.Alter(context.Background(), op)) 651 652 // Add edge 653 txn := s.dg.NewTxn() 654 mu := &api.Mutation{} 655 mu.SetJson = []byte(`{"name": "Manish", "friend": [{"name": "Jan"}]}`) 656 assigned, err := txn.Mutate(context.Background(), mu) 657 658 require.NoError(t, err) 659 require.Equal(t, 2, len(assigned.Uids)) 660 661 uids := retrieveUids(assigned.Uids) 662 uid1 := uids[0] 663 uid2 := uids[1] 664 q := fmt.Sprintf(`{ 665 me(func: uid(%s)) { 666 uid 667 friend { 668 uid 669 name 670 } 671 } 672 }`, uid1) 673 674 resp, err := txn.Query(context.Background(), q) 675 require.NoError(t, err) 676 expectedResp := fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan", "uid":"%s"}]}]}`, uid1, uid2) 677 require.JSONEq(t, expectedResp, string(resp.Json)) 678 679 // Delete S P * 680 mu = &api.Mutation{} 681 dgo.DeleteEdges(mu, uid1, "friend") 682 assigned, err = txn.Mutate(context.Background(), mu) 683 require.NoError(t, err) 684 require.Equal(t, 0, len(assigned.Uids)) 685 686 resp, err = txn.Query(context.Background(), q) 687 require.NoError(t, err) 688 expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s"}]}`, uid1) 689 require.JSONEq(t, expectedResp, string(resp.Json)) 690 691 // Add edge 692 mu = &api.Mutation{} 693 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s" ,"name": "Manish", "friend": [{"name": "Jan2"}]}`, uid1)) 694 assigned, err = txn.Mutate(context.Background(), mu) 695 require.NoError(t, err) 696 require.Equal(t, 1, len(assigned.Uids)) 697 uid3 := retrieveUids(assigned.Uids)[0] 698 resp, err = txn.Query(context.Background(), q) 699 require.NoError(t, err) 700 expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan2", "uid":"%s"}]}]}`, 701 uid1, uid3) 702 require.JSONEq(t, expectedResp, string(resp.Json)) 703 704 // Delete S P * 705 mu = &api.Mutation{} 706 dgo.DeleteEdges(mu, uid1, "friend") 707 assigned, err = txn.Mutate(context.Background(), mu) 708 require.NoError(t, err) 709 require.Equal(t, 0, len(assigned.Uids)) 710 711 resp, err = txn.Query(context.Background(), q) 712 require.NoError(t, err) 713 expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s"}]}`, uid1) 714 require.JSONEq(t, expectedResp, string(resp.Json)) 715 716 // Add edge 717 mu = &api.Mutation{} 718 mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s" ,"name": "Manish", "friend": [{"name": "Jan3"}]}`, uid1)) 719 assigned, err = txn.Mutate(context.Background(), mu) 720 require.NoError(t, err) 721 require.Equal(t, 1, len(assigned.Uids)) 722 723 uid4 := retrieveUids(assigned.Uids)[0] 724 resp, err = txn.Query(context.Background(), q) 725 require.NoError(t, err) 726 expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan3", "uid":"%s"}]}]}`, uid1, uid4) 727 require.JSONEq(t, expectedResp, string(resp.Json)) 728 } 729 730 var ( 731 ctxb = context.Background() 732 countQuery = ` 733 query countAnswers($num: int) { 734 me(func: eq(count(answer), $num)) { 735 uid 736 count(answer) 737 } 738 } 739 ` 740 ) 741 742 func TestCountIndexConcurrentTxns(t *testing.T) { 743 dg := testutil.DgraphClientWithGroot(testutil.SockAddr) 744 testutil.DropAll(t, dg) 745 alterSchema(dg, "answer: [uid] @count .") 746 747 // Expected edge count of 0x100: 1 748 txn0 := dg.NewTxn() 749 mu := api.Mutation{SetNquads: []byte("<0x100> <answer> <0x200> .")} 750 _, err := txn0.Mutate(ctxb, &mu) 751 x.Check(err) 752 err = txn0.Commit(ctxb) 753 x.Check(err) 754 755 // The following two mutations are in separate interleaved txns. 756 txn1 := dg.NewTxn() 757 mu = api.Mutation{SetNquads: []byte("<0x1> <answer> <0x2> .")} 758 _, err = txn1.Mutate(ctxb, &mu) 759 x.Check(err) 760 761 txn2 := dg.NewTxn() 762 mu = api.Mutation{SetNquads: []byte("<0x1> <answer> <0x3> .")} 763 _, err = txn2.Mutate(ctxb, &mu) 764 x.Check(err) 765 766 err = txn1.Commit(ctxb) 767 x.Check(err) 768 err = txn2.Commit(ctxb) 769 require.Error(t, err, 770 "the txn2 should be aborted due to concurrent update on the count index of <0x01>") 771 772 // retry the mutatiton 773 txn3 := dg.NewTxn() 774 _, err = txn3.Mutate(ctxb, &mu) 775 x.Check(err) 776 err = txn3.Commit(ctxb) 777 x.Check(err) 778 779 // Verify count queries 780 txn := dg.NewReadOnlyTxn() 781 vars := map[string]string{"$num": "1"} 782 resp, err := txn.QueryWithVars(ctxb, countQuery, vars) 783 x.Check(err) 784 js := string(resp.GetJson()) 785 require.JSONEq(t, 786 `{"me": [{"count(answer)": 1, "uid": "0x100"}]}`, 787 js) 788 txn = dg.NewReadOnlyTxn() 789 vars = map[string]string{"$num": "2"} 790 resp, err = txn.QueryWithVars(ctxb, countQuery, vars) 791 x.Check(err) 792 js = string(resp.GetJson()) 793 require.JSONEq(t, 794 `{"me": [{"count(answer)": 2, "uid": "0x1"}]}`, 795 js) 796 } 797 798 func TestCountIndexSerialTxns(t *testing.T) { 799 dg := testutil.DgraphClientWithGroot(testutil.SockAddr) 800 testutil.DropAll(t, dg) 801 alterSchema(dg, "answer: [uid] @count .") 802 803 // Expected Edge count of 0x100: 1 804 txn0 := dg.NewTxn() 805 mu := api.Mutation{SetNquads: []byte("<0x100> <answer> <0x200> .")} 806 _, err := txn0.Mutate(ctxb, &mu) 807 require.NoError(t, err) 808 err = txn0.Commit(ctxb) 809 require.NoError(t, err) 810 811 // Expected edge count of 0x1: 2 812 // This should NOT appear in the query result 813 // The following two mutations are in serial txns. 814 txn1 := dg.NewTxn() 815 mu = api.Mutation{SetNquads: []byte("<0x1> <answer> <0x2> .")} 816 _, err = txn1.Mutate(ctxb, &mu) 817 require.NoError(t, err) 818 err = txn1.Commit(ctxb) 819 require.NoError(t, err) 820 821 txn2 := dg.NewTxn() 822 mu = api.Mutation{SetNquads: []byte("<0x1> <answer> <0x3> .")} 823 _, err = txn2.Mutate(ctxb, &mu) 824 require.NoError(t, err) 825 err = txn2.Commit(ctxb) 826 require.NoError(t, err) 827 828 // Verify query 829 txn := dg.NewReadOnlyTxn() 830 vars := map[string]string{"$num": "1"} 831 resp, err := txn.QueryWithVars(ctxb, countQuery, vars) 832 require.NoError(t, err) 833 js := string(resp.GetJson()) 834 require.JSONEq(t, 835 `{"me": [{"count(answer)": 1, "uid": "0x100"}]}`, 836 js) 837 txn = dg.NewReadOnlyTxn() 838 vars = map[string]string{"$num": "2"} 839 resp, err = txn.QueryWithVars(ctxb, countQuery, vars) 840 require.NoError(t, err) 841 js = string(resp.GetJson()) 842 require.JSONEq(t, 843 `{"me": [{"count(answer)": 2, "uid": "0x1"}]}`, 844 js) 845 } 846 847 func TestCountIndexSameTxn(t *testing.T) { 848 dg := testutil.DgraphClientWithGroot(testutil.SockAddr) 849 testutil.DropAll(t, dg) 850 alterSchema(dg, "answer: [uid] @count .") 851 852 // Expected Edge count of 0x100: 1 853 txn0 := dg.NewTxn() 854 mu := api.Mutation{SetNquads: []byte("<0x100> <answer> <0x200> .")} 855 _, err := txn0.Mutate(ctxb, &mu) 856 x.Check(err) 857 err = txn0.Commit(ctxb) 858 x.Check(err) 859 860 // Expected edge count of 0x1: 2 861 // This should NOT appear in the query result 862 // The following two mutations are in the same txn. 863 txn1 := dg.NewTxn() 864 mu = api.Mutation{SetNquads: []byte("<0x1> <answer> <0x2> .")} 865 _, err = txn1.Mutate(ctxb, &mu) 866 x.Check(err) 867 mu = api.Mutation{SetNquads: []byte("<0x1> <answer> <0x3> .")} 868 _, err = txn1.Mutate(ctxb, &mu) 869 x.Check(err) 870 err = txn1.Commit(ctxb) 871 x.Check(err) 872 873 // Verify query 874 txn := dg.NewReadOnlyTxn() 875 vars := map[string]string{"$num": "1"} 876 resp, err := txn.QueryWithVars(ctxb, countQuery, vars) 877 x.Check(err) 878 js := string(resp.GetJson()) 879 require.JSONEq(t, 880 `{"me": [{"count(answer)": 1, "uid": "0x100"}]}`, 881 js) 882 txn = dg.NewReadOnlyTxn() 883 vars = map[string]string{"$num": "2"} 884 resp, err = txn.QueryWithVars(ctxb, countQuery, vars) 885 x.Check(err) 886 js = string(resp.GetJson()) 887 require.JSONEq(t, 888 `{"me": [{"count(answer)": 2, "uid": "0x1"}]}`, 889 js) 890 } 891 892 func TestConcurrentQueryMutate(t *testing.T) { 893 testutil.DropAll(t, s.dg) 894 alterSchema(s.dg, "name: string .") 895 896 txn := s.dg.NewTxn() 897 defer txn.Discard(context.Background()) 898 899 // Do one query, so a new timestamp is assigned to the txn. 900 q := `{me(func: uid(0x01)) { name }}` 901 _, err := txn.Query(context.Background(), q) 902 require.NoError(t, err) 903 904 var wg sync.WaitGroup 905 wg.Add(2) 906 start := time.Now() 907 go func() { 908 defer wg.Done() 909 for time.Since(start) < 5*time.Second { 910 mu := &api.Mutation{} 911 mu.SetJson = []byte(`{"uid": "0x01", "name": "manish"}`) 912 _, err := txn.Mutate(context.Background(), mu) 913 assert.Nil(t, err) 914 } 915 }() 916 917 go func() { 918 defer wg.Done() 919 for time.Since(start) < 5*time.Second { 920 _, err := txn.Query(context.Background(), q) 921 require.NoError(t, err) 922 } 923 }() 924 wg.Wait() 925 t.Logf("Done\n") 926 } 927 928 func alterSchema(dg *dgo.Dgraph, schema string) { 929 op := api.Operation{} 930 op.Schema = schema 931 err := dg.Alter(ctxb, &op) 932 x.Check(err) 933 }