diff --git a/Firestore/tests/System/AggregateQueryTest.php b/Firestore/tests/System/AggregateQueryTest.php index fb61b9418f01..adc0d53ed305 100644 --- a/Firestore/tests/System/AggregateQueryTest.php +++ b/Firestore/tests/System/AggregateQueryTest.php @@ -35,162 +35,92 @@ public function setUp(): void self::$localDeletionQueue->add($this->query); } - public function testSelect() + /** + * @dataProvider getSelectCases + */ + public function testSelect($type, $arg, $fieldMask, $expected, $docsToAdd = []) { - $this->insertDoc([ - 'foo' => 'bar', - 'hello' => 'world', - 'good' => 'night' - ]); - - $query = $this->query->select(['foo', 'good']); - - $this->assertQueryCount($query, 1); + $this->insertDocs($docsToAdd); + $query = $this->query->select($fieldMask); + $this->assertQuery($query, $type, $arg, $expected); } - public function testSelectEmpty() + /** + * @dataProvider getWhereCases + */ + public function testWhere($type, $arg, $op, $fieldValue, $expected, $docsToAdd = []) { - $this->insertDoc([ - 'foo' => 'bar' - ]); - - $query = $this->query->select([]); - - $this->assertQueryCount($query, 1); + $this->insertDocs($docsToAdd); + $query = $this->query->where('value', $op, $fieldValue); + $this->assertQuery($query, $type, $arg, $expected); } - public function testWhere() + /** + * @dataProvider getSnapshotCursorCases + */ + public function testSnapshotCursors($type, $arg, $expectedResults, $docsToAdd = []) { - $randomVal = base64_encode(random_bytes(10)); - $this->insertDoc([ - 'foo' => $randomVal - ]); - - $query = $this->query->where('foo', '=', $randomVal); - $this->assertQueryCount($query, 1); - } + $refs = $this->insertDocs($docsToAdd); - public function testWhereNull() - { - $this->insertDoc([ - 'foo' => null - ]); + $query = $this->query->orderBy('value')->startAt($refs[0]->snapshot()); + $this->assertQuery($query, $type, $arg, $expectedResults[0]); - $query = $this->query->where('foo', '=', null); - $this->assertQueryCount($query, 1); - } + $query = $this->query->orderBy('value')->startAfter($refs[0]->snapshot()); + $this->assertQuery($query, $type, $arg, $expectedResults[1]); - public function testWhereNan() - { - $this->insertDoc([ - 'foo' => NAN - ]); + $query = $this->query->orderBy('value')->endBefore(end($refs)->snapshot()); + $this->assertQuery($query, $type, $arg, $expectedResults[2]); - $query = $this->query->where('foo', '=', NAN); - $this->assertQueryCount($query, 1); + $query = $this->query->orderBy('value')->endAt(end($refs)->snapshot()); + $this->assertQuery($query, $type, $arg, $expectedResults[3]); } - public function testWhereInArray() + /** + * @dataProvider getLimitCases + */ + public function testLimits($type, $arg, $expectedResults, $docsToAdd = []) { - $name = $this->query->name(); - $this->insertDoc([ - 'foos' => ['foo', 'bar'], - ]); - $this->insertDoc([ - 'foos' => ['foo'], - ]); - - $docs = self::$client->collection($name)->where('foos', 'in', [['foo']]); - $this->assertQueryCount($docs, 1); - $docs = self::$client->collection($name)->where('foos', 'in', [['bar']]); - $this->assertQueryCount($docs, 0); - $docs = self::$client->collection($name)->where('foos', 'in', [['foo', 'bar']]); - $this->assertQueryCount($docs, 1); - $docs = self::$client->collection($name)->where('foos', 'in', [['bar', 'foo']]); - $this->assertQueryCount($docs, 0); - } + $refs = $this->insertDocs($docsToAdd); - public function testSnapshotCursors() - { - $collection = self::$client->collection(uniqid(self::COLLECTION_NAME)); - self::$localDeletionQueue->add($collection); - - $refs = []; - for ($i = 0; $i <= 3; $i++) { - $doc = $collection->document($i); - $doc->create(['i' => $i]); - $refs[] = $doc; - } - - $q = $collection->startAt($refs[0]->snapshot()); - $this->assertQueryCount($q, count($refs)); - - $q = $collection->startAfter($refs[0]->snapshot()); - $this->assertQueryCount($q, count($refs)-1); - - $q = $collection->endBefore(end($refs)->snapshot()); - $this->assertQueryCount($q, count($refs)-1); - - $q = $collection->endAt(end($refs)->snapshot()); - $this->assertQueryCount($q, count($refs)); - } + $query = $this->query->orderBy('value') + ->limitToLast(2); + $this->assertQuery($query, $type, $arg, $expectedResults[0]); - public function testLimitToLast() - { - $collection = self::$client->collection(uniqid(self::COLLECTION_NAME)); - self::$localDeletionQueue->add($collection); - for ($i = 1; $i <= 5; $i++) { - $collection->add(['i' => $i]); - } - $q = $collection->orderBy('i') + $query = $this->query->orderBy('value') + ->startAt($refs[1]->snapshot()) + ->endAt($refs[3]->snapshot()) ->limitToLast(2); - - $this->assertQueryCount($q, 2); + $this->assertQuery($query, $type, $arg, $expectedResults[1]); } - public function testLimitToLastWithCursors() + private function insertDocs(array $docs) { - $collection = self::$client->collection(uniqid(self::COLLECTION_NAME)); - self::$localDeletionQueue->add($collection); - for ($i = 1; $i <= 5; $i++) { - $collection->add(['i' => $i]); + $docsRefs = []; + foreach ($docs as $doc) { + $docsRefs[] = $this->query->add($doc); } - - $q = $collection->orderBy('i') - ->startAt([2]) - ->endAt([4]) - ->limitToLast(5); - - $this->assertQueryCount($q, 3); + return $docsRefs; } - private function insertDoc(array $fields) + private function assertQuery(Query $query, $type, $arg, $expected) { - return $this->query->add($fields); + $actual = $arg ? $query->$type($arg) : $query->$type(); + $this->assertEquals($expected, $actual); + $this->assertQueryWithMultipleAggregations($query, $type, $arg, $expected); } - private function assertQueryCount(Query $query, $expectedCount) + private function assertQueryWithMultipleAggregations(Query $query, $type, $arg, $expected) { - $actualCount = $query->count(); - $this->assertEquals($expectedCount, $actualCount); - - $this->assertQueryCountWithMultipleAggregations($query, $expectedCount); - } - - private function assertQueryCountWithMultipleAggregations( - Query $query, - $expectedCount - ) { $aggregations = [ - Aggregate::count()->alias('count'), - Aggregate::count()->alias('count_with_alias_a'), - Aggregate::count()->alias('count_with_alias_b'), + ($arg ? Aggregate::$type($arg) : Aggregate::$type())->alias('a1'), + ($arg ? Aggregate::$type($arg) : Aggregate::$type())->alias('a2'), + ($arg ? Aggregate::$type($arg) : Aggregate::$type())->alias('a3') ]; - $expectedCounts = [ - 'count' => $expectedCount, - 'count_with_alias_a' => $expectedCount, - 'count_with_alias_b' => $expectedCount, + $expectedResults = [ + 'a1' => $expected, + 'a2' => $expected, + 'a3' => $expected, ]; foreach ($aggregations as $aggregation) { $query = $query->addAggregation($aggregation); @@ -199,10 +129,10 @@ private function assertQueryCountWithMultipleAggregations( $snapshot = $query->getSnapshot(); - foreach ($expectedCounts as $k => $v) { - $expectedCount = $v; - $actualCount = $snapshot->get($k); - $this->assertEquals($expectedCount, $actualCount); + foreach ($expectedResults as $k => $v) { + $expectedResult = $v; + $actualResult = $snapshot->get($k); + $this->assertEquals($expectedResult, $actualResult); } $this->assertEquals(0, strlen($snapshot->getTransaction())); @@ -211,7 +141,108 @@ private function assertQueryCountWithMultipleAggregations( $this->assertEqualsWithDelta( $expectedTimestamp->get()->getTimestamp(), $actualTimestamp->get()->getTimestamp(), - 10 + 100 ); } + + public function getSelectCases() + { + // This dataProvider returns the test cases to test + // how aggregations work with `select()` field mask. + // + // The values are of the form + // [ + // $aggregationType, + // $arg, + // $fieldMask, + // $expectedResult, + // $docsToAddBeforeTestRunning + // ] + // + + return [ + ['count', null, ['foo', 'good'], 1, [['foo' => 'bar', 'hello' => 'world', 'good' => 'night']]], + ['count', null, [], 1, [['foo' => 'bar']]], + ]; + } + + public function getWhereCases() + { + // This dataProvider returns the test cases to test + // how aggregations work with `where()` (i.e. field filter). + // + // The values are of the form + // [ + // $aggregationType, + // $arg, + // $operation, + // $fieldValue, + // $expectedResult, + // $docsToAddBeforeTestRunning + // ] + // + + $arrayDoc = [ + ['value' => ['foo', 'bar']], + ['value' => ['foo']] + ]; + $randomVal = base64_encode(random_bytes(10)); + return [ + // For testing where: equality for random value + ['count', null, '=', $randomVal, 1, [['value' => $randomVal]]], + + // For testing where: equality for null + ['count', null, '=', null, 1, [['value' => null]]], + + // For testing where: equality for NAN + ['count', null, '=', NAN, 1, [['value' => NAN]]], + + // For testing where: in array + ['count', null, 'in', [['foo']], 1, $arrayDoc], + ['count', null, 'in', [['foo'], ['foo', 'bar']], 2, $arrayDoc], + ['count', null, 'in', [['bar']], 0, $arrayDoc], + ['count', null, 'in', [['foo', 'bar']], 1, $arrayDoc], + ['count', null, 'in', [['bar', 'foo']], 0, $arrayDoc], + ]; + } + + public function getSnapshotCursorCases() + { + // This dataProvider returns the test cases to test + // how aggregations work with `cursors`. + // + // The values are of the form + // [ + // $aggregationType, + // $arg, + // $expectedResults, + // $docsToAddBeforeTestRunning + // ] + // + + $docsToAdd = [['value' => 0], ['value' => 1], ['value' => 2], ['value' => 3]]; + return [ + ['count', null, [4, 3, 3, 4], $docsToAdd] + ]; + } + + public function getLimitCases() + { + // This dataProvider returns the test cases to test + // how aggregations work with `limits`. + // + // The values are of the form + // [ + // $aggregationType, + // $arg, + // $expectedResults, + // $docsToAddBeforeTestRunning + // ] + // + + $docsToAdd = [['value' => 0], ['value' => 1], ['value' => 2], ['value' => 3], ['value' => 4]]; + return [ + ['count', null, [2, 2], $docsToAdd] + ]; + } } diff --git a/Firestore/tests/System/FirestoreTestCase.php b/Firestore/tests/System/FirestoreTestCase.php index 770ea2e8bbb5..276f556f7f2a 100644 --- a/Firestore/tests/System/FirestoreTestCase.php +++ b/Firestore/tests/System/FirestoreTestCase.php @@ -20,6 +20,9 @@ use Google\Cloud\Core\ExponentialBackoff; use Google\Cloud\Core\Testing\System\DeletionQueue; use Google\Cloud\Core\Testing\System\SystemTestCase; +use Google\Cloud\Firestore\CollectionReference; +use Google\Cloud\Firestore\DocumentReference; +use Google\Cloud\Firestore\DocumentSnapshot; use Google\Cloud\Firestore\FirestoreClient; class FirestoreTestCase extends SystemTestCase