Skip to content

Commit 3280b2e

Browse files
committed
test(spanner): consolidate test database provisioning
1 parent 5b36970 commit 3280b2e

8 files changed

Lines changed: 116 additions & 46 deletions

File tree

Spanner/tests/System/BatchTest.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ public static function setUpTestFixtures(): void
5858
))->pollUntilComplete();
5959

6060
if (self::$database->info()['databaseDialect'] == DatabaseDialect::GOOGLE_STANDARD_SQL) {
61-
$statements = [
62-
sprintf('CREATE ROLE %s', self::$dbRole),
63-
sprintf('CREATE ROLE %s', self::$restrictiveDbRole),
64-
];
61+
$statements = [];
6562

6663
if (!self::isEmulatorUsed()) {
6764
$statements[] = sprintf(

Spanner/tests/System/DatabaseRoleTrait.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
*/
2525
trait DatabaseRoleTrait
2626
{
27-
private static $restrictiveDbRole = 'restrictiveReaderRole';
28-
private static $dbRole = 'readerRole';
27+
private static $restrictiveDbRole = 'RestrictiveReader';
28+
private static $dbRole = 'Reader';
2929

3030
abstract public static function setUpBeforeClass();
3131

Spanner/tests/System/OperationsTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,14 @@ public function testRead()
9797
public function testUpdate()
9898
{
9999
$db = self::$database;
100+
$newName = uniqid('Doug');
100101
$row = $this->getRow();
101-
$row['name'] = 'Doug';
102+
$row['name'] = $newName;
102103

103104
$db->update('Users', $row);
104105

105106
$row = $this->getRow();
106-
$this->assertEquals('Doug', $row['name']);
107+
$this->assertEquals($newName, $row['name']);
107108
}
108109

109110
public function testInsertOrUpdate()

Spanner/tests/System/PgSystemTestCaseTrait.php

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,54 +25,64 @@ trait PgSystemTestCaseTrait
2525

2626
protected static function setUpTestDatabase(): void
2727
{
28-
if (self::$hasSetUp) {
28+
if (TestDatabaseManager::$pgHasSetUp) {
29+
self::$client = TestDatabaseManager::$client;
30+
self::$instance = TestDatabaseManager::$instance;
31+
self::$database = TestDatabaseManager::$pgDatabase;
32+
self::$dbName = TestDatabaseManager::$pgDbName;
33+
self::$hasSetUp = true;
2934
return;
3035
}
3136

3237
self::$instance = self::getClient()->instance(self::INSTANCE_NAME);
3338

34-
self::$dbName = uniqid(self::TESTING_PREFIX);
39+
if (!self::$dbName = getenv('GOOGLE_CLOUD_SPANNER_TEST_PG_DATABASE')) {
40+
self::$dbName = uniqid(self::TESTING_PREFIX);
3541

36-
// create a PG DB first
37-
$op = self::$instance->createDatabase(self::$dbName, [
38-
'databaseDialect' => DatabaseDialect::POSTGRESQL
39-
]);
40-
// wait for the DB to be ready
41-
$op->pollUntilComplete();
42-
43-
$db = self::getDatabaseInstance(self::$dbName);
44-
45-
self::$deletionQueue->add(function () use ($db) {
46-
$db->drop();
47-
});
48-
49-
self::$database = $db;
50-
51-
$db->updateDdlBatch(
52-
[
53-
'CREATE TABLE ' . self::TEST_TABLE_NAME . ' (
54-
id bigint PRIMARY KEY,
55-
name varchar(1024) NOT NULL,
56-
birthday date
57-
)',
58-
]
59-
)->pollUntilComplete();
42+
self::$deletionQueue->add(function () {
43+
self::getDatabaseInstance(self::$dbName)->drop();
44+
});
45+
}
46+
47+
self::$database = self::getDatabaseInstance(self::$dbName);
6048

61-
// Currently, the emulator doesn't support setting roles for the PG
62-
// dialect.
63-
if (!self::isEmulatorUsed()) {
49+
if (!self::$database->exists()) {
50+
$op = self::$instance->createDatabase(self::$dbName, [
51+
'databaseDialect' => DatabaseDialect::POSTGRESQL
52+
]);
53+
$op->pollUntilComplete();
54+
6455
$db->updateDdlBatch(
6556
[
66-
'CREATE ROLE ' . self::DATABASE_ROLE,
67-
'CREATE ROLE ' . self::RESTRICTIVE_DATABASE_ROLE,
68-
'GRANT SELECT ON TABLE ' . self::TEST_TABLE_NAME .
69-
' TO ' . self::DATABASE_ROLE,
70-
'GRANT SELECT(id, name), INSERT(id, name), UPDATE(id, name) ON TABLE '
71-
. self::TEST_TABLE_NAME . ' TO ' . self::RESTRICTIVE_DATABASE_ROLE,
57+
'CREATE TABLE IF NOT EXISTS ' . self::TEST_TABLE_NAME . ' (
58+
id bigint PRIMARY KEY,
59+
name varchar(1024) NOT NULL,
60+
birthday date
61+
)',
7262
]
7363
)->pollUntilComplete();
64+
65+
// Currently, the emulator doesn't support setting roles for the PG
66+
// dialect.
67+
if (!self::isEmulatorUsed()) {
68+
$db->updateDdlBatch(
69+
[
70+
'CREATE ROLE ' . self::DATABASE_ROLE,
71+
'CREATE ROLE ' . self::RESTRICTIVE_DATABASE_ROLE,
72+
'GRANT SELECT ON TABLE ' . self::TEST_TABLE_NAME .
73+
' TO ' . self::DATABASE_ROLE,
74+
'GRANT SELECT(id, name), INSERT(id, name), UPDATE(id, name) ON TABLE '
75+
. self::TEST_TABLE_NAME . ' TO ' . self::RESTRICTIVE_DATABASE_ROLE,
76+
]
77+
)->pollUntilComplete();
78+
}
7479
}
7580

81+
TestDatabaseManager::$pgHasSetUp = true;
82+
TestDatabaseManager::$client = self::$client;
83+
TestDatabaseManager::$instance = self::$instance;
84+
TestDatabaseManager::$pgDatabase = self::$database;
85+
TestDatabaseManager::$pgDbName = self::$dbName;
7686
self::$hasSetUp = true;
7787
}
7888
}

Spanner/tests/System/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ GOOGLE_CLOUD_PROJECT="<YOUR_PROJECT_ID>"
1212

1313
# These environment variables are optional, and will speed up running the tests locally
1414
GOOGLE_CLOUD_SPANNER_TEST_DATABASE=test-database
15+
GOOGLE_CLOUD_SPANNER_TEST_PG_DATABASE=test-pg-database
1516
GOOGLE_CLOUD_SPANNER_TEST_BACKUP_DATABASE_1=test-backup-database1
1617
GOOGLE_CLOUD_SPANNER_TEST_BACKUP_DATABASE_2=test-backup-database2
1718
```

Spanner/tests/System/SystemTestCaseTrait.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ private static function getClient()
4444
if (self::$client) {
4545
return self::$client;
4646
}
47+
if (TestDatabaseManager::$client) {
48+
return self::$client = TestDatabaseManager::$client;
49+
}
4750

4851
$keyFilePath = getenv('GOOGLE_CLOUD_PHP_TESTS_KEY_PATH');
4952

@@ -68,6 +71,7 @@ private static function getClient()
6871
]
6972
];
7073
$clientConfig = [
74+
'projectId' => getenv('GOOGLE_CLOUD_PROJECT') ?: null,
7175
'keyFilePath' => $keyFilePath,
7276
'enableBuiltInMetrics' => false, // Disabling the metrics for general tests
7377
];
@@ -93,7 +97,12 @@ private static function getClient()
9397

9498
private static function setUpTestDatabase(): void
9599
{
96-
if (self::$hasSetUp) {
100+
if (TestDatabaseManager::$sqlHasSetUp) {
101+
self::$client = TestDatabaseManager::$client;
102+
self::$instance = TestDatabaseManager::$instance;
103+
self::$database = TestDatabaseManager::$sqlDatabase;
104+
self::$dbName = TestDatabaseManager::$sqlDbName;
105+
self::$hasSetUp = true;
97106
return;
98107
}
99108

@@ -139,6 +148,11 @@ private static function setUpTestDatabase(): void
139148
}
140149
}
141150

151+
TestDatabaseManager::$sqlHasSetUp = true;
152+
TestDatabaseManager::$client = self::$client;
153+
TestDatabaseManager::$instance = self::$instance;
154+
TestDatabaseManager::$sqlDatabase = self::$database;
155+
TestDatabaseManager::$sqlDbName = self::$dbName;
142156
self::$hasSetUp = true;
143157
}
144158

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
namespace Google\Cloud\Spanner\Tests\System;
19+
20+
/**
21+
* Manages shared database states across Spanner system tests to avoid provisioning
22+
* a new database for every test class.
23+
*
24+
* @internal
25+
*/
26+
class TestDatabaseManager
27+
{
28+
public static $client;
29+
public static $instance;
30+
31+
public static $sqlHasSetUp = false;
32+
public static $sqlDatabase;
33+
public static $sqlDbName;
34+
35+
public static $pgHasSetUp = false;
36+
public static $pgDatabase;
37+
public static $pgDbName;
38+
}

Spanner/tests/System/WriteTest.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use Google\Cloud\Spanner\KeySet;
2929
use Google\Cloud\Spanner\Numeric;
3030
use Google\Cloud\Spanner\Proto;
31+
use Google\Cloud\Spanner\Uuid;
3132
use Google\Cloud\Spanner\Timestamp;
3233
use Google\Protobuf\Internal\Message;
3334
use Google\Rpc\Code;
@@ -139,8 +140,12 @@ public function testWriteAndReadBackValue($id, $field, $value)
139140
$read = $db->read(self::TABLE_NAME, $keyset, [$field]);
140141
$row = $read->rows()->current();
141142

142-
if ($value instanceof Timestamp || $value instanceof Uuid) {
143+
if ($value instanceof Timestamp) {
143144
$this->assertEquals($value->formatAsString(), $row[$field]->formatAsString());
145+
} elseif ($value instanceof Uuid) {
146+
$this->assertEquals($value->formatAsString(), is_string($row[$field])
147+
? $row[$field]
148+
: $row[$field]->formatAsString());
144149
} else {
145150
$this->assertValues($value, $row[$field]);
146151
}
@@ -153,8 +158,12 @@ public function testWriteAndReadBackValue($id, $field, $value)
153158
]);
154159

155160
$row = $exec->rows()->current();
156-
if ($value instanceof Timestamp || $value instanceof Uuid) {
161+
if ($value instanceof Timestamp) {
157162
$this->assertEquals($value->formatAsString(), $row[$field]->formatAsString());
163+
} elseif ($value instanceof Uuid) {
164+
$this->assertEquals($value->formatAsString(), is_string($row[$field])
165+
? $row[$field]
166+
: $row[$field]->formatAsString());
158167
} elseif ($value instanceof Message) {
159168
$this->assertInstanceOf(Proto::class, $row[$field]);
160169
$this->assertEquals(base64_encode($value->serializeToString()), $row[$field]->getValue());

0 commit comments

Comments
 (0)