Skip to content

Commit 50f3cd9

Browse files
authored
test: Fix Spanner Backup tests (GoogleCloudPlatform#1052)
1 parent 8e3b542 commit 50f3cd9

File tree

3 files changed

+245
-194
lines changed

3 files changed

+245
-194
lines changed

spanner/test/spannerBackupTest.php

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
<?php
2+
/**
3+
* Copyright 2020 Google LLC
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\Samples\Spanner;
19+
20+
use Google\Cloud\Spanner\Database;
21+
use Google\Cloud\Spanner\Backup;
22+
use Google\Cloud\Spanner\SpannerClient;
23+
use Google\Cloud\Spanner\Instance;
24+
use Google\Cloud\TestUtils\ExecuteCommandTrait;
25+
use Google\Cloud\TestUtils\EventuallyConsistentTestTrait;
26+
use Google\Cloud\TestUtils\TestTrait;
27+
use PHPUnitRetry\RetryTrait;
28+
use PHPUnit\Framework\TestCase;
29+
30+
/**
31+
* @retryAttempts 3
32+
*/
33+
class spannerBackupTest extends TestCase
34+
{
35+
use RetryTrait, TestTrait, EventuallyConsistentTestTrait;
36+
use ExecuteCommandTrait {
37+
ExecuteCommandTrait::runCommand as traitRunCommand;
38+
}
39+
40+
private static $commandFile = __DIR__ . '/../spanner.php';
41+
42+
/** @var string instanceId */
43+
protected static $instanceId;
44+
45+
/** @var string backupId */
46+
protected static $backupId;
47+
48+
/** @var string databaseId */
49+
protected static $databaseId;
50+
51+
/** @var $instance Instance */
52+
protected static $instance;
53+
54+
public static function setUpBeforeClass()
55+
{
56+
self::checkProjectEnvVars();
57+
58+
if (!extension_loaded('grpc')) {
59+
self::markTestSkipped('Must enable grpc extension.');
60+
}
61+
self::$instanceId = self::requireEnv('GOOGLE_SPANNER_INSTANCE_ID');
62+
63+
$spanner = new SpannerClient([
64+
'projectId' => self::$projectId,
65+
]);
66+
67+
self::$databaseId = 'test-' . time() . rand();
68+
self::$backupId = 'backup-' . self::$databaseId;
69+
self::$instance = $spanner->instance(self::$instanceId);
70+
self::$instance->database(self::$databaseId)->create();
71+
}
72+
73+
public function testCancelBackup()
74+
{
75+
$output = $this->runCommand('cancel-backup', [
76+
'database_id' => self::$databaseId,
77+
]);
78+
$this->assertContains('Cancel backup operation complete', $output);
79+
}
80+
81+
public function testCreateBackup()
82+
{
83+
$output = $this->traitRunCommand('create-backup', [
84+
'instance_id' => self::$instanceId,
85+
'database_id' => self::$databaseId,
86+
'backup_id' => self::$backupId,
87+
]);
88+
$this->assertContains(self::$backupId, $output);
89+
}
90+
91+
/**
92+
* @depends testCreateBackup
93+
*/
94+
public function testListBackupOperations()
95+
{
96+
$databaseId2 = self::$databaseId . '-2';
97+
$database2 = self::$instance->database($databaseId2);
98+
// DB may already exist if the test timed out and retried
99+
if (!$database2->exists()) {
100+
$database2->create();
101+
}
102+
$backup = self::$instance->backup(self::$backupId . '-pro');
103+
$lro = $backup->create($databaseId2, new \DateTime('+7 hours'));
104+
$output = $this->runCommand('list-backup-operations', [
105+
'database_id' => self::$databaseId,
106+
]);
107+
$this->assertContains(basename($lro->name()), $output);
108+
$lro->pollUntilComplete();
109+
}
110+
111+
/**
112+
* @depends testCreateBackup
113+
*/
114+
public function testListBackups()
115+
{
116+
$output = $this->runCommand('list-backups');
117+
$this->assertContains(self::$backupId, $output);
118+
}
119+
120+
/**
121+
* @depends testCreateBackup
122+
*/
123+
public function testUpdateBackup()
124+
{
125+
$output = $this->runCommand('update-backup', [
126+
'backup_id' => self::$backupId,
127+
]);
128+
$this->assertContains(self::$backupId, $output);
129+
}
130+
131+
/**
132+
* @depends testUpdateBackup
133+
*/
134+
public function testRestoreBackup()
135+
{
136+
$output = $this->runCommand('restore-backup', [
137+
'database_id' => self::$databaseId . '-res',
138+
'backup_id' => self::$backupId,
139+
]);
140+
$this->assertContains(self::$backupId, $output);
141+
$this->assertContains(self::$databaseId, $output);
142+
}
143+
144+
145+
/**
146+
* @depends testRestoreBackup
147+
*/
148+
public function testListDatabaseOperations()
149+
{
150+
$output = $this->runCommand('list-database-operations');
151+
$this->assertContains('Running optimize operation', $output);
152+
}
153+
154+
/**
155+
* @depends testListBackups
156+
*/
157+
public function testDeleteBackup()
158+
{
159+
self::waitForOperations();
160+
$output = $this->runCommand('delete-backup', [
161+
'backup_id' => self::$backupId,
162+
]);
163+
$this->assertContains(self::$backupId, $output);
164+
}
165+
166+
private static function waitForOperations()
167+
{
168+
// Wait for backup operations
169+
$filter = '(metadata.@type:type.googleapis.com/' .
170+
'google.spanner.admin.database.v1.%s)';
171+
172+
$backupOperations = self::$instance->backupOperations([
173+
'filter' => sprintf($filter, 'CreateBackupMetadata')
174+
]);
175+
176+
$dbOperations = self::$instance->databaseOperations([
177+
'filter' => sprintf($filter, 'OptimizeRestoredDatabaseMetadata')
178+
]);
179+
180+
foreach ($backupOperations as $operation) {
181+
if (!$operation->done()) {
182+
$operation->pollUntilComplete();
183+
}
184+
}
185+
foreach ($dbOperations as $operation) {
186+
if (!$operation->done()) {
187+
$operation->pollUntilComplete();
188+
}
189+
}
190+
}
191+
192+
private function runCommand($commandName, $params = [])
193+
{
194+
return $this->traitRunCommand($commandName, $params + [
195+
'instance_id' => self::$instanceId,
196+
]);
197+
}
198+
199+
public static function tearDownAfterClass()
200+
{
201+
if (!self::$instance->exists()) {
202+
return;
203+
}
204+
205+
self::waitForOperations();
206+
207+
$exceptions = [];
208+
209+
$dbs = self::$instance->databases();
210+
/** @var Database $db */
211+
foreach ($dbs as $db) {
212+
if (strstr($db->name(), self::$databaseId) !== false) {
213+
try {
214+
$db->drop();
215+
} catch (\Exception $e) {
216+
$exceptions[] = $e;
217+
}
218+
}
219+
}
220+
221+
$backups = self::$instance->backups();
222+
/** @var Backup $backup */
223+
foreach ($backups as $backup) {
224+
if (strstr($backup->name(), self::$databaseId) !== false) {
225+
try {
226+
$backup->delete();
227+
} catch (\Exception $e) {
228+
$exceptions[] = $e;
229+
}
230+
}
231+
}
232+
233+
if ($exceptions) {
234+
throw new \RuntimeException(PHP_EOL . implode(PHP_EOL, $exceptions));
235+
}
236+
}
237+
}

0 commit comments

Comments
 (0)