Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(91)

Side by Side Diff: test/db/e2e/db_test_impl.dart

Issue 1520863002: Implement support for converting db values to datastore values with db.Query.filter (Closed) Base URL: git@github.com:dart-lang/gcloud.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pubspec.yaml ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library db_test; 5 library db_test;
6 6
7 /// NOTE: In order to run these tests, the following datastore indices must 7 /// NOTE: In order to run these tests, the following datastore indices must
8 /// exist: 8 /// exist:
9 /// $ cat index.yaml 9 /// $ cat index.yaml
10 /// indexes: 10 /// indexes:
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 import '../../common_e2e.dart'; 54 import '../../common_e2e.dart';
55 55
56 @db.Kind() 56 @db.Kind()
57 class Person extends db.Model { 57 class Person extends db.Model {
58 @db.StringProperty() 58 @db.StringProperty()
59 String name; 59 String name;
60 60
61 @db.IntProperty() 61 @db.IntProperty()
62 int age; 62 int age;
63 63
64 @db.ModelKeyProperty() 64 @db.ModelKeyProperty(propertyName: 'mangledWife')
65 db.Key wife; 65 db.Key wife;
66 66
67 operator==(Object other) => sameAs(other); 67 operator==(Object other) => sameAs(other);
68 68
69 sameAs(Object other) { 69 sameAs(Object other) {
70 return other is Person && 70 return other is Person &&
71 id == other.id && 71 id == other.id &&
72 parentKey == other.parentKey && 72 parentKey == other.parentKey &&
73 name == other.name && 73 name == other.name &&
74 age == other.age && 74 age == other.age &&
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 return false; 131 return false;
132 } 132 }
133 } 133 }
134 return true; 134 return true;
135 } 135 }
136 return false; 136 return false;
137 } 137 }
138 } 138 }
139 139
140 140
141 Future sleep(Duration duration) { 141 Future sleep(Duration duration) => new Future.delayed(duration);
142 var completer = new Completer();
143 new Timer(duration, completer.complete);
144 return completer.future;
145 }
146 142
147 runTests(db.DatastoreDB store, String namespace) { 143 runTests(db.DatastoreDB store, String namespace) {
148 var partition = store.newPartition(namespace); 144 var partition = store.newPartition(namespace);
149 145
150 void compareModels(List<db.Model> expectedModels, 146 void compareModels(List<db.Model> expectedModels,
151 List<db.Model> models, 147 List<db.Model> models,
152 {bool anyOrder: false}) { 148 {bool anyOrder: false}) {
153 expect(models.length, equals(expectedModels.length)); 149 expect(models.length, equals(expectedModels.length));
154 if (anyOrder) { 150 if (anyOrder) {
155 // Do expensive O(n^2) search. 151 // Do expensive O(n^2) search.
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 for (var i = 1; i <= 10; i++) { 384 for (var i = 1; i <= 10; i++) {
389 var languages = []; 385 var languages = [];
390 if (i == 9) { 386 if (i == 9) {
391 languages = ['foo']; 387 languages = ['foo'];
392 } else if (i == 10) { 388 } else if (i == 10) {
393 languages = ['foo', 'bar']; 389 languages = ['foo', 'bar'];
394 } 390 }
395 users.add(new User() 391 users.add(new User()
396 ..id = i 392 ..id = i
397 ..parentKey = root 393 ..parentKey = root
394 ..wife = root.append(User, id: 42 + i)
398 ..age = 42 + i 395 ..age = 42 + i
399 ..name = 'user$i' 396 ..name = 'user$i'
400 ..nickname = 'nickname${i%3}' 397 ..nickname = 'nickname${i%3}'
401 ..languages = languages); 398 ..languages = languages);
402 } 399 }
403 400
404 var expandoPersons = []; 401 var expandoPersons = [];
405 for (var i = 1; i <= 3; i++) { 402 for (var i = 1; i <= 3; i++) {
406 var expandoPerson = new ExpandoPerson() 403 var expandoPerson = new ExpandoPerson()
407 ..parentKey = root 404 ..parentKey = root
(...skipping 30 matching lines...) Expand all
438 435
439 var usersSortedAndFilteredNameDescNicknameDesc = 436 var usersSortedAndFilteredNameDescNicknameDesc =
440 usersSortedNameDescNicknameDesc.where((User u) { 437 usersSortedNameDescNicknameDesc.where((User u) {
441 return LOWER_BOUND.compareTo(u.name) <= 0; 438 return LOWER_BOUND.compareTo(u.name) <= 0;
442 }).toList(); 439 }).toList();
443 440
444 var fooUsers = users.where( 441 var fooUsers = users.where(
445 (User u) => u.languages.contains('foo')).toList(); 442 (User u) => u.languages.contains('foo')).toList();
446 var barUsers = users.where( 443 var barUsers = users.where(
447 (User u) => u.languages.contains('bar')).toList(); 444 (User u) => u.languages.contains('bar')).toList();
445 var usersWithWife = users.where(
446 (User u) => u.wife == root.append(User, id: 42 + 3));
448 447
449 var allInserts = [] 448 var allInserts = []
450 ..addAll(users) 449 ..addAll(users)
451 ..addAll(expandoPersons); 450 ..addAll(expandoPersons);
452 var allKeys = allInserts.map((db.Model model) => model.key).toList(); 451 var allKeys = allInserts.map((db.Model model) => model.key).toList();
453 return store.commit(inserts: allInserts).then((_) { 452 return store.commit(inserts: allInserts).then((_) {
454 return waitUntilEntitiesReady(store, allKeys, partition).then((_) { 453 return waitUntilEntitiesReady(store, allKeys, partition).then((_) {
455 var tests = [ 454 var tests = [
456 // Queries for [Person] return no results, we only have [User] 455 // Queries for [Person] return no results, we only have [User]
457 // objects. 456 // objects.
458 () { 457 () {
459 return store.query(Person, partition: partition).run().toList() 458 return store.query(Person, partition: partition).run().toList()
460 .then((List<db.Model> models) { 459 .then((List<db.Model> models) {
461 compareModels([], models); 460 compareModels([], models);
462 }); 461 });
463 }, 462 },
464 463
465 // All users query 464 // All users query
466 () { 465 () {
467 return store.query(User, partition: partition).run().toList() 466 return store.query(User, partition: partition).run().toList()
468 .then((List<db.Model> models) { 467 .then((List<db.Model> models) {
469 compareModels(users, models, anyOrder: true); 468 compareModels(users, models, anyOrder: true);
470 }); 469 });
471 }, 470 },
472 471
473 // Sorted query 472 // Sorted query
474 () { 473 () async {
475 return store.query(User, partition: partition) 474 var query = store.query(User, partition: partition)
476 ..order('-name') 475 ..order('-name')
477 ..order('nickname') 476 ..order('nickname');
478 ..run().toList().then((List<db.Model> models) { 477 var models = await runQueryWithExponentialBackoff(
479 compareModels( 478 query, usersSortedNameDescNicknameAsc.length);
kustermann 2015/12/11 11:08:44 There is still some flakiness on the buildbot. I d
480 usersSortedNameDescNicknameAsc, models); 479 compareModels(
481 }); 480 usersSortedNameDescNicknameAsc, models);
482 }, 481 },
483 () { 482 () async {
484 return store.query(User, partition: partition) 483 var query = store.query(User, partition: partition)
485 ..order('-name') 484 ..order('-name')
486 ..order('-nickname') 485 ..order('-nickname')
487 ..run().toList().then((List<db.Model> models) { 486 ..run();
488 compareModels( 487 var models = await runQueryWithExponentialBackoff(
489 usersSortedNameDescNicknameDesc, models); 488 query, usersSortedNameDescNicknameDesc.length);
490 }); 489 compareModels(
490 usersSortedNameDescNicknameDesc, models);
491 }, 491 },
492 492
493 // Sorted query with filter 493 // Sorted query with filter
494 () { 494 () async {
495 return store.query(User, partition: partition) 495 var query = store.query(User, partition: partition)
496 ..filter('name >=', LOWER_BOUND) 496 ..filter('name >=', LOWER_BOUND)
497 ..order('-name') 497 ..order('-name')
498 ..order('nickname') 498 ..order('nickname');
499 ..run().toList().then((List<db.Model> models) { 499 var models = await runQueryWithExponentialBackoff(
500 compareModels(usersSortedAndFilteredNameDescNicknameAsc, 500 query, usersSortedAndFilteredNameDescNicknameAsc.length);
501 models); 501 compareModels(usersSortedAndFilteredNameDescNicknameAsc,
502 }); 502 models);
503 }, 503 },
504 () { 504 () async {
505 return store.query(User, partition: partition) 505 var query = store.query(User, partition: partition)
506 ..filter('name >=', LOWER_BOUND) 506 ..filter('name >=', LOWER_BOUND)
507 ..order('-name') 507 ..order('-name')
508 ..order('-nickname') 508 ..order('-nickname')
509 ..run().toList().then((List<db.Model> models) { 509 ..run();
510 compareModels(usersSortedAndFilteredNameDescNicknameDesc, 510 var models = await runQueryWithExponentialBackoff(
511 models); 511 query, usersSortedAndFilteredNameDescNicknameDesc.length);
512 }); 512 compareModels(usersSortedAndFilteredNameDescNicknameDesc,
513 models);
513 }, 514 },
514 515
515 // Filter lists 516 // Filter lists
516 /* FIXME: TODO: FIXME: "IN" not supported in public proto/apiary */ 517 /* FIXME: TODO: FIXME: "IN" not supported in public proto/apiary */
517 () { 518 () async {
518 return store.query(User, partition: partition) 519 var query = store.query(User, partition: partition)
519 ..filter('languages IN', ['foo']) 520 ..filter('languages IN', ['foo'])
520 ..order('name') 521 ..order('name')
521 ..run().toList().then((List<db.Model> models) { 522 ..run();
522 compareModels(fooUsers, models, anyOrder: true); 523 var models = await runQueryWithExponentialBackoff(query, fooUsers. length);
Søren Gjesse 2015/12/14 07:53:24 Long line - and a few more below.
kustermann 2015/12/14 09:41:16 Done.
523 }); 524 compareModels(fooUsers, models, anyOrder: true);
524 }, 525 },
525 () { 526 () async {
526 return store.query(User, partition: partition) 527 var query = store.query(User, partition: partition)
527 ..filter('languages IN', ['bar']) 528 ..filter('languages IN', ['bar'])
528 ..order('name') 529 ..order('name')
529 ..run().toList().then((List<db.Model> models) { 530 ..run();
530 compareModels(barUsers, models, anyOrder: true); 531 var models = await runQueryWithExponentialBackoff(query, barUsers. length);
531 }); 532 compareModels(barUsers, models, anyOrder: true);
533 },
534
535 // Filter equals
536 () async {
537 var wifeKey = root.append(User, id: usersWithWife.first.wife.id);
538 var query = store.query(User, partition: partition)
539 ..filter('wife =', wifeKey)
540 ..run();
541 var models = await runQueryWithExponentialBackoff(query, usersWith Wife.length);
542 compareModels(usersWithWife, models, anyOrder: true);
532 }, 543 },
533 544
534 // Simple limit/offset test. 545 // Simple limit/offset test.
535 () { 546 () async {
536 return store.query(User, partition: partition) 547 var query = store.query(User, partition: partition)
537 ..order('-name') 548 ..order('-name')
538 ..order('nickname') 549 ..order('nickname')
539 ..offset(3) 550 ..offset(3)
540 ..limit(4) 551 ..limit(4);
541 ..run().toList().then((List<db.Model> models) { 552 var expectedModels =
542 var expectedModels = 553 usersSortedAndFilteredNameDescNicknameAsc.sublist(3, 7);
543 usersSortedAndFilteredNameDescNicknameAsc.sublist(3, 7); 554 var models = await runQueryWithExponentialBackoff(
544 compareModels(expectedModels, models); 555 query, expectedModels.length);
545 }); 556 compareModels(expectedModels, models);
546 }, 557 },
547 558
548 // Expando queries: Filter on normal property. 559 // Expando queries: Filter on normal property.
549 () { 560 () async {
550 return store.query(ExpandoPerson, partition: partition) 561 var query = store.query(ExpandoPerson, partition: partition)
551 ..filter('name =', expandoPersons.last.name) 562 ..filter('name =', expandoPersons.last.name)
552 ..run().toList().then((List<db.Model> models) { 563 ..run();
553 compareModels([expandoPersons.last], models); 564 var models = await runQueryWithExponentialBackoff(query, 1);
554 }); 565 compareModels([expandoPersons.last], models);
555 }, 566 },
556 // Expando queries: Filter on expanded String property 567 // Expando queries: Filter on expanded String property
557 () { 568 () async {
558 return store.query(ExpandoPerson, partition: partition) 569 var query = store.query(ExpandoPerson, partition: partition)
559 ..filter('foo =', expandoPersons.last.foo) 570 ..filter('foo =', expandoPersons.last.foo)
560 ..run().toList().then((List<db.Model> models) { 571 ..run();
561 compareModels([expandoPersons.last], models); 572 var models = await runQueryWithExponentialBackoff(query, 1);
562 }); 573 compareModels([expandoPersons.last], models);
563 }, 574 },
564 // Expando queries: Filter on expanded int property 575 // Expando queries: Filter on expanded int property
565 () { 576 () async {
566 return store.query(ExpandoPerson, partition: partition) 577 var query = store.query(ExpandoPerson, partition: partition)
567 ..filter('bar =', expandoPersons.last.bar) 578 ..filter('bar =', expandoPersons.last.bar)
568 ..run().toList().then((List<db.Model> models) { 579 ..run();
569 compareModels([expandoPersons.last], models); 580 var models = await runQueryWithExponentialBackoff(query, 1);
570 }); 581 compareModels([expandoPersons.last], models);
571 }, 582 },
572 // Expando queries: Filter normal property with different 583 // Expando queries: Filter normal property with different
573 // propertyName (datastore name is 'NN'). 584 // propertyName (datastore name is 'NN').
574 () { 585 () async {
575 return store.query(ExpandoPerson, partition: partition) 586 var query = store.query(ExpandoPerson, partition: partition)
576 ..filter('nickname =', expandoPersons.last.nickname) 587 ..filter('nickname =', expandoPersons.last.nickname)
577 ..run().toList().then((List<db.Model> models) { 588 ..run();
578 compareModels([expandoPersons.last], models); 589 var models = await runQueryWithExponentialBackoff(query, 1);
579 }); 590 compareModels([expandoPersons.last], models);
580 }, 591 },
581 592
582 // Delete results 593 // Delete results
583 () => store.commit(deletes: allKeys), 594 () => store.commit(deletes: allKeys),
584 595
585 // Wait until the entity deletes are reflected in the indices. 596 // Wait until the entity deletes are reflected in the indices.
586 () => waitUntilEntitiesGone(store, allKeys, partition), 597 () => waitUntilEntitiesGone(store, allKeys, partition),
587 598
588 // Make sure queries don't return results 599 // Make sure queries don't return results
589 () => store.lookup(allKeys).then((List<db.Model> models) { 600 () => store.lookup(allKeys).then((List<db.Model> models) {
590 expect(models.length, equals(allKeys.length)); 601 expect(models.length, equals(allKeys.length));
591 for (var model in models) { 602 for (var model in models) {
592 expect(model, isNull); 603 expect(model, isNull);
593 } 604 }
594 }), 605 }),
595 ]; 606 ];
596 return Future.forEach(tests, (f) => f()); 607 return Future.forEach(tests, (f) => f());
597 }); 608 });
598 }); 609 });
599 }); 610 });
600 }); 611 });
601 } 612 }
602 613
614 Future<List<db.Model>> runQueryWithExponentialBackoff(
Søren Gjesse 2015/12/14 07:53:24 This looks like a good idea.
615 db.Query query, int expectedResults) async {
616 for (int i = 0; i <= 6; i++) {
617 if (i > 0) {
618 // Wait for 0.1s, 0.2s, ..., 12.8s
619 var duration = new Duration(milliseconds: 100 * (2 << i));
620 print("Running query did return less results than expected."
621 "Using exponential backoff: Sleeping for $duration.");
622 await sleep(duration);
623 }
624
625 List<db.Model> models = await query.run().toList();
626 if (models.length >= expectedResults) {
627 return models;
628 }
629 }
630
631 throw new Exception(
632 "Tried running a query with exponential backoff, giving up now.");
633 }
634
603 Future waitUntilEntitiesReady(db.DatastoreDB mdb, 635 Future waitUntilEntitiesReady(db.DatastoreDB mdb,
604 List<db.Key> keys, 636 List<db.Key> keys,
605 db.Partition partition) { 637 db.Partition partition) {
606 return waitUntilEntitiesHelper(mdb, keys, true, partition); 638 return waitUntilEntitiesHelper(mdb, keys, true, partition);
607 } 639 }
608 640
609 Future waitUntilEntitiesGone(db.DatastoreDB mdb, 641 Future waitUntilEntitiesGone(db.DatastoreDB mdb,
610 List<db.Key> keys, 642 List<db.Key> keys,
611 db.Partition partition) { 643 db.Partition partition) {
612 return waitUntilEntitiesHelper(mdb, keys, false, partition); 644 return waitUntilEntitiesHelper(mdb, keys, false, partition);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 var scopes = datastore_impl.DatastoreImpl.SCOPES; 680 var scopes = datastore_impl.DatastoreImpl.SCOPES;
649 681
650 withAuthClient(scopes, (String project, httpClient) { 682 withAuthClient(scopes, (String project, httpClient) {
651 var datastore = new datastore_impl.DatastoreImpl(httpClient, 's~$project'); 683 var datastore = new datastore_impl.DatastoreImpl(httpClient, 's~$project');
652 return datastore_test.cleanupDB(datastore, null).then((_) { 684 return datastore_test.cleanupDB(datastore, null).then((_) {
653 return runE2EUnittest( 685 return runE2EUnittest(
654 () => runTests(new db.DatastoreDB(datastore), null)); 686 () => runTests(new db.DatastoreDB(datastore), null));
655 }); 687 });
656 }); 688 });
657 } 689 }
OLDNEW
« no previous file with comments | « pubspec.yaml ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698