Skip to content

Commit

Permalink
Update beginTransaction and allocateIds rpc + unit + snippet tests
Browse files Browse the repository at this point in the history
  • Loading branch information
yash30201 committed Mar 28, 2024
1 parent be2533c commit 2eab49d
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 176 deletions.
68 changes: 68 additions & 0 deletions Core/src/Testing/DatastoreOperationRefreshTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
use Google\Cloud\Datastore\Connection\ConnectionInterface;
use Google\Cloud\Datastore\EntityMapper;
use Google\Cloud\Datastore\Operation;
use Google\Cloud\Datastore\V1\Client\DatastoreClient;
use Prophecy\Argument;

/**
* Refresh Datastore operation class
Expand Down Expand Up @@ -88,4 +90,70 @@ public function refreshOperation($stub, ConnectionInterface $connection, Request

return $stub;
}

/**
* Helper method for Unit and Snippet test classes. This mocks the
* $requestHandler class property present in the Test Class with
* given arguments.
*
* @param string $methodName The method name to mock in RequestHandler::sendRequest
* @param array<string, mixed> $params The parameters to look for in the
* array equivalent of rpc request.
* @param mixed $returnValue The value to be returned by sendRequest mock.
* @param null|int $shouldBeCalledTimes Adds a shouldBeCalled prophecy. Defaults to `null`, implying nothing is added.
* [
* `0` => `shouldBeCalled`,
* Non zero positive integer $x => `shouldBeCalledTimes($x)`
* ]
*/
private function mockSendRequest($methodName, $params, $returnValue, $shouldBeCalledTimes = null)
{
if (isset($this->serializer)) {
$serializer = $this->serializer;
} else {
$serializer = new Serializer([], [
'google.protobuf.Value' => function ($v) {
return $this->flattenValue($v);
},
'google.protobuf.Timestamp' => function ($v) {
return $this->formatTimestampFromApi($v);
}
], [], [
'google.protobuf.Timestamp' => function ($v) {
if (is_string($v)) {
$dt = new \DateTime($v);
return ['seconds' => $dt->format('U')];
}
return $v;
}
]);
}

$prophecy = $this->requestHandler->sendRequest(
DatastoreClient::class,
$methodName,
Argument::that(function ($arg) use ($methodName, $params, $serializer) {
$requestName = ucfirst($methodName . 'Request');
$x = explode('\\', get_class($arg));
$argName = end($x);

if ($requestName != $argName) {
return false;
}
$data = $serializer->encodeMessage($arg);
return array_merge($params, $data) == $data;
}),
Argument::cetera()
);

if (!is_null($shouldBeCalledTimes)) {
if ($shouldBeCalledTimes == 0) {
$prophecy->shouldBeCalled();
} else {
$prophecy->shouldBeCalledTimes($shouldBeCalledTimes);
}
}

$prophecy->willReturn($returnValue);
}
}
42 changes: 38 additions & 4 deletions Datastore/src/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@
use Google\Cloud\Datastore\Query\AggregationQueryResult;
use Google\Cloud\Datastore\Query\Query;
use Google\Cloud\Datastore\Query\QueryInterface;
use Google\Cloud\Datastore\V1\AllocateIdsRequest;
use Google\Cloud\Datastore\V1\BeginTransactionRequest;
use Google\Cloud\Datastore\V1\Client\DatastoreClient;
use Google\Cloud\Datastore\V1\QueryResultBatch\MoreResultsType;
use Google\Cloud\Datastore\V1\TransactionOptions;

