github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/posting/list_test.go (about) 1 /* 2 * Copyright 2015-2018 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package posting 18 19 import ( 20 "context" 21 "io/ioutil" 22 "math" 23 "math/rand" 24 "os" 25 "sort" 26 "strconv" 27 "testing" 28 29 "github.com/dgraph-io/badger" 30 bpb "github.com/dgraph-io/badger/pb" 31 "github.com/stretchr/testify/require" 32 33 "github.com/dgraph-io/dgraph/protos/pb" 34 "github.com/dgraph-io/dgraph/schema" 35 "github.com/dgraph-io/dgraph/x" 36 ) 37 38 func (l *List) PostingList() *pb.PostingList { 39 l.RLock() 40 defer l.RUnlock() 41 return l.plist 42 } 43 44 func listToArray(t *testing.T, afterUid uint64, l *List, readTs uint64) []uint64 { 45 out := make([]uint64, 0, 10) 46 l.Iterate(readTs, afterUid, func(p *pb.Posting) error { 47 out = append(out, p.Uid) 48 return nil 49 }) 50 return out 51 } 52 53 func checkUids(t *testing.T, l *List, uids []uint64, readTs uint64) { 54 require.Equal(t, uids, listToArray(t, 0, l, readTs)) 55 if len(uids) >= 3 { 56 require.Equal(t, uids[1:], listToArray(t, 10, l, readTs), uids[1:]) 57 require.Equal(t, []uint64{81}, listToArray(t, 80, l, readTs)) 58 require.Empty(t, listToArray(t, 82, l, readTs)) 59 } 60 } 61 62 func addMutationHelper(t *testing.T, l *List, edge *pb.DirectedEdge, op uint32, txn *Txn) { 63 if op == Del { 64 edge.Op = pb.DirectedEdge_DEL 65 } else if op == Set { 66 edge.Op = pb.DirectedEdge_SET 67 } else { 68 x.Fatalf("Unhandled op: %v", op) 69 } 70 err := l.addMutation(context.Background(), txn, edge) 71 require.NoError(t, err) 72 } 73 74 func (l *List) commitMutation(startTs, commitTs uint64) error { 75 l.Lock() 76 defer l.Unlock() 77 78 plist, ok := l.mutationMap[startTs] 79 if !ok { 80 // It was already committed, might be happening due to replay. 81 return nil 82 } 83 if commitTs == 0 { 84 // Abort mutation. 85 delete(l.mutationMap, startTs) 86 return nil 87 } 88 89 // We have a valid commit. 90 plist.CommitTs = commitTs 91 for _, mpost := range plist.Postings { 92 mpost.CommitTs = commitTs 93 } 94 95 // In general, a posting list shouldn't try to mix up it's job of keeping 96 // things in memory, with writing things to disk. A separate process can 97 // roll up and write them to disk. posting list should only keep things in 98 // memory, to make it available for transactions. So, all we need to do here 99 // is to roll them up periodically, now being done by draft.go. 100 // For the PLs in memory, we roll them up after we do the disk rollup. 101 return nil 102 } 103 104 func TestAddMutation(t *testing.T) { 105 key := x.DataKey("name", 2) 106 107 txn := NewTxn(1) 108 l, err := txn.Get(key) 109 require.NoError(t, err) 110 111 edge := &pb.DirectedEdge{ 112 ValueId: 9, 113 Label: "testing", 114 } 115 addMutationHelper(t, l, edge, Set, txn) 116 117 require.Equal(t, listToArray(t, 0, l, 1), []uint64{9}) 118 119 p := getFirst(l, 1) 120 require.NotNil(t, p, "Unable to retrieve posting") 121 require.EqualValues(t, p.Label, "testing") 122 123 // Add another edge now. 124 edge.ValueId = 81 125 addMutationHelper(t, l, edge, Set, txn) 126 require.Equal(t, listToArray(t, 0, l, 1), []uint64{9, 81}) 127 128 // Add another edge, in between the two above. 129 edge.ValueId = 49 130 addMutationHelper(t, l, edge, Set, txn) 131 require.Equal(t, listToArray(t, 0, l, 1), []uint64{9, 49, 81}) 132 133 checkUids(t, l, []uint64{9, 49, 81}, 1) 134 135 // Delete an edge, add an edge, replace an edge 136 edge.ValueId = 49 137 addMutationHelper(t, l, edge, Del, txn) 138 139 edge.ValueId = 69 140 addMutationHelper(t, l, edge, Set, txn) 141 142 edge.ValueId = 9 143 edge.Label = "anti-testing" 144 addMutationHelper(t, l, edge, Set, txn) 145 l.commitMutation(1, 2) 146 147 uids := []uint64{9, 69, 81} 148 checkUids(t, l, uids, 3) 149 150 p = getFirst(l, 3) 151 require.NotNil(t, p, "Unable to retrieve posting") 152 require.EqualValues(t, "anti-testing", p.Label) 153 } 154 155 func getFirst(l *List, readTs uint64) (res pb.Posting) { 156 l.Iterate(readTs, 0, func(p *pb.Posting) error { 157 res = *p 158 return ErrStopIteration 159 }) 160 return res 161 } 162 163 func checkValue(t *testing.T, ol *List, val string, readTs uint64) { 164 p := getFirst(ol, readTs) 165 require.Equal(t, uint64(math.MaxUint64), p.Uid) // Cast to prevent overflow. 166 require.EqualValues(t, val, p.Value) 167 } 168 169 // TODO(txn): Add tests after lru eviction 170 func TestAddMutation_Value(t *testing.T) { 171 key := x.DataKey("value", 10) 172 ol, err := getNew(key, ps) 173 require.NoError(t, err) 174 edge := &pb.DirectedEdge{ 175 Value: []byte("oh hey there"), 176 Label: "new-testing", 177 } 178 txn := &Txn{StartTs: 1} 179 addMutationHelper(t, ol, edge, Set, txn) 180 checkValue(t, ol, "oh hey there", txn.StartTs) 181 182 // Run the same check after committing. 183 ol.commitMutation(txn.StartTs, txn.StartTs+1) 184 checkValue(t, ol, "oh hey there", uint64(3)) 185 186 // The value made it to the posting list. Changing it now. 187 edge.Value = []byte(strconv.Itoa(119)) 188 txn = &Txn{StartTs: 3} 189 addMutationHelper(t, ol, edge, Set, txn) 190 checkValue(t, ol, "119", txn.StartTs) 191 } 192 193 func TestAddMutation_jchiu1(t *testing.T) { 194 key := x.DataKey("value", 12) 195 ol, err := GetNoStore(key) 196 require.NoError(t, err) 197 198 // Set value to cars and merge to BadgerDB. 199 edge := &pb.DirectedEdge{ 200 Value: []byte("cars"), 201 Label: "jchiu", 202 } 203 txn := &Txn{StartTs: 1} 204 addMutationHelper(t, ol, edge, Set, txn) 205 ol.commitMutation(1, uint64(2)) 206 207 // TODO: Read at commitTimestamp with all committed 208 require.EqualValues(t, 1, ol.Length(uint64(3), 0)) 209 checkValue(t, ol, "cars", uint64(3)) 210 211 txn = &Txn{StartTs: 3} 212 // Set value to newcars, but don't merge yet. 213 edge = &pb.DirectedEdge{ 214 Value: []byte("newcars"), 215 Label: "jchiu", 216 } 217 addMutationHelper(t, ol, edge, Set, txn) 218 require.EqualValues(t, 1, ol.Length(txn.StartTs, 0)) 219 checkValue(t, ol, "newcars", txn.StartTs) 220 221 // Set value to someothercars, but don't merge yet. 222 edge = &pb.DirectedEdge{ 223 Value: []byte("someothercars"), 224 Label: "jchiu", 225 } 226 addMutationHelper(t, ol, edge, Set, txn) 227 require.EqualValues(t, 1, ol.Length(txn.StartTs, 0)) 228 checkValue(t, ol, "someothercars", txn.StartTs) 229 230 // Set value back to the committed value cars, but don't merge yet. 231 edge = &pb.DirectedEdge{ 232 Value: []byte("cars"), 233 Label: "jchiu", 234 } 235 addMutationHelper(t, ol, edge, Set, txn) 236 require.EqualValues(t, 1, ol.Length(txn.StartTs, 0)) 237 checkValue(t, ol, "cars", txn.StartTs) 238 } 239 240 func TestAddMutation_DelSet(t *testing.T) { 241 key := x.DataKey("value", 1534) 242 ol, err := GetNoStore(key) 243 require.NoError(t, err) 244 245 // DO sp*, don't commit 246 // Del a value cars and but don't merge. 247 edge := &pb.DirectedEdge{ 248 Value: []byte(x.Star), 249 Op: pb.DirectedEdge_DEL, 250 } 251 txn := &Txn{StartTs: 1} 252 err = ol.addMutation(context.Background(), txn, edge) 253 require.NoError(t, err) 254 255 // Set value to newcars, commit it 256 edge = &pb.DirectedEdge{ 257 Value: []byte("newcars"), 258 } 259 txn = &Txn{StartTs: 2} 260 addMutationHelper(t, ol, edge, Set, txn) 261 ol.commitMutation(2, uint64(3)) 262 require.EqualValues(t, 1, ol.Length(3, 0)) 263 checkValue(t, ol, "newcars", 3) 264 } 265 266 func TestAddMutation_DelRead(t *testing.T) { 267 key := x.DataKey("value", 1543) 268 ol, err := GetNoStore(key) 269 require.NoError(t, err) 270 271 // Set value to newcars, and commit it 272 edge := &pb.DirectedEdge{ 273 Value: []byte("newcars"), 274 } 275 txn := &Txn{StartTs: 1} 276 addMutationHelper(t, ol, edge, Set, txn) 277 ol.commitMutation(1, uint64(2)) 278 require.EqualValues(t, 1, ol.Length(2, 0)) 279 checkValue(t, ol, "newcars", 2) 280 281 // DO sp*, don't commit 282 // Del a value cars and but don't merge. 283 edge = &pb.DirectedEdge{ 284 Value: []byte(x.Star), 285 Op: pb.DirectedEdge_DEL, 286 } 287 txn = &Txn{StartTs: 3} 288 err = ol.addMutation(context.Background(), txn, edge) 289 require.NoError(t, err) 290 291 // Part of same transaction as sp*, so should see zero length even 292 // if not committed yet. 293 require.EqualValues(t, 0, ol.Length(3, 0)) 294 295 // Commit sp* only in oracle, don't apply to pl yet 296 ol.commitMutation(3, 5) 297 298 // This read should ignore sp*, since readts is 4 and it was committed at 5 299 require.EqualValues(t, 1, ol.Length(4, 0)) 300 checkValue(t, ol, "newcars", 4) 301 302 require.EqualValues(t, 0, ol.Length(6, 0)) 303 } 304 305 func TestAddMutation_jchiu2(t *testing.T) { 306 key := x.DataKey("value", 15) 307 ol, err := GetNoStore(key) 308 require.NoError(t, err) 309 310 // Del a value cars and but don't merge. 311 edge := &pb.DirectedEdge{ 312 Value: []byte("cars"), 313 Label: "jchiu", 314 } 315 txn := &Txn{StartTs: 1} 316 addMutationHelper(t, ol, edge, Del, txn) 317 require.EqualValues(t, 0, ol.Length(txn.StartTs, 0)) 318 319 // Set value to newcars, but don't merge yet. 320 edge = &pb.DirectedEdge{ 321 Value: []byte("newcars"), 322 Label: "jchiu", 323 } 324 addMutationHelper(t, ol, edge, Set, txn) 325 require.EqualValues(t, 1, ol.Length(txn.StartTs, 0)) 326 checkValue(t, ol, "newcars", txn.StartTs) 327 } 328 329 func TestAddMutation_jchiu2_Commit(t *testing.T) { 330 key := x.DataKey("value", 16) 331 ol, err := GetNoStore(key) 332 require.NoError(t, err) 333 334 // Del a value cars and but don't merge. 335 edge := &pb.DirectedEdge{ 336 Value: []byte("cars"), 337 Label: "jchiu", 338 } 339 txn := &Txn{StartTs: 1} 340 addMutationHelper(t, ol, edge, Del, txn) 341 ol.commitMutation(1, uint64(2)) 342 require.EqualValues(t, 0, ol.Length(uint64(3), 0)) 343 344 // Set value to newcars, but don't merge yet. 345 edge = &pb.DirectedEdge{ 346 Value: []byte("newcars"), 347 Label: "jchiu", 348 } 349 txn = &Txn{StartTs: 3} 350 addMutationHelper(t, ol, edge, Set, txn) 351 ol.commitMutation(3, uint64(4)) 352 require.EqualValues(t, 1, ol.Length(5, 0)) 353 checkValue(t, ol, "newcars", 5) 354 } 355 356 func TestAddMutation_jchiu3(t *testing.T) { 357 key := x.DataKey("value", 29) 358 ol, err := GetNoStore(key) 359 require.NoError(t, err) 360 361 // Set value to cars and merge to BadgerDB. 362 edge := &pb.DirectedEdge{ 363 Value: []byte("cars"), 364 Label: "jchiu", 365 } 366 txn := &Txn{StartTs: 1} 367 addMutationHelper(t, ol, edge, Set, txn) 368 ol.commitMutation(1, uint64(2)) 369 require.Equal(t, 1, ol.Length(uint64(3), 0)) 370 require.EqualValues(t, 1, ol.Length(uint64(3), 0)) 371 checkValue(t, ol, "cars", uint64(3)) 372 373 // Del a value cars and but don't merge. 374 edge = &pb.DirectedEdge{ 375 Value: []byte("cars"), 376 Label: "jchiu", 377 } 378 txn = &Txn{StartTs: 3} 379 addMutationHelper(t, ol, edge, Del, txn) 380 require.Equal(t, 0, ol.Length(txn.StartTs, 0)) 381 382 // Set value to newcars, but don't merge yet. 383 edge = &pb.DirectedEdge{ 384 Value: []byte("newcars"), 385 Label: "jchiu", 386 } 387 addMutationHelper(t, ol, edge, Set, txn) 388 require.EqualValues(t, 1, ol.Length(txn.StartTs, 0)) 389 checkValue(t, ol, "newcars", txn.StartTs) 390 391 // Del a value newcars and but don't merge. 392 edge = &pb.DirectedEdge{ 393 Value: []byte("newcars"), 394 Label: "jchiu", 395 } 396 addMutationHelper(t, ol, edge, Del, txn) 397 require.Equal(t, 0, ol.Length(txn.StartTs, 0)) 398 } 399 400 func TestAddMutation_mrjn1(t *testing.T) { 401 key := x.DataKey("value", 21) 402 ol, err := GetNoStore(key) 403 require.NoError(t, err) 404 405 // Set a value cars and merge. 406 edge := &pb.DirectedEdge{ 407 Value: []byte("cars"), 408 Label: "jchiu", 409 } 410 txn := &Txn{StartTs: 1} 411 addMutationHelper(t, ol, edge, Set, txn) 412 ol.commitMutation(1, uint64(2)) 413 414 // Delete the previously committed value cars. But don't merge. 415 txn = &Txn{StartTs: 3} 416 edge = &pb.DirectedEdge{ 417 Value: []byte("cars"), 418 Label: "jchiu", 419 } 420 addMutationHelper(t, ol, edge, Del, txn) 421 require.Equal(t, 0, ol.Length(txn.StartTs, 0)) 422 423 // Do this again to cover Del, muid == curUid, inPlist test case. 424 // Delete the previously committed value cars. But don't merge. 425 edge = &pb.DirectedEdge{ 426 Value: []byte("cars"), 427 Label: "jchiu", 428 } 429 addMutationHelper(t, ol, edge, Del, txn) 430 require.Equal(t, 0, ol.Length(txn.StartTs, 0)) 431 432 // Set the value again to cover Set, muid == curUid, inPlist test case. 433 // Set the previously committed value cars. But don't merge. 434 edge = &pb.DirectedEdge{ 435 Value: []byte("cars"), 436 Label: "jchiu", 437 } 438 addMutationHelper(t, ol, edge, Set, txn) 439 checkValue(t, ol, "cars", txn.StartTs) 440 441 // Delete it again, just for fun. 442 edge = &pb.DirectedEdge{ 443 Value: []byte("cars"), 444 Label: "jchiu", 445 } 446 addMutationHelper(t, ol, edge, Del, txn) 447 require.Equal(t, 0, ol.Length(txn.StartTs, 0)) 448 } 449 450 func TestMillion(t *testing.T) { 451 // Ensure list is stored in a single part. 452 maxListSize = math.MaxInt32 453 454 key := x.DataKey("bal", 1331) 455 ol, err := getNew(key, ps) 456 require.NoError(t, err) 457 var commits int 458 N := int(1e6) 459 for i := 2; i <= N; i += 2 { 460 edge := &pb.DirectedEdge{ 461 ValueId: uint64(i), 462 } 463 txn := Txn{StartTs: uint64(i)} 464 addMutationHelper(t, ol, edge, Set, &txn) 465 require.NoError(t, ol.commitMutation(uint64(i), uint64(i)+1)) 466 if i%10000 == 0 { 467 // Do a rollup, otherwise, it gets too slow to add a million mutations to one posting 468 // list. 469 t.Logf("Start Ts: %d. Rolling up posting list.\n", txn.StartTs) 470 kvs, err := ol.Rollup() 471 require.NoError(t, err) 472 require.NoError(t, writePostingListToDisk(kvs)) 473 ol, err = getNew(key, ps) 474 require.NoError(t, err) 475 } 476 commits++ 477 } 478 479 t.Logf("Completed a million writes.\n") 480 opt := ListOptions{ReadTs: uint64(N) + 1} 481 l, err := ol.Uids(opt) 482 require.NoError(t, err) 483 require.Equal(t, commits, len(l.Uids), "List of Uids received: %+v", l.Uids) 484 for i, uid := range l.Uids { 485 require.Equal(t, uint64(i+1)*2, uid) 486 } 487 } 488 489 // Test the various mutate, commit and abort sequences. 490 func TestAddMutation_mrjn2(t *testing.T) { 491 ctx := context.Background() 492 key := x.DataKey("bal", 1001) 493 ol, err := getNew(key, ps) 494 require.NoError(t, err) 495 var readTs uint64 496 for readTs = 1; readTs < 10; readTs++ { 497 edge := &pb.DirectedEdge{ 498 ValueId: readTs, 499 ValueType: pb.Posting_INT, 500 } 501 txn := &Txn{StartTs: readTs} 502 addMutationHelper(t, ol, edge, Set, txn) 503 } 504 for i := 1; i < 10; i++ { 505 // Each of these txns see their own write. 506 opt := ListOptions{ReadTs: uint64(i)} 507 list, err := ol.Uids(opt) 508 require.NoError(t, err) 509 require.EqualValues(t, 1, len(list.Uids)) 510 require.EqualValues(t, uint64(i), list.Uids[0]) 511 } 512 require.EqualValues(t, 0, ol.Length(readTs, 0)) 513 require.NoError(t, ol.commitMutation(1, 0)) 514 require.NoError(t, ol.commitMutation(3, 4)) 515 require.NoError(t, ol.commitMutation(6, 10)) 516 require.NoError(t, ol.commitMutation(9, 14)) 517 require.EqualValues(t, 3, ol.Length(15, 0)) // The three commits. 518 519 { 520 edge := &pb.DirectedEdge{ 521 Value: []byte(x.Star), 522 Op: pb.DirectedEdge_DEL, 523 } 524 txn := &Txn{StartTs: 7} 525 err := ol.addMutation(ctx, txn, edge) 526 require.NoError(t, err) 527 528 // Add edge just to test that the deletion still happens. 529 edge = &pb.DirectedEdge{ 530 ValueId: 7, 531 ValueType: pb.Posting_INT, 532 } 533 err = ol.addMutation(ctx, txn, edge) 534 require.NoError(t, err) 535 536 require.EqualValues(t, 3, ol.Length(15, 0)) // The three commits should still be found. 537 require.NoError(t, ol.commitMutation(7, 11)) 538 539 require.EqualValues(t, 2, ol.Length(10, 0)) // Two commits should be found. 540 require.EqualValues(t, 1, ol.Length(12, 0)) // Only one commit should be found. 541 require.EqualValues(t, 2, ol.Length(15, 0)) // Only one commit should be found. 542 } 543 { 544 edge := &pb.DirectedEdge{ 545 Value: []byte(x.Star), 546 Op: pb.DirectedEdge_DEL, 547 } 548 txn := &Txn{StartTs: 5} 549 err := ol.addMutation(ctx, txn, edge) 550 require.NoError(t, err) 551 require.NoError(t, ol.commitMutation(5, 7)) 552 553 // Commits are: 554 // 4, 7 (Delete *), 10, 11 (Delete *), 14 555 require.EqualValues(t, 1, ol.Length(8, 0)) // Nothing below 8, but consider itself. 556 require.NoError(t, ol.commitMutation(8, 0)) 557 require.EqualValues(t, 0, ol.Length(8, 0)) // Nothing <= 8. 558 require.EqualValues(t, 1, ol.Length(10, 0)) // Find committed 10. 559 require.EqualValues(t, 1, ol.Length(12, 0)) // Find committed 11. 560 require.EqualValues(t, 2, ol.Length(15, 0)) // Find committed 14. 561 opts := ListOptions{ReadTs: 15} 562 list, err := ol.Uids(opts) 563 require.NoError(t, err) 564 require.EqualValues(t, 7, list.Uids[0]) 565 require.EqualValues(t, 9, list.Uids[1]) 566 } 567 } 568 569 func TestAddMutation_gru(t *testing.T) { 570 key := x.DataKey("question.tag", 0x01) 571 ol, err := getNew(key, ps) 572 require.NoError(t, err) 573 574 { 575 // Set two tag ids and merge. 576 edge := &pb.DirectedEdge{ 577 ValueId: 0x2b693088816b04b7, 578 Label: "gru", 579 } 580 txn := &Txn{StartTs: 1} 581 addMutationHelper(t, ol, edge, Set, txn) 582 edge = &pb.DirectedEdge{ 583 ValueId: 0x29bf442b48a772e0, 584 Label: "gru", 585 } 586 addMutationHelper(t, ol, edge, Set, txn) 587 ol.commitMutation(1, uint64(2)) 588 } 589 590 { 591 edge := &pb.DirectedEdge{ 592 ValueId: 0x38dec821d2ac3a79, 593 Label: "gru", 594 } 595 txn := &Txn{StartTs: 3} 596 addMutationHelper(t, ol, edge, Set, txn) 597 edge = &pb.DirectedEdge{ 598 ValueId: 0x2b693088816b04b7, 599 Label: "gru", 600 } 601 addMutationHelper(t, ol, edge, Del, txn) 602 ol.commitMutation(3, uint64(4)) 603 } 604 } 605 606 func TestAddMutation_gru2(t *testing.T) { 607 key := x.DataKey("question.tag", 0x100) 608 ol, err := getNew(key, ps) 609 require.NoError(t, err) 610 611 { 612 // Set two tag ids and merge. 613 edge := &pb.DirectedEdge{ 614 ValueId: 0x02, 615 Label: "gru", 616 } 617 txn := &Txn{StartTs: 1} 618 addMutationHelper(t, ol, edge, Set, txn) 619 edge = &pb.DirectedEdge{ 620 ValueId: 0x03, 621 Label: "gru", 622 } 623 txn = &Txn{StartTs: 1} 624 addMutationHelper(t, ol, edge, Set, txn) 625 ol.commitMutation(1, uint64(2)) 626 } 627 628 { 629 // Lets set a new tag and delete the two older ones. 630 edge := &pb.DirectedEdge{ 631 ValueId: 0x02, 632 Label: "gru", 633 } 634 txn := &Txn{StartTs: 3} 635 addMutationHelper(t, ol, edge, Del, txn) 636 edge = &pb.DirectedEdge{ 637 ValueId: 0x03, 638 Label: "gru", 639 } 640 addMutationHelper(t, ol, edge, Del, txn) 641 642 edge = &pb.DirectedEdge{ 643 ValueId: 0x04, 644 Label: "gru", 645 } 646 addMutationHelper(t, ol, edge, Set, txn) 647 648 ol.commitMutation(3, uint64(4)) 649 } 650 651 // Posting list should just have the new tag. 652 uids := []uint64{0x04} 653 require.Equal(t, uids, listToArray(t, 0, ol, uint64(5))) 654 } 655 656 func TestAddAndDelMutation(t *testing.T) { 657 // Ensure each test uses unique key since we don't clear the postings 658 // after each test 659 key := x.DataKey("dummy_key", 0x927) 660 ol, err := getNew(key, ps) 661 require.NoError(t, err) 662 663 { 664 edge := &pb.DirectedEdge{ 665 ValueId: 0x02, 666 Label: "gru", 667 } 668 txn := &Txn{StartTs: 1} 669 addMutationHelper(t, ol, edge, Set, txn) 670 ol.commitMutation(1, uint64(2)) 671 } 672 673 { 674 edge := &pb.DirectedEdge{ 675 ValueId: 0x02, 676 Label: "gru", 677 } 678 txn := &Txn{StartTs: 3} 679 addMutationHelper(t, ol, edge, Del, txn) 680 addMutationHelper(t, ol, edge, Del, txn) 681 ol.commitMutation(3, uint64(4)) 682 683 checkUids(t, ol, []uint64{}, 5) 684 } 685 checkUids(t, ol, []uint64{}, 5) 686 } 687 688 func TestAfterUIDCount(t *testing.T) { 689 key := x.DataKey("value", 22) 690 ol, err := getNew(key, ps) 691 require.NoError(t, err) 692 // Set value to cars and merge to BadgerDB. 693 edge := &pb.DirectedEdge{ 694 Label: "jchiu", 695 } 696 697 txn := &Txn{StartTs: 1} 698 for i := 100; i < 300; i++ { 699 edge.ValueId = uint64(i) 700 addMutationHelper(t, ol, edge, Set, txn) 701 } 702 require.EqualValues(t, 200, ol.Length(txn.StartTs, 0)) 703 require.EqualValues(t, 100, ol.Length(txn.StartTs, 199)) 704 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 705 706 // Delete half of the edges. 707 for i := 100; i < 300; i += 2 { 708 edge.ValueId = uint64(i) 709 addMutationHelper(t, ol, edge, Del, txn) 710 } 711 require.EqualValues(t, 100, ol.Length(txn.StartTs, 0)) 712 require.EqualValues(t, 50, ol.Length(txn.StartTs, 199)) 713 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 714 715 // Try to delete half of the edges. Redundant deletes. 716 for i := 100; i < 300; i += 2 { 717 edge.ValueId = uint64(i) 718 addMutationHelper(t, ol, edge, Del, txn) 719 } 720 require.EqualValues(t, 100, ol.Length(txn.StartTs, 0)) 721 require.EqualValues(t, 50, ol.Length(txn.StartTs, 199)) 722 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 723 724 // Delete everything. 725 for i := 100; i < 300; i++ { 726 edge.ValueId = uint64(i) 727 addMutationHelper(t, ol, edge, Del, txn) 728 } 729 require.EqualValues(t, 0, ol.Length(txn.StartTs, 0)) 730 require.EqualValues(t, 0, ol.Length(txn.StartTs, 199)) 731 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 732 733 // Insert 1/4 of the edges. 734 for i := 100; i < 300; i += 4 { 735 edge.ValueId = uint64(i) 736 addMutationHelper(t, ol, edge, Set, txn) 737 } 738 require.EqualValues(t, 50, ol.Length(txn.StartTs, 0)) 739 require.EqualValues(t, 25, ol.Length(txn.StartTs, 199)) 740 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 741 742 // Insert 1/4 of the edges. 743 edge.Label = "somethingelse" 744 for i := 100; i < 300; i += 4 { 745 edge.ValueId = uint64(i) 746 addMutationHelper(t, ol, edge, Set, txn) 747 } 748 require.EqualValues(t, 50, ol.Length(txn.StartTs, 0)) // Expect no change. 749 require.EqualValues(t, 25, ol.Length(txn.StartTs, 199)) 750 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 751 752 // Insert 1/4 of the edges. 753 for i := 103; i < 300; i += 4 { 754 edge.ValueId = uint64(i) 755 addMutationHelper(t, ol, edge, Set, txn) 756 } 757 require.EqualValues(t, 100, ol.Length(txn.StartTs, 0)) 758 require.EqualValues(t, 50, ol.Length(txn.StartTs, 199)) 759 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 760 } 761 762 func TestAfterUIDCount2(t *testing.T) { 763 key := x.DataKey("value", 23) 764 ol, err := getNew(key, ps) 765 require.NoError(t, err) 766 767 // Set value to cars and merge to BadgerDB. 768 edge := &pb.DirectedEdge{ 769 Label: "jchiu", 770 } 771 772 txn := &Txn{StartTs: 1} 773 for i := 100; i < 300; i++ { 774 edge.ValueId = uint64(i) 775 addMutationHelper(t, ol, edge, Set, txn) 776 } 777 require.EqualValues(t, 200, ol.Length(txn.StartTs, 0)) 778 require.EqualValues(t, 100, ol.Length(txn.StartTs, 199)) 779 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 780 781 // Re-insert 1/4 of the edges. Counts should not change. 782 edge.Label = "somethingelse" 783 for i := 100; i < 300; i += 4 { 784 edge.ValueId = uint64(i) 785 addMutationHelper(t, ol, edge, Set, txn) 786 } 787 require.EqualValues(t, 200, ol.Length(txn.StartTs, 0)) 788 require.EqualValues(t, 100, ol.Length(txn.StartTs, 199)) 789 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 790 } 791 792 func TestDelete(t *testing.T) { 793 key := x.DataKey("value", 25) 794 ol, err := getNew(key, ps) 795 require.NoError(t, err) 796 797 // Set value to cars and merge to BadgerDB. 798 edge := &pb.DirectedEdge{ 799 Label: "jchiu", 800 } 801 802 txn := &Txn{StartTs: 1} 803 for i := 1; i <= 30; i++ { 804 edge.ValueId = uint64(i) 805 addMutationHelper(t, ol, edge, Set, txn) 806 } 807 require.EqualValues(t, 30, ol.Length(txn.StartTs, 0)) 808 edge.Value = []byte(x.Star) 809 addMutationHelper(t, ol, edge, Del, txn) 810 require.EqualValues(t, 0, ol.Length(txn.StartTs, 0)) 811 ol.commitMutation(txn.StartTs, txn.StartTs+1) 812 813 require.EqualValues(t, 0, ol.Length(txn.StartTs+2, 0)) 814 } 815 816 func TestAfterUIDCountWithCommit(t *testing.T) { 817 key := x.DataKey("value", 26) 818 ol, err := getNew(key, ps) 819 require.NoError(t, err) 820 821 // Set value to cars and merge to BadgerDB. 822 edge := &pb.DirectedEdge{ 823 Label: "jchiu", 824 } 825 826 txn := &Txn{StartTs: 1} 827 for i := 100; i < 400; i++ { 828 edge.ValueId = uint64(i) 829 addMutationHelper(t, ol, edge, Set, txn) 830 } 831 require.EqualValues(t, 300, ol.Length(txn.StartTs, 0)) 832 require.EqualValues(t, 200, ol.Length(txn.StartTs, 199)) 833 require.EqualValues(t, 0, ol.Length(txn.StartTs, 400)) 834 835 // Commit to database. 836 ol.commitMutation(txn.StartTs, txn.StartTs+1) 837 838 txn = &Txn{StartTs: 3} 839 // Mutation layer starts afresh from here. 840 // Delete half of the edges. 841 for i := 100; i < 400; i += 2 { 842 edge.ValueId = uint64(i) 843 addMutationHelper(t, ol, edge, Del, txn) 844 } 845 require.EqualValues(t, 150, ol.Length(txn.StartTs, 0)) 846 require.EqualValues(t, 100, ol.Length(txn.StartTs, 199)) 847 require.EqualValues(t, 0, ol.Length(txn.StartTs, 400)) 848 849 // Try to delete half of the edges. Redundant deletes. 850 for i := 100; i < 400; i += 2 { 851 edge.ValueId = uint64(i) 852 addMutationHelper(t, ol, edge, Del, txn) 853 } 854 require.EqualValues(t, 150, ol.Length(txn.StartTs, 0)) 855 require.EqualValues(t, 100, ol.Length(txn.StartTs, 199)) 856 require.EqualValues(t, 0, ol.Length(txn.StartTs, 400)) 857 858 // Delete everything. 859 for i := 100; i < 400; i++ { 860 edge.ValueId = uint64(i) 861 addMutationHelper(t, ol, edge, Del, txn) 862 } 863 require.EqualValues(t, 0, ol.Length(txn.StartTs, 0)) 864 require.EqualValues(t, 0, ol.Length(txn.StartTs, 199)) 865 require.EqualValues(t, 0, ol.Length(txn.StartTs, 400)) 866 867 // Insert 1/4 of the edges. 868 for i := 100; i < 300; i += 4 { 869 edge.ValueId = uint64(i) 870 addMutationHelper(t, ol, edge, Set, txn) 871 } 872 require.EqualValues(t, 50, ol.Length(txn.StartTs, 0)) 873 require.EqualValues(t, 25, ol.Length(txn.StartTs, 199)) 874 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 875 876 // Insert 1/4 of the edges. 877 edge.Label = "somethingelse" 878 for i := 100; i < 300; i += 4 { 879 edge.ValueId = uint64(i) 880 addMutationHelper(t, ol, edge, Set, txn) 881 } 882 require.EqualValues(t, 50, ol.Length(txn.StartTs, 0)) // Expect no change. 883 require.EqualValues(t, 25, ol.Length(txn.StartTs, 199)) 884 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 885 886 // Insert 1/4 of the edges. 887 for i := 103; i < 300; i += 4 { 888 edge.ValueId = uint64(i) 889 addMutationHelper(t, ol, edge, Set, txn) 890 } 891 require.EqualValues(t, 100, ol.Length(txn.StartTs, 0)) 892 require.EqualValues(t, 50, ol.Length(txn.StartTs, 199)) 893 require.EqualValues(t, 0, ol.Length(txn.StartTs, 300)) 894 } 895 896 func createMultiPartList(t *testing.T, size int, addLabel bool) (*List, int) { 897 // For testing, set the max list size to a lower threshold. 898 maxListSize = 5000 899 defer func() { 900 maxListSize = math.MaxInt32 901 }() 902 903 key := x.DataKey("multi-bal", 1331) 904 ol, err := getNew(key, ps) 905 require.NoError(t, err) 906 commits := 0 907 for i := 1; i <= size; i++ { 908 edge := &pb.DirectedEdge{ 909 ValueId: uint64(i), 910 } 911 if addLabel { 912 edge.Label = strconv.Itoa(i) 913 } 914 915 txn := Txn{StartTs: uint64(i)} 916 addMutationHelper(t, ol, edge, Set, &txn) 917 require.NoError(t, ol.commitMutation(uint64(i), uint64(i)+1)) 918 if i%2000 == 0 { 919 kvs, err := ol.Rollup() 920 require.NoError(t, err) 921 require.NoError(t, writePostingListToDisk(kvs)) 922 ol, err = getNew(key, ps) 923 require.NoError(t, err) 924 } 925 commits++ 926 } 927 928 kvs, err := ol.Rollup() 929 require.NoError(t, err) 930 require.NoError(t, writePostingListToDisk(kvs)) 931 ol, err = getNew(key, ps) 932 require.NoError(t, err) 933 934 return ol, commits 935 } 936 937 func createAndDeleteMultiPartList(t *testing.T, size int) (*List, int) { 938 // For testing, set the max list size to a lower threshold. 939 maxListSize = 5000 940 defer func() { 941 maxListSize = math.MaxInt32 942 }() 943 944 key := x.DataKey("bal_del", 1331) 945 ol, err := getNew(key, ps) 946 require.NoError(t, err) 947 commits := 0 948 for i := 1; i <= size; i++ { 949 edge := &pb.DirectedEdge{ 950 ValueId: uint64(i), 951 } 952 953 txn := Txn{StartTs: uint64(i)} 954 addMutationHelper(t, ol, edge, Set, &txn) 955 require.NoError(t, ol.commitMutation(uint64(i), uint64(i)+1)) 956 if i%2000 == 0 { 957 kvs, err := ol.Rollup() 958 require.NoError(t, err) 959 require.NoError(t, writePostingListToDisk(kvs)) 960 ol, err = getNew(key, ps) 961 require.NoError(t, err) 962 } 963 commits++ 964 } 965 966 // Delete all the previously inserted entries from the list. 967 baseStartTs := uint64(size) + 1 968 for i := 1; i <= size; i++ { 969 edge := &pb.DirectedEdge{ 970 ValueId: uint64(i), 971 } 972 txn := Txn{StartTs: baseStartTs + uint64(i)} 973 addMutationHelper(t, ol, edge, Del, &txn) 974 require.NoError(t, ol.commitMutation(baseStartTs+uint64(i), baseStartTs+uint64(i)+1)) 975 if i%2000 == 0 { 976 kvs, err := ol.Rollup() 977 require.NoError(t, err) 978 require.NoError(t, writePostingListToDisk(kvs)) 979 ol, err = getNew(key, ps) 980 require.NoError(t, err) 981 } 982 commits++ 983 } 984 985 return ol, commits 986 } 987 988 func writePostingListToDisk(kvs []*bpb.KV) error { 989 writer := NewTxnWriter(pstore) 990 for _, kv := range kvs { 991 if err := writer.SetAt(kv.Key, kv.Value, kv.UserMeta[0], kv.Version); err != nil { 992 return err 993 } 994 } 995 return writer.Flush() 996 } 997 998 // Create a multi-part list and verify all the uids are there. 999 func TestMultiPartListBasic(t *testing.T) { 1000 size := int(1e5) 1001 ol, commits := createMultiPartList(t, size, false) 1002 t.Logf("List parts %v", len(ol.plist.Splits)) 1003 opt := ListOptions{ReadTs: uint64(size) + 1} 1004 l, err := ol.Uids(opt) 1005 require.NoError(t, err) 1006 require.Equal(t, commits, len(l.Uids), "List of Uids received: %+v", l.Uids) 1007 for i, uid := range l.Uids { 1008 require.Equal(t, uint64(i+1), uid) 1009 } 1010 } 1011 1012 // Verify that iteration works with an afterUid value greater than zero. 1013 func TestMultiPartListIterAfterUid(t *testing.T) { 1014 size := int(1e5) 1015 ol, _ := createMultiPartList(t, size, false) 1016 t.Logf("List parts %v", len(ol.plist.Splits)) 1017 1018 var visitedUids []uint64 1019 ol.Iterate(uint64(size+1), 50000, func(p *pb.Posting) error { 1020 visitedUids = append(visitedUids, p.Uid) 1021 return nil 1022 }) 1023 require.Equal(t, 50000, len(visitedUids)) 1024 for i, uid := range visitedUids { 1025 require.Equal(t, uint64(50000+i+1), uid) 1026 } 1027 } 1028 1029 // Verify that postings can be retrieved in multi-part lists. 1030 func TestMultiPartListWithPostings(t *testing.T) { 1031 size := int(1e5) 1032 ol, commits := createMultiPartList(t, size, true) 1033 t.Logf("List parts %v", len(ol.plist.Splits)) 1034 1035 var labels []string 1036 err := ol.Iterate(uint64(size)+1, 0, func(p *pb.Posting) error { 1037 if len(p.Label) > 0 { 1038 labels = append(labels, p.Label) 1039 } 1040 return nil 1041 }) 1042 require.NoError(t, err) 1043 require.Equal(t, commits, len(labels)) 1044 for i, label := range labels { 1045 require.Equal(t, label, strconv.Itoa(int(i+1))) 1046 } 1047 } 1048 1049 // Verify marshaling of multi-part lists. 1050 func TestMultiPartListMarshal(t *testing.T) { 1051 size := int(1e5) 1052 ol, _ := createMultiPartList(t, size, false) 1053 t.Logf("List parts %v", len(ol.plist.Splits)) 1054 1055 kvs, err := ol.Rollup() 1056 require.NoError(t, err) 1057 require.Equal(t, len(kvs), len(ol.plist.Splits)+1) 1058 require.NoError(t, writePostingListToDisk(kvs)) 1059 1060 sort.Slice(kvs, func(i, j int) bool { 1061 return string(kvs[i].Key) < string(kvs[j].Key) 1062 }) 1063 1064 key := x.DataKey("multi-bal", 1331) 1065 require.Equal(t, key, kvs[0].Key) 1066 1067 for i, startUid := range ol.plist.Splits { 1068 partKey, err := x.GetSplitKey(key, startUid) 1069 require.NoError(t, err) 1070 require.Equal(t, partKey, kvs[i+1].Key) 1071 part, err := ol.readListPart(startUid) 1072 require.NoError(t, err) 1073 data, err := part.Marshal() 1074 require.NoError(t, err) 1075 require.Equal(t, data, kvs[i+1].Value) 1076 require.Equal(t, []byte{BitCompletePosting}, kvs[i+1].UserMeta) 1077 require.Equal(t, ol.minTs, kvs[i+1].Version) 1078 } 1079 } 1080 1081 // Verify that writing a multi-part list to disk works correctly. 1082 func TestMultiPartListWriteToDisk(t *testing.T) { 1083 size := int(1e5) 1084 originalList, commits := createMultiPartList(t, size, false) 1085 1086 kvs, err := originalList.Rollup() 1087 require.NoError(t, err) 1088 require.Equal(t, len(kvs), len(originalList.plist.Splits)+1) 1089 1090 require.NoError(t, writePostingListToDisk(kvs)) 1091 newList, err := getNew(kvs[0].Key, ps) 1092 require.NoError(t, err) 1093 1094 opt := ListOptions{ReadTs: uint64(size) + 1} 1095 originalUids, err := originalList.Uids(opt) 1096 require.NoError(t, err) 1097 newUids, err := newList.Uids(opt) 1098 require.NoError(t, err) 1099 require.Equal(t, commits, len(originalUids.Uids)) 1100 require.Equal(t, len(originalUids.Uids), len(newUids.Uids)) 1101 for i := range originalUids.Uids { 1102 require.Equal(t, originalUids.Uids[i], newUids.Uids[i]) 1103 } 1104 } 1105 1106 // Verify that adding and deleting all the entries returns an empty list. 1107 func TestMultiPartListDelete(t *testing.T) { 1108 size := int(1e4) 1109 ol, commits := createAndDeleteMultiPartList(t, size) 1110 t.Logf("List parts %v", len(ol.plist.Splits)) 1111 require.Equal(t, size*2, commits) 1112 1113 counter := 0 1114 ol.Iterate(math.MaxUint64, 0, func(p *pb.Posting) error { 1115 counter++ 1116 return nil 1117 }) 1118 require.Equal(t, 0, counter) 1119 1120 kvs, err := ol.Rollup() 1121 require.NoError(t, err) 1122 require.Equal(t, len(kvs), 1) 1123 1124 for _, kv := range kvs { 1125 require.Equal(t, []byte{BitEmptyPosting}, kv.UserMeta) 1126 require.Equal(t, ol.minTs, kv.Version) 1127 } 1128 } 1129 1130 // Verify that the first part of a multi-part list is kept even when all its 1131 // entries have been deleted. Do this by creating a list, deleting the first 1132 // half, and ensuring iteration and mutation still work as expected. 1133 func TestMultiPartListDeleteAndAdd(t *testing.T) { 1134 size := int(1e5) 1135 // For testing, set the max list size to a lower threshold. 1136 maxListSize = 5000 1137 defer func() { 1138 maxListSize = math.MaxInt32 1139 }() 1140 1141 // Add entries to the maps. 1142 key := x.DataKey("del_add", 1331) 1143 ol, err := getNew(key, ps) 1144 require.NoError(t, err) 1145 for i := 1; i <= size; i++ { 1146 edge := &pb.DirectedEdge{ 1147 ValueId: uint64(i), 1148 } 1149 1150 txn := Txn{StartTs: uint64(i)} 1151 addMutationHelper(t, ol, edge, Set, &txn) 1152 require.NoError(t, ol.commitMutation(uint64(i), uint64(i)+1)) 1153 if i%2000 == 0 { 1154 kvs, err := ol.Rollup() 1155 require.NoError(t, err) 1156 require.NoError(t, writePostingListToDisk(kvs)) 1157 ol, err = getNew(key, ps) 1158 require.NoError(t, err) 1159 } 1160 } 1161 1162 // Verify all entries are in the list. 1163 opt := ListOptions{ReadTs: math.MaxUint64} 1164 l, err := ol.Uids(opt) 1165 require.NoError(t, err) 1166 require.Equal(t, size, len(l.Uids), "List of Uids received: %+v", l.Uids) 1167 for i, uid := range l.Uids { 1168 require.Equal(t, uint64(i+1), uid) 1169 } 1170 1171 // Delete the first half of the previously inserted entries from the list. 1172 baseStartTs := uint64(size) + 1 1173 for i := 1; i <= 50000; i++ { 1174 edge := &pb.DirectedEdge{ 1175 ValueId: uint64(i), 1176 } 1177 txn := Txn{StartTs: baseStartTs + uint64(i)} 1178 addMutationHelper(t, ol, edge, Del, &txn) 1179 require.NoError(t, ol.commitMutation(baseStartTs+uint64(i), baseStartTs+uint64(i)+1)) 1180 if i%2000 == 0 { 1181 kvs, err := ol.Rollup() 1182 require.NoError(t, err) 1183 require.NoError(t, writePostingListToDisk(kvs)) 1184 ol, err = getNew(key, ps) 1185 require.NoError(t, err) 1186 } 1187 } 1188 1189 // Rollup list at the end of all the deletions. 1190 kvs, err := ol.Rollup() 1191 require.NoError(t, err) 1192 require.NoError(t, writePostingListToDisk(kvs)) 1193 ol, err = getNew(key, ps) 1194 require.NoError(t, err) 1195 1196 // Verify that the entries were actually deleted. 1197 opt = ListOptions{ReadTs: math.MaxUint64} 1198 l, err = ol.Uids(opt) 1199 require.NoError(t, err) 1200 require.Equal(t, 50000, len(l.Uids), "List of Uids received: %+v", l.Uids) 1201 for i, uid := range l.Uids { 1202 require.Equal(t, 50000+uint64(i+1), uid) 1203 } 1204 1205 // Re-add the entries that were just deleted. 1206 baseStartTs = uint64(2*size) + 1 1207 for i := 1; i <= 50000; i++ { 1208 edge := &pb.DirectedEdge{ 1209 ValueId: uint64(i), 1210 } 1211 txn := Txn{StartTs: baseStartTs + uint64(i)} 1212 addMutationHelper(t, ol, edge, Set, &txn) 1213 require.NoError(t, ol.commitMutation(baseStartTs+uint64(i), baseStartTs+uint64(i)+1)) 1214 1215 if i%2000 == 0 { 1216 kvs, err := ol.Rollup() 1217 require.NoError(t, err) 1218 require.NoError(t, writePostingListToDisk(kvs)) 1219 ol, err = getNew(key, ps) 1220 require.NoError(t, err) 1221 } 1222 } 1223 1224 // Rollup list at the end of all the additions 1225 kvs, err = ol.Rollup() 1226 require.NoError(t, err) 1227 require.NoError(t, writePostingListToDisk(kvs)) 1228 ol, err = getNew(key, ps) 1229 require.NoError(t, err) 1230 1231 // Verify all entries are once again in the list. 1232 opt = ListOptions{ReadTs: math.MaxUint64} 1233 l, err = ol.Uids(opt) 1234 require.NoError(t, err) 1235 require.Equal(t, size, len(l.Uids), "List of Uids received: %+v", l.Uids) 1236 for i, uid := range l.Uids { 1237 require.Equal(t, uint64(i+1), uid) 1238 } 1239 } 1240 1241 var ps *badger.DB 1242 1243 func TestMain(m *testing.M) { 1244 x.Init() 1245 Config.AllottedMemory = 1024.0 1246 Config.CommitFraction = 0.10 1247 1248 dir, err := ioutil.TempDir("", "storetest_") 1249 x.Check(err) 1250 1251 ps, err = badger.OpenManaged(badger.DefaultOptions(dir)) 1252 x.Check(err) 1253 Init(ps) 1254 schema.Init(ps) 1255 1256 r := m.Run() 1257 1258 os.RemoveAll(dir) 1259 os.Exit(r) 1260 } 1261 1262 func BenchmarkAddMutations(b *testing.B) { 1263 key := x.DataKey("name", 1) 1264 l, err := getNew(key, ps) 1265 if err != nil { 1266 b.Error(err) 1267 } 1268 b.ResetTimer() 1269 1270 ctx := context.Background() 1271 for i := 0; i < b.N; i++ { 1272 if err != nil { 1273 b.Error(err) 1274 return 1275 } 1276 edge := &pb.DirectedEdge{ 1277 ValueId: uint64(rand.Intn(b.N) + 1), 1278 Label: "testing", 1279 Op: pb.DirectedEdge_SET, 1280 } 1281 txn := &Txn{StartTs: 1} 1282 if err = l.addMutation(ctx, txn, edge); err != nil { 1283 b.Error(err) 1284 } 1285 } 1286 }