go.mercari.io/datastore@v1.8.2/testbed/clouddatastore_test.go (about) 1 package testbed 2 3 import ( 4 "context" 5 "fmt" 6 "reflect" 7 "sync" 8 "testing" 9 10 "cloud.google.com/go/datastore" 11 "go.mercari.io/datastore/internal" 12 "golang.org/x/sync/errgroup" 13 "google.golang.org/api/iterator" 14 ) 15 16 type CloudDatastoreStruct struct { 17 Test string 18 } 19 20 func cleanUp() error { 21 ctx := context.Background() 22 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 23 if err != nil { 24 return err 25 } 26 defer client.Close() 27 28 q := datastore.NewQuery("__kind__").KeysOnly() 29 iter := client.Run(ctx, q) 30 var kinds []string 31 for { 32 key, err := iter.Next(nil) 33 if err == iterator.Done { 34 break 35 } 36 if err != nil { 37 return err 38 } 39 kinds = append(kinds, key.Name) 40 } 41 42 for _, kind := range kinds { 43 q := datastore.NewQuery(kind).KeysOnly() 44 keys, err := client.GetAll(ctx, q, nil) 45 if err != nil { 46 return err 47 } 48 err = client.DeleteMulti(ctx, keys) 49 if err != nil { 50 return err 51 } 52 } 53 54 return nil 55 } 56 57 func TestCloudDatastore_Put(t *testing.T) { 58 ctx := context.Background() 59 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 60 if err != nil { 61 t.Fatal(err.Error()) 62 } 63 defer client.Close() 64 defer cleanUp() 65 66 key := datastore.IncompleteKey("CloudDatastoreStruct", nil) 67 key, err = client.Put(ctx, key, &CloudDatastoreStruct{"Hi!"}) 68 if err != nil { 69 t.Fatal(err.Error()) 70 } 71 72 t.Logf("key: %s", key.String()) 73 } 74 75 func TestCloudDatastore_GetMulti(t *testing.T) { 76 ctx := context.Background() 77 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 78 if err != nil { 79 t.Fatal(err.Error()) 80 } 81 defer client.Close() 82 defer cleanUp() 83 84 type Data struct { 85 Str string 86 } 87 88 key1, err := client.Put(ctx, datastore.IDKey("Data", 1, nil), &Data{"Data1"}) 89 if err != nil { 90 t.Fatal(err.Error()) 91 } 92 key2, err := client.Put(ctx, datastore.IDKey("Data", 2, nil), &Data{"Data2"}) 93 if err != nil { 94 t.Fatal(err.Error()) 95 } 96 97 list := make([]*Data, 2) 98 err = client.GetMulti(ctx, []*datastore.Key{key1, key2}, list) 99 if err != nil { 100 t.Fatal(err.Error()) 101 } 102 103 if v := len(list); v != 2 { 104 t.Fatalf("unexpected: %v", v) 105 } 106 } 107 108 func TestCloudDatastore_Transaction(t *testing.T) { 109 ctx := context.Background() 110 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 111 if err != nil { 112 t.Fatal(err.Error()) 113 } 114 defer client.Close() 115 defer cleanUp() 116 117 key := datastore.IncompleteKey("CloudDatastoreStruct", nil) 118 key, err = client.Put(ctx, key, &CloudDatastoreStruct{"Hi!"}) 119 if err != nil { 120 t.Fatal(err.Error()) 121 } 122 123 { // Commit 124 tx, err := client.NewTransaction(ctx) 125 if err != nil { 126 t.Fatal(err.Error()) 127 } 128 129 s := &CloudDatastoreStruct{} 130 err = tx.Get(key, s) 131 if err != nil { 132 t.Fatal(err.Error()) 133 } 134 135 s.Test = "Updated 1" 136 _, err = tx.Put(key, s) 137 if err != nil { 138 t.Fatal(err.Error()) 139 } 140 141 _, err = tx.Commit() 142 if err != nil { 143 t.Fatal(err.Error()) 144 } 145 146 // should updated 147 newS := &CloudDatastoreStruct{} 148 err = client.Get(ctx, key, newS) 149 if err != nil { 150 t.Fatal(err.Error()) 151 } 152 153 if v := newS.Test; v != "Updated 1" { 154 t.Fatalf("unexpected: %+v", v) 155 } 156 } 157 { // Rollback 158 tx, err := client.NewTransaction(ctx) 159 if err != nil { 160 t.Fatal(err.Error()) 161 } 162 163 s := &CloudDatastoreStruct{} 164 err = tx.Get(key, s) 165 if err != nil { 166 t.Fatal(err.Error()) 167 } 168 169 s.Test = "Updated 2" 170 _, err = tx.Put(key, s) 171 if err != nil { 172 t.Fatal(err.Error()) 173 } 174 175 err = tx.Rollback() 176 if err != nil { 177 t.Fatal(err.Error()) 178 } 179 180 // should not updated 181 newS := &CloudDatastoreStruct{} 182 err = client.Get(ctx, key, newS) 183 if err != nil { 184 t.Fatal(err.Error()) 185 } 186 187 if v := newS.Test; v != "Updated 1" { 188 t.Fatalf("unexpected: %+v", v) 189 } 190 } 191 192 t.Logf("key: %s", key.String()) 193 } 194 195 func TestCloudDatastore_TransactionDeleteAndGet(t *testing.T) { 196 ctx := context.Background() 197 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 198 if err != nil { 199 t.Fatal(err.Error()) 200 } 201 defer client.Close() 202 defer cleanUp() 203 204 type Data struct { 205 Str string 206 } 207 208 key, err := client.Put(ctx, datastore.IncompleteKey("Data", nil), &Data{"Data"}) 209 if err != nil { 210 t.Fatal(err.Error()) 211 } 212 213 tx, err := client.NewTransaction(ctx) 214 if err != nil { 215 t.Fatal(err.Error()) 216 } 217 218 err = tx.Delete(key) 219 if err != nil { 220 t.Fatal(err.Error()) 221 } 222 223 obj := &Data{} 224 err = tx.Get(key, obj) 225 if err != nil { 226 t.Fatalf("unexpected: %v", err) 227 } 228 229 err = tx.Rollback() 230 if err != nil { 231 t.Fatal(err.Error()) 232 } 233 } 234 235 func TestCloudDatastore_SingleToBatch(t *testing.T) { 236 ctx := context.Background() 237 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 238 if err != nil { 239 t.Fatal(err.Error()) 240 } 241 defer client.Close() 242 defer cleanUp() 243 244 type putResult struct { 245 key *datastore.Key 246 error error 247 } 248 249 var m sync.Mutex 250 var keys []*datastore.Key 251 var srcList []interface{} 252 var cList []chan *putResult 253 254 put := func(key *datastore.Key, src interface{}) chan *putResult { 255 m.Lock() 256 defer m.Unlock() 257 258 c := make(chan *putResult) 259 260 keys = append(keys, key) 261 srcList = append(srcList, src) 262 cList = append(cList, c) 263 264 return c 265 } 266 execBatchOps := func() { 267 newKeys, err := client.PutMulti(ctx, keys, srcList) 268 if merr, ok := err.(datastore.MultiError); ok { 269 for idx, err := range merr { 270 c := cList[idx] 271 if err != nil { 272 c <- &putResult{error: err} 273 } else { 274 c <- &putResult{key: newKeys[idx]} 275 } 276 } 277 return 278 } else if err != nil { 279 for _, c := range cList { 280 c <- &putResult{error: err} 281 } 282 return 283 } 284 285 for idx, newKey := range newKeys { 286 c := cList[idx] 287 c <- &putResult{key: newKey} 288 } 289 } 290 unwrap := func(r *putResult) (key *datastore.Key, err error) { 291 if r.error != nil { 292 return nil, r.error 293 } 294 295 return r.key, nil 296 } 297 298 eg := &errgroup.Group{} 299 { // 1st entity 300 301 key := datastore.IncompleteKey("CloudDatastoreStruct", nil) 302 c := put(key, &CloudDatastoreStruct{"Hi!"}) 303 eg.Go(func() error { 304 key, err := unwrap(<-c) 305 if err != nil { 306 return err 307 } 308 t.Logf("#1: %s", key.String()) 309 return nil 310 }) 311 } 312 { // 2nd entity 313 key := datastore.IncompleteKey("CloudDatastoreStruct", nil) 314 c := put(key, &CloudDatastoreStruct{"Hi!"}) 315 eg.Go(func() error { 316 key, err := unwrap(<-c) 317 if err != nil { 318 return err 319 } 320 t.Logf("#2: %s", key.String()) 321 return nil 322 }) 323 } 324 325 execBatchOps() 326 err = eg.Wait() 327 if err != nil { 328 t.Fatal(err.Error()) 329 } 330 } 331 332 func TestCloudDatastore_Query(t *testing.T) { 333 ctx := context.Background() 334 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 335 if err != nil { 336 t.Fatal(err.Error()) 337 } 338 defer client.Close() 339 defer cleanUp() 340 341 type Data struct { 342 Str string 343 } 344 345 _, err = client.Put(ctx, datastore.IncompleteKey("Data", nil), &Data{"Data1"}) 346 if err != nil { 347 t.Fatal(err.Error()) 348 } 349 _, err = client.Put(ctx, datastore.IncompleteKey("Data", nil), &Data{"Data2"}) 350 if err != nil { 351 t.Fatal(err.Error()) 352 } 353 354 q := datastore.NewQuery("Data").Filter("Str =", "Data2") 355 { 356 var list []*Data 357 _, err = client.GetAll(ctx, q, &list) 358 if err != nil { 359 t.Fatal(err.Error()) 360 } 361 362 if v := len(list); v != 1 { 363 t.Fatalf("unexpected: %v", v) 364 } 365 } 366 { 367 keys, err := client.GetAll(ctx, q.KeysOnly(), nil) 368 if err != nil { 369 t.Fatal(err.Error()) 370 } 371 372 if v := len(keys); v != 1 { 373 t.Fatalf("unexpected: %v", v) 374 } 375 } 376 } 377 378 func TestCloudDatastore_QueryCursor(t *testing.T) { 379 ctx := context.Background() 380 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 381 if err != nil { 382 t.Fatal(err.Error()) 383 } 384 defer client.Close() 385 defer cleanUp() 386 387 type Data struct { 388 Str string 389 } 390 391 { 392 var keys []*datastore.Key 393 var entities []*Data 394 for i := 0; i < 100; i++ { 395 keys = append(keys, datastore.IncompleteKey("Data", nil)) 396 entities = append(entities, &Data{Str: fmt.Sprintf("#%d", i+1)}) 397 } 398 _, err = client.PutMulti(ctx, keys, entities) 399 if err != nil { 400 t.Fatal(err) 401 } 402 } 403 404 var cur datastore.Cursor 405 var dataList []*Data 406 const limit = 3 407 outer: 408 for { 409 q := datastore.NewQuery("Data").Order("Str").Limit(limit) 410 if cur.String() != "" { 411 q = q.Start(cur) 412 } 413 it := client.Run(ctx, q) 414 415 count := 0 416 for { 417 obj := &Data{} 418 _, err := it.Next(obj) 419 if err == iterator.Done { 420 break 421 } else if err != nil { 422 t.Fatal(err) 423 } 424 425 dataList = append(dataList, obj) 426 count++ 427 } 428 if count != limit { 429 break 430 } 431 432 cur, err = it.Cursor() 433 if err != nil { 434 t.Fatal(err) 435 } 436 if cur.String() == "" { 437 break outer 438 } 439 } 440 441 if v := len(dataList); v != 100 { 442 t.Errorf("unexpected: %v", v) 443 } 444 } 445 446 func TestCloudDatastore_ErrConcurrentTransaction(t *testing.T) { 447 ctx := context.Background() 448 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 449 if err != nil { 450 t.Fatal(err.Error()) 451 } 452 defer client.Close() 453 defer cleanUp() 454 455 type Data struct { 456 Str string 457 } 458 459 key := datastore.NameKey("Data", "a", nil) 460 _, err = client.Put(ctx, key, &Data{}) 461 if err != nil { 462 t.Fatal(err) 463 } 464 465 // ErrConcurrent will be occur 466 _, err = client.RunInTransaction(ctx, func(tx1 *datastore.Transaction) error { 467 err := tx1.Get(key, &Data{}) 468 if err != nil { 469 return err 470 } 471 472 _, err = client.RunInTransaction(ctx, func(tx2 *datastore.Transaction) error { 473 err := tx2.Get(key, &Data{}) 474 if err != nil { 475 return err 476 } 477 478 _, err = tx2.Put(key, &Data{Str: "#2"}) 479 return err 480 }) 481 if err != nil { 482 return err 483 } 484 485 _, err = tx1.Put(key, &Data{Str: "#1"}) 486 return err 487 }) 488 if err != datastore.ErrConcurrentTransaction { 489 t.Fatal(err) 490 } 491 } 492 493 func TestCloudDatastore_ObjectHasObjectSlice(t *testing.T) { 494 type Inner struct { 495 A string 496 B string 497 } 498 499 type Data struct { 500 Slice []Inner 501 } 502 503 ps, err := datastore.SaveStruct(&Data{ 504 Slice: []Inner{ 505 {A: "A1", B: "B1"}, 506 {A: "A2", B: "B2"}, 507 {A: "A3", B: "B3"}, 508 }, 509 }) 510 if err != nil { 511 t.Fatal(err) 512 } 513 514 if v := len(ps); v != 1 { 515 t.Fatalf("unexpected: %v", v) 516 } 517 p := ps[0] 518 if v := p.Name; v != "Slice" { 519 t.Fatalf("unexpected: %v", v) 520 } 521 es := p.Value.([]interface{}) 522 if v := len(es); v != 3 { 523 t.Fatalf("unexpected: %v", v) 524 } 525 526 expects := []struct { 527 Name string 528 Value string 529 }{ 530 {"A", "A1"}, 531 {"B", "B1"}, 532 {"A", "A2"}, 533 {"B", "B2"}, 534 {"A", "A3"}, 535 {"B", "B3"}, 536 } 537 538 for idx, entity := range es { 539 e := entity.(*datastore.Entity) 540 if v := len(e.Properties); v != 2 { 541 t.Fatalf("unexpected: %v", v) 542 } 543 for pIdx, p := range e.Properties { 544 expect := expects[idx*len(e.Properties)+pIdx] 545 if v := p.Name; v != expect.Name { 546 t.Errorf("unexpected: %v", v) 547 } 548 if v := p.Value.(string); v != expect.Value { 549 t.Errorf("unexpected: %v", v) 550 } 551 } 552 } 553 } 554 555 func TestCloudDatastore_ObjectHasObjectSliceFlatten(t *testing.T) { 556 type Inner struct { 557 A string 558 B string 559 } 560 561 type Data struct { 562 Slice []Inner `datastore:",flatten"` 563 } 564 565 ps, err := datastore.SaveStruct(&Data{ 566 Slice: []Inner{ 567 {A: "A1", B: "B1"}, 568 {A: "A2", B: "B2"}, 569 {A: "A3", B: "B3"}, 570 }, 571 }) 572 if err != nil { 573 t.Fatal(err) 574 } 575 576 if v := len(ps); v != 2 { 577 t.Fatalf("unexpected: %v", v) 578 } 579 580 expects := []struct { 581 Name string 582 Values []interface{} 583 }{ 584 {"Slice.A", []interface{}{"A1", "A2", "A3"}}, 585 {"Slice.B", []interface{}{"B1", "B2", "B3"}}, 586 } 587 for idx, expect := range expects { 588 p := ps[idx] 589 if v := p.Name; v != expect.Name { 590 t.Fatalf("unexpected: %v", v) 591 } 592 if v := p.Value.([]interface{}); !reflect.DeepEqual(v, expect.Values) { 593 t.Fatalf("unexpected: %v", v) 594 } 595 } 596 } 597 598 func TestCloudDatastore_NestedEntityWithKey(t *testing.T) { 599 ctx := context.Background() 600 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 601 if err != nil { 602 t.Fatal(err.Error()) 603 } 604 defer client.Close() 605 defer cleanUp() 606 607 type Inner struct { 608 K *datastore.Key `datastore:"__key__"` 609 A string 610 B string 611 } 612 613 type Data struct { 614 Slice []Inner 615 } 616 617 _, err = client.Put(ctx, datastore.IncompleteKey("Test", nil), &Data{ 618 Slice: []Inner{ 619 {K: datastore.IDKey("TestInner", 1, nil), A: "A1", B: "B1"}, 620 {K: datastore.IDKey("TestInner", 2, nil), A: "A2", B: "B2"}, 621 {K: datastore.IDKey("TestInner", 3, nil), A: "A3", B: "B3"}, 622 }, 623 }) 624 if err != nil { 625 t.Fatal(err) 626 } 627 } 628 629 func TestCloudDatastore_GeoPoint(t *testing.T) { 630 ctx := context.Background() 631 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 632 if err != nil { 633 t.Fatal(err.Error()) 634 } 635 defer client.Close() 636 defer cleanUp() 637 638 type Data struct { 639 A datastore.GeoPoint 640 B *datastore.GeoPoint 641 C []datastore.GeoPoint 642 D []*datastore.GeoPoint 643 } 644 645 // NOTE Cloud Datastore can save *datastore.GeoPoint. 646 // but it is not means that is can handling *datastore.GeoPoint. 647 // *datastore.GeoPoint will convert to *datastore.Entity. 648 obj := &Data{ 649 A: datastore.GeoPoint{Lat: 1.1, Lng: 2.2}, 650 B: &datastore.GeoPoint{Lat: 3.3, Lng: 4.4}, 651 C: []datastore.GeoPoint{ 652 {Lat: 5.5, Lng: 6.6}, 653 {Lat: 7.7, Lng: 8.8}, 654 }, 655 D: []*datastore.GeoPoint{ 656 {Lat: 9.9, Lng: 10.10}, 657 {Lat: 11.11, Lng: 12.12}, 658 }, 659 } 660 661 key, err := client.Put(ctx, datastore.IncompleteKey("Data", nil), obj) 662 if err != nil { 663 t.Fatal(err) 664 } 665 666 obj = &Data{} 667 err = client.Get(ctx, key, obj) 668 if err != nil { 669 t.Fatal(err) 670 } 671 672 if v := obj.A.Lat; v != 1.1 { 673 t.Errorf("unexpected: %v", v) 674 } 675 if v := obj.A.Lng; v != 2.2 { 676 t.Errorf("unexpected: %v", v) 677 } 678 679 if v := obj.B.Lat; v != 3.3 { 680 t.Errorf("unexpected: %v", v) 681 } 682 if v := obj.B.Lng; v != 4.4 { 683 t.Errorf("unexpected: %v", v) 684 } 685 686 if v := len(obj.C); v != 2 { 687 t.Fatalf("unexpected: %v", v) 688 } 689 if v := obj.C[0].Lat; v != 5.5 { 690 t.Errorf("unexpected: %v", v) 691 } 692 if v := obj.C[0].Lng; v != 6.6 { 693 t.Errorf("unexpected: %v", v) 694 } 695 if v := obj.C[1].Lat; v != 7.7 { 696 t.Errorf("unexpected: %v", v) 697 } 698 if v := obj.C[1].Lng; v != 8.8 { 699 t.Errorf("unexpected: %v", v) 700 } 701 702 if v := len(obj.D); v != 2 { 703 t.Fatalf("unexpected: %v", v) 704 } 705 if v := obj.D[0].Lat; v != 9.9 { 706 t.Errorf("unexpected: %v", v) 707 } 708 if v := obj.D[0].Lng; v != 10.10 { 709 t.Errorf("unexpected: %v", v) 710 } 711 if v := obj.D[1].Lat; v != 11.11 { 712 t.Errorf("unexpected: %v", v) 713 } 714 if v := obj.D[1].Lng; v != 12.12 { 715 t.Errorf("unexpected: %v", v) 716 } 717 } 718 719 func TestCloudDatastore_PutInterface(t *testing.T) { 720 ctx := context.Background() 721 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 722 if err != nil { 723 t.Fatal(err.Error()) 724 } 725 defer client.Close() 726 defer cleanUp() 727 728 var e EntityInterface = &PutInterfaceTest{} 729 730 key := datastore.IncompleteKey("Test", nil) 731 _, err = client.Put(ctx, key, e) 732 if err != nil { 733 t.Fatal(err) 734 } 735 } 736 737 func TestCloudDatastore_PutAndGetPropertyList(t *testing.T) { 738 ctx := context.Background() 739 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 740 if err != nil { 741 t.Fatal(err.Error()) 742 } 743 defer client.Close() 744 defer cleanUp() 745 746 var ps datastore.PropertyList 747 ps = append(ps, datastore.Property{ 748 Name: "A", 749 Value: "A-Value", 750 }) 751 ps = append(ps, datastore.Property{ 752 Name: "B", 753 Value: true, 754 }) 755 756 key := datastore.IncompleteKey("Test", nil) 757 // passed datastore.PropertyList, would be error. 758 _, err = client.Put(ctx, key, ps) 759 if err != datastore.ErrInvalidEntityType { 760 t.Fatal(err) 761 } 762 763 // ok! 764 key, err = client.Put(ctx, key, &ps) 765 if err != nil { 766 t.Fatal(err) 767 } 768 769 // passed datastore.PropertyList, would be error. 770 ps = datastore.PropertyList{} 771 err = client.Get(ctx, key, ps) 772 if err != datastore.ErrInvalidEntityType { 773 t.Fatal(err) 774 } 775 776 // ok! 777 ps = datastore.PropertyList{} 778 err = client.Get(ctx, key, &ps) 779 if err != nil { 780 t.Fatal(err) 781 } 782 783 if v := len(ps); v != 2 { 784 t.Fatalf("unexpected: %v", v) 785 } 786 } 787 788 func TestCloudDatastore_PutAndGetMultiPropertyListSlice(t *testing.T) { 789 ctx := context.Background() 790 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 791 if err != nil { 792 t.Fatal(err.Error()) 793 } 794 defer client.Close() 795 defer cleanUp() 796 797 var pss []datastore.PropertyList 798 var keys []*datastore.Key 799 { 800 var ps datastore.PropertyList 801 ps = append(ps, datastore.Property{ 802 Name: "A", 803 Value: "A-Value", 804 }) 805 ps = append(ps, datastore.Property{ 806 Name: "B", 807 Value: true, 808 }) 809 810 key := datastore.IncompleteKey("Test", nil) 811 812 pss = append(pss, ps) 813 keys = append(keys, key) 814 } 815 816 // passed *[]datastore.PropertyList, would be error. 817 _, err = client.PutMulti(ctx, keys, &pss) 818 if err == nil { 819 t.Fatal(err) 820 } 821 822 // ok! []datastore.PropertyList 823 keys, err = client.PutMulti(ctx, keys, pss) 824 if err != nil { 825 t.Fatal(err) 826 } 827 828 // passed *[]datastore.PropertyList, would be error. 829 pss = make([]datastore.PropertyList, len(keys)) 830 err = client.GetMulti(ctx, keys, &pss) 831 if err == nil { 832 t.Fatal(err) 833 } 834 835 // passed []datastore.PropertyList with length 0, would be error. 836 pss = make([]datastore.PropertyList, 0) 837 err = client.GetMulti(ctx, keys, pss) 838 if err == nil { 839 t.Fatal(err) 840 } 841 842 // ok! []datastore.PropertyList with length == len(keys) 843 pss = make([]datastore.PropertyList, len(keys)) 844 err = client.GetMulti(ctx, keys, pss) 845 if err != nil { 846 t.Fatal(err) 847 } 848 849 if v := len(pss); v != 1 { 850 t.Fatalf("unexpected: %v", v) 851 } 852 } 853 854 func TestCloudDatastore_PutAndGetBareStruct(t *testing.T) { 855 ctx := context.Background() 856 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 857 if err != nil { 858 t.Fatal(err.Error()) 859 } 860 defer client.Close() 861 defer cleanUp() 862 863 type Data struct { 864 Name string 865 } 866 867 key := datastore.IncompleteKey("Test", nil) 868 // passed Data, would be error. 869 _, err = client.Put(ctx, key, Data{Name: "A"}) 870 if err != datastore.ErrInvalidEntityType { 871 t.Fatal(err) 872 } 873 874 // ok! *Data 875 key, err = client.Put(ctx, key, &Data{Name: "A"}) 876 if err != nil { 877 t.Fatal(err) 878 } 879 880 // ok! but struct are copied. can't watching Get result. 881 obj := Data{} 882 err = client.Get(ctx, key, obj) 883 if err != datastore.ErrInvalidEntityType { 884 t.Fatal(err) 885 } 886 887 if v := obj.Name; v != "" { 888 t.Errorf("unexpected: '%v'", v) 889 } 890 } 891 892 func TestCloudDatastore_PutAndGetMultiBareStruct(t *testing.T) { 893 ctx := context.Background() 894 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 895 if err != nil { 896 t.Fatal(err.Error()) 897 } 898 defer client.Close() 899 defer cleanUp() 900 901 type Data struct { 902 Name string 903 } 904 905 var list []Data 906 var keys []*datastore.Key 907 { 908 obj := Data{Name: "A"} 909 key := datastore.IncompleteKey("Test", nil) 910 911 list = append(list, obj) 912 keys = append(keys, key) 913 } 914 915 // ok! 916 keys, err = client.PutMulti(ctx, keys, list) 917 if err != nil { 918 t.Fatal(err) 919 } 920 921 // passed []Data with length 0, would be error. 922 list = make([]Data, 0) 923 err = client.GetMulti(ctx, keys, list) 924 if err == nil { 925 t.Fatal(err) 926 } 927 928 // ok! []Data with length == len(keys) 929 list = make([]Data, len(keys)) 930 err = client.GetMulti(ctx, keys, list) 931 if err != nil { 932 t.Fatal(err) 933 } 934 935 if v := len(list); v != 1 { 936 t.Fatalf("unexpected: '%v'", v) 937 } 938 if v := list[0].Name; v != "A" { 939 t.Errorf("unexpected: '%v'", v) 940 } 941 } 942 943 func TestCloudDatastore_PutAndGetStringSynonym(t *testing.T) { 944 ctx := context.Background() 945 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 946 if err != nil { 947 t.Fatal(err.Error()) 948 } 949 defer client.Close() 950 defer cleanUp() 951 952 type Email string 953 954 type Data struct { 955 Email Email 956 } 957 958 key, err := client.Put(ctx, datastore.IncompleteKey("Data", nil), &Data{Email: "test@example.com"}) 959 if err != nil { 960 t.Fatal(err) 961 } 962 963 obj := &Data{} 964 err = client.Get(ctx, key, obj) 965 if err != nil { 966 t.Fatal(err) 967 } 968 969 if v := obj.Email; v != "test@example.com" { 970 t.Errorf("unexpected: '%v'", v) 971 } 972 } 973 974 func TestCloudDatastore_QueryNextByPropertyList(t *testing.T) { 975 ctx := context.Background() 976 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 977 if err != nil { 978 t.Fatal(err.Error()) 979 } 980 defer client.Close() 981 defer cleanUp() 982 983 type Data struct { 984 Name string 985 } 986 987 _, err = client.Put(ctx, datastore.IncompleteKey("Data", nil), &Data{Name: "A"}) 988 if err != nil { 989 t.Fatal(err) 990 } 991 992 q := datastore.NewQuery("Data") 993 994 { // passed datastore.PropertyList, would be error. 995 iter := client.Run(ctx, q) 996 997 var ps datastore.PropertyList 998 _, err = iter.Next(ps) 999 if err == nil { 1000 t.Fatal(err) 1001 } 1002 } 1003 { // ok! *datastore.PropertyList 1004 iter := client.Run(ctx, q) 1005 1006 var ps datastore.PropertyList 1007 _, err = iter.Next(&ps) 1008 if err != nil { 1009 t.Fatal(err) 1010 } 1011 } 1012 } 1013 1014 func TestCloudDatastore_GetAllByPropertyListSlice(t *testing.T) { 1015 ctx := context.Background() 1016 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 1017 if err != nil { 1018 t.Fatal(err.Error()) 1019 } 1020 defer client.Close() 1021 defer cleanUp() 1022 1023 type Data struct { 1024 Name string 1025 } 1026 1027 _, err = client.Put(ctx, datastore.IncompleteKey("Data", nil), &Data{Name: "A"}) 1028 if err != nil { 1029 t.Fatal(err) 1030 } 1031 1032 q := datastore.NewQuery("Data") 1033 var psList []datastore.PropertyList 1034 1035 // passed []datastore.PropertyList, would be error. 1036 _, err = client.GetAll(ctx, q, psList) 1037 if err == nil { 1038 t.Fatal(err) 1039 } 1040 1041 // ok! *[]datastore.PropertyList 1042 psList = nil 1043 _, err = client.GetAll(ctx, q, &psList) 1044 if err != nil { 1045 t.Fatal(err) 1046 } 1047 } 1048 1049 func TestCloudDatastore_PendingKeyWithCompleteKey(t *testing.T) { 1050 ctx := context.Background() 1051 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 1052 if err != nil { 1053 t.Fatal(err.Error()) 1054 } 1055 defer client.Close() 1056 defer cleanUp() 1057 1058 type Data struct { 1059 Name string 1060 } 1061 1062 tx, err := client.NewTransaction(ctx) 1063 if err != nil { 1064 t.Fatal(err) 1065 } 1066 1067 pKey, err := tx.Put(datastore.NameKey("Data", "a", nil), &Data{Name: "Test"}) 1068 if err != nil { 1069 t.Fatal(err) 1070 } 1071 1072 commit, err := tx.Commit() 1073 if err != nil { 1074 t.Fatal(err) 1075 } 1076 1077 // don't panic occurred after https://github.com/GoogleCloudPlatform/google-cloud-go/commit/02a2d936c7c22d0d585fb1e86ac05043bacb3a13 1078 commit.Key(pKey) 1079 } 1080 1081 func TestCloudDatastore_Namespace(t *testing.T) { 1082 ctx := context.Background() 1083 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 1084 if err != nil { 1085 t.Fatal(err.Error()) 1086 } 1087 defer client.Close() 1088 defer cleanUp() 1089 1090 type Data struct { 1091 Name string 1092 } 1093 1094 key := datastore.IDKey("Test", 1, nil) 1095 key.Namespace = "no1" 1096 if v := key.String(); v != "/Test,1" { 1097 t.Fatalf("unexpected: %v", v) 1098 } 1099 1100 _, err = client.Put(ctx, key, &Data{"Name #1"}) 1101 if err != nil { 1102 t.Fatal(err) 1103 } 1104 1105 key.Namespace = "" 1106 err = client.Get(ctx, key, &Data{}) 1107 if err != datastore.ErrNoSuchEntity { 1108 t.Fatal(err) 1109 } 1110 1111 key.Namespace = "no1" 1112 err = client.Get(ctx, key, &Data{}) 1113 if err != nil { 1114 t.Fatal(err) 1115 } 1116 1117 q := datastore.NewQuery("Test") 1118 q = q.KeysOnly() 1119 1120 var keys []*datastore.Key 1121 1122 keys, err = client.GetAll(ctx, q, nil) 1123 if err != nil { 1124 t.Fatal(err) 1125 } 1126 if v := len(keys); v != 0 { 1127 t.Fatalf("unexpected: %v", v) 1128 } 1129 1130 q = q.Namespace("no1") 1131 keys, err = client.GetAll(ctx, q, nil) 1132 if err != nil { 1133 t.Fatal(err) 1134 } 1135 if v := len(keys); v != 1 { 1136 t.Fatalf("unexpected: %v", v) 1137 } 1138 } 1139 1140 func TestCloudDatastore_RollbackAfterCommit(t *testing.T) { 1141 ctx := context.Background() 1142 client, err := datastore.NewClient(ctx, internal.GetProjectID()) 1143 if err != nil { 1144 t.Fatal(err) 1145 } 1146 defer client.Close() 1147 defer cleanUp() 1148 1149 tx, err := client.NewTransaction(ctx) 1150 if err != nil { 1151 t.Fatal(err) 1152 } 1153 1154 _, err = tx.Commit() 1155 if err != nil { 1156 t.Fatal(err) 1157 } 1158 1159 err = tx.Rollback() 1160 if err == nil || err.Error() != "datastore: transaction expired" { 1161 t.Fatal(err) 1162 } 1163 1164 _, err = tx.Commit() 1165 if err == nil || err.Error() != "datastore: transaction expired" { 1166 t.Fatal(err) 1167 } 1168 }