/**
* Run lookups and queries and commit changes.
Expand Down Expand Up @@ -304,11 +308,30 @@ public function beginTransaction($transactionOptions, array $options = [])
$transactionOptions['readOnly']
);
}
$res = $this->connection->beginTransaction($options + [

array_walk($transactionOptions, function (&$item) {
if ($item instanceof \stdClass) {
$item = [];
}
});

list($data, $optionalArgs) = $this->splitOptionalArgs($options);

$data += [
'projectId' => $this->projectId,
'databaseId' => $this->databaseId,
'transactionOptions' => $transactionOptions,
]);
];

$data = $this->convertDataToProtos($data, ['transactionOptions' => TransactionOptions::class]);
$request = $this->serializer->decodeMessage(new BeginTransactionRequest(), $data);

$res = $this->requestHandler->sendRequest(
DatastoreClient::class,
'beginTransaction',
$request,
$optionalArgs
);

return $res['transaction'];
}
Expand Down Expand Up @@ -349,11 +372,22 @@ public function allocateIds(array $keys, array $options = [])
$serviceKeys[] = $key->keyObject();
}

$res = $this->connection->allocateIds($options + [
list($data, $optionalArgs) = $this->splitOptionalArgs($options);

$data += [
'projectId' => $this->projectId,
'databaseId' => $this->databaseId,
'keys' => $serviceKeys,
]);
];

$request = $this->serializer->decodeMessage(new AllocateIdsRequest(), $data);

$res = $this->requestHandler->sendRequest(
DatastoreClient::class,
'allocateIds',
$request,
$optionalArgs
);

if (isset($res['keys'])) {
foreach ($res['keys'] as $index => $key) {
Expand Down
62 changes: 34 additions & 28 deletions Datastore/tests/Snippet/DatastoreClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace Google\Cloud\Datastore\Tests\Snippet;

use Google\Cloud\Core\ApiHelperTrait;
use Google\Cloud\Core\Int64;
use Google\Cloud\Core\RequestHandler;
use Google\Cloud\Core\Testing\DatastoreOperationRefreshTrait;
Expand All @@ -36,6 +37,7 @@
use Google\Cloud\Datastore\Query\QueryInterface;
use Google\Cloud\Datastore\ReadOnlyTransaction;
use Google\Cloud\Datastore\Transaction;
use Google\Cloud\Datastore\V1\Client\DatastoreClient as DatastoreGapicClient;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;

Expand All @@ -44,6 +46,7 @@
*/
class DatastoreClientTest extends SnippetTestCase
{
use ApiHelperTrait;
use DatastoreOperationRefreshTrait;
use ProphecyTrait;

Expand All @@ -58,6 +61,7 @@ class DatastoreClientTest extends SnippetTestCase
public function setUp(): void
{
$this->connection = $this->prophesize(ConnectionInterface::class);

$this->client = TestHelpers::stub(DatastoreClient::class, [], ['operation']);

$this->key = new Key('my-awesome-project', [
Expand Down Expand Up @@ -351,11 +355,11 @@ public function testTransaction()
$snippet = $this->snippetFromMethod(DatastoreClient::class, 'transaction');
$snippet->addLocal('datastore', $this->client);

$this->connection->beginTransaction($this->validateTransactionOptions('readWrite'))
->shouldBeCalled()
->willReturn([
'transaction' => 'foo'
]);
$this->mockSendRequest(
'beginTransaction',
['transactionOptions' => ['readWrite' => []]],
['transaction' => 'foo']
);

$this->refreshOperation($this->client, $this->connection->reveal(), $this->requestHandler->reveal(), [
'projectId' => self::PROJECT
Expand All @@ -369,11 +373,11 @@ public function testReadOnlyTransaction()
{
$snippet = $this->snippetFromMethod(DatastoreClient::class, 'readOnlyTransaction');
$snippet->addLocal('datastore', $this->client);
$this->connection->beginTransaction($this->validateTransactionOptions('readOnly'))
->shouldBeCalled()
->willReturn([
'transaction' => 'foo'
]);
$this->mockSendRequest(
'beginTransaction',
['transactionOptions' => ['readOnly' => []]],
['transaction' => 'foo']
);
$this->refreshOperation($this->client, $this->connection->reveal(), $this->requestHandler->reveal(), [
'projectId' => self::PROJECT
]);
Expand Down Expand Up @@ -770,28 +774,30 @@ public function testRunAggregationQuery()

private function allocateIdsConnectionMock()
{
$this->connection->allocateIds(Argument::any())
->shouldBeCalled()
->willReturn([
'keys' => [
[
'path' => [
[
'kind' => 'Person',
'id' => '4682475895'
]
$this->requestHandler->sendRequest(
DatastoreGapicClient::class,
'allocateIds',
Argument::cetera()
)->shouldBeCalled()->willReturn([
'keys' => [
[
'path' => [
[
'kind' => 'Person',
'id' => '4682475895'
]
],
[
'path' => [
[
'kind' => 'Person',
'id' => '4682475896'
]
]
],
[
'path' => [
[
'kind' => 'Person',
'id' => '4682475896'
]
]
]
]);
]
]);
}

private function validateTransactionOptions($type, array $options = [])
Expand Down
33 changes: 19 additions & 14 deletions Datastore/tests/Snippet/DatastoreSessionHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace Google\Cloud\Datastore\Tests\Snippet;

use Google\Cloud\Core\ApiHelperTrait;
use Google\Cloud\Core\RequestHandler;
use Google\Cloud\Core\Testing\DatastoreOperationRefreshTrait;
use Google\Cloud\Core\Testing\Snippet\SnippetTestCase;
Expand All @@ -36,8 +37,10 @@ class DatastoreSessionHandlerTest extends SnippetTestCase
{
use DatastoreOperationRefreshTrait;
use ProphecyTrait;
use ApiHelperTrait;

const TRANSACTION = 'transaction-id';
const PROJECT = 'example-project';

private $connection;
private $client;
Expand Down Expand Up @@ -78,12 +81,11 @@ public function testClass()
})
))->shouldBeCalled()->willReturn([]);

$this->connection->beginTransaction(Argument::withEntry(
'transactionOptions',
['readWrite' => (object) []]
))->shouldBeCalled()->willReturn([
'transaction' => self::TRANSACTION,
]);
$this->mockSendRequest(
'beginTransaction',
['transactionOptions' => ['readWrite' => []]],
['transaction' => self::TRANSACTION]
);

$this->connection->commit(Argument::allOf(
Argument::withEntry('transaction', self::TRANSACTION),
Expand All @@ -99,7 +101,9 @@ public function testClass()
})
))->shouldBeCalled()->willReturn([]);

$this->refreshOperation($this->client, $this->connection->reveal(), $this->requestHandler->reveal());
$this->refreshOperation($this->client, $this->connection->reveal(), $this->requestHandler->reveal(), [
'projectId' => self::PROJECT
]);
$snippet->addLocal('datastore', $this->client);

$res = $snippet->invoke();
Expand All @@ -124,20 +128,21 @@ public function testClassErrorHandler()
})
))->shouldBeCalled()->willReturn([]);

$this->connection->beginTransaction(Argument::withEntry(
'transactionOptions',
['readWrite' => (object) []]
))->shouldBeCalled()->willReturn([
'transaction' => self::TRANSACTION,
]);
$this->mockSendRequest(
'beginTransaction',
['transactionOptions' => ['readWrite' => []]],
['transaction' => self::TRANSACTION]
);

$this->connection->commit(Argument::any())
->shouldBeCalled()
->will(function () {
trigger_error('oops!', E_USER_WARNING);
});

$this->refreshOperation($this->client, $this->connection->reveal(), $this->requestHandler->reveal());
$this->refreshOperation($this->client, $this->connection->reveal(), $this->requestHandler->reveal(), [
'projectId' => self::PROJECT
]);
$snippet->addLocal('datastore', $this->client);

$res = $snippet->invoke();
Expand Down
22 changes: 12 additions & 10 deletions Datastore/tests/Snippet/ReadOnlyTransactionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,12 @@ public function setUp(): void

public function testClass()
{
$this->connection->beginTransaction(Argument::any())
->shouldBeCalled()
->willReturn([
'transaction' => 'foo'
]);
$this->mockSendRequest(
'beginTransaction',
[],
['transaction' => 'foo'],
0
);

$this->refreshOperation($this->client, $this->connection->reveal(), $this->requestHandler->reveal(), [
'projectId' => self::PROJECT
Expand All @@ -124,11 +125,12 @@ public function testClass()

public function testClassRollback()
{
$this->connection->beginTransaction(Argument::any())
->shouldBeCalled()
->willReturn([
'transaction' => 'foo'
]);
$this->mockSendRequest(
'beginTransaction',
[],
['transaction' => 'foo'],
0
);
$this->connection->lookup(Argument::any())
->shouldBeCalled()
->willReturn([]);
Expand Down
Loading

0 comments on commit 2eab49d

Please sign in to comment.