Skip to content

Commit 1fd47bf

Browse files
chore(test): improve resource handling in tests (googleapis#801)
* chore(test): improve resource handling in tests * fix resource cleanup: time based resource cleanup expected a prefix followed by a number, but some tests inserted a string in between which would prevent clean. Now all prefixes are generated in a single place * fix cleanup contention: concurrent tests will try to cleanup resources at the same time. Mitigate this by swallowing not found error * fix concurrent test runs: the prefix was based on time only, which would causes tests running in the same second to clobber each other * optimize backup test to only create a single new instance * shorten clean up of backups * tweaks * reverse logic in cross instance restore
1 parent b836fde commit 1fd47bf

6 files changed

Lines changed: 293 additions & 179 deletions

File tree

java-bigtable/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableBackupIT.java

Lines changed: 84 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
import static io.grpc.Status.Code.NOT_FOUND;
2222
import static org.junit.Assert.fail;
2323

24-
import com.google.api.core.ApiFuture;
25-
import com.google.api.core.ApiFutures;
24+
import com.google.api.gax.batching.Batcher;
2625
import com.google.api.gax.rpc.ApiException;
2726
import com.google.cloud.Policy;
2827
import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminClient;
@@ -38,11 +37,10 @@
3837
import com.google.cloud.bigtable.admin.v2.models.Table;
3938
import com.google.cloud.bigtable.admin.v2.models.UpdateBackupRequest;
4039
import com.google.cloud.bigtable.data.v2.BigtableDataClient;
41-
import com.google.cloud.bigtable.data.v2.models.RowMutation;
42-
import com.google.cloud.bigtable.test_helpers.env.AbstractTestEnv;
40+
import com.google.cloud.bigtable.data.v2.models.RowMutationEntry;
4341
import com.google.cloud.bigtable.test_helpers.env.EmulatorEnv;
4442
import com.google.cloud.bigtable.test_helpers.env.TestEnvRule;
45-
import com.google.common.collect.Lists;
43+
import com.google.common.base.Stopwatch;
4644
import com.google.protobuf.ByteString;
4745
import io.grpc.StatusRuntimeException;
4846
import java.io.IOException;
@@ -52,97 +50,61 @@
5250
import java.util.concurrent.TimeUnit;
5351
import java.util.concurrent.TimeoutException;
5452
import java.util.logging.Logger;
55-
import org.junit.*;
53+
import org.junit.AfterClass;
54+
import org.junit.BeforeClass;
55+
import org.junit.ClassRule;
56+
import org.junit.Test;
5657
import org.junit.runner.RunWith;
5758
import org.junit.runners.JUnit4;
5859
import org.threeten.bp.Duration;
5960
import org.threeten.bp.Instant;
6061

6162
@RunWith(JUnit4.class)
6263
public class BigtableBackupIT {
63-
@ClassRule public static TestEnvRule testEnvRule = new TestEnvRule();
64+
@ClassRule public static final TestEnvRule testEnvRule = new TestEnvRule();
6465

6566
private static final Logger LOGGER = Logger.getLogger(BigtableBackupIT.class.getName());
6667

6768
private static final int[] BACKOFF_DURATION = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
6869

69-
private static final String TEST_TABLE_SUFFIX = "test-table-for-backup-it";
70-
private static final String TEST_BACKUP_SUFFIX = "test-backup-for-backup-it";
71-
7270
private static BigtableTableAdminClient tableAdmin;
7371
private static BigtableInstanceAdminClient instanceAdmin;
7472
private static BigtableDataClient dataClient;
7573

76-
private static String targetInstance;
7774
private static String targetCluster;
7875
private static Table testTable;
79-
private static String prefix;
8076

8177
@BeforeClass
82-
public static void createClient()
83-
throws IOException, InterruptedException, ExecutionException, TimeoutException {
78+
public static void setUpClass() throws InterruptedException {
8479
assume()
8580
.withMessage("BigtableInstanceAdminClient is not supported on Emulator")
8681
.that(testEnvRule.env())
8782
.isNotInstanceOf(EmulatorEnv.class);
8883

84+
tableAdmin = testEnvRule.env().getTableAdminClient();
8985
instanceAdmin = testEnvRule.env().getInstanceAdminClient();
86+
dataClient = testEnvRule.env().getDataClient();
9087

91-
targetCluster = AbstractTestEnv.TEST_CLUSTER_PREFIX + Instant.now().getEpochSecond();
92-
targetInstance =
93-
AbstractTestEnv.TEST_INSTANCE_PREFIX + "backup-" + Instant.now().getEpochSecond();
94-
95-
instanceAdmin.createInstance(
96-
CreateInstanceRequest.of(targetInstance)
97-
.addCluster(targetCluster, testEnvRule.env().getPrimaryZone(), 3, StorageType.SSD)
98-
.setDisplayName("backups-test-instance")
99-
.addLabel("state", "readytodelete")
100-
.setType(Type.PRODUCTION));
101-
102-
// Setup a prefix to avoid collisions between concurrent test runs
103-
prefix = String.format("020%d", System.currentTimeMillis());
104-
105-
tableAdmin = testEnvRule.env().getTableAdminClientForInstance(targetInstance);
106-
dataClient = testEnvRule.env().getDataClientForInstance(targetInstance);
107-
88+
targetCluster = testEnvRule.env().getPrimaryClusterId();
10889
testTable = createAndPopulateTestTable(tableAdmin, dataClient);
10990
}
11091

11192
@AfterClass
112-
public static void closeClient() {
93+
public static void tearDownClass() {
11394
if (testTable != null) {
11495
try {
11596
tableAdmin.deleteTable(testTable.getId());
11697
} catch (Exception e) {
11798
// Ignore.
11899
}
119100
}
120-
121-
if (targetInstance != null) {
122-
instanceAdmin.deleteInstance(targetInstance);
123-
}
124-
125-
if (tableAdmin != null) {
126-
tableAdmin.close();
127-
}
128-
129-
if (dataClient != null) {
130-
dataClient.close();
131-
}
132-
}
133-
134-
@Before
135-
public void setup() {
136-
if (tableAdmin == null) {
137-
throw new AssumptionViolatedException(
138-
"Required properties are not set, skipping integration tests.");
139-
}
140101
}
141102

142103
@Test
143-
public void createAndGetBackupTest() throws InterruptedException {
144-
Instant expireTime = Instant.now().plus(Duration.ofDays(15));
145-
String backupId = generateId(TEST_BACKUP_SUFFIX);
104+
public void createAndGetBackupTest() {
105+
String backupId = testEnvRule.env().newPrefix();
106+
Instant expireTime = Instant.now().plus(Duration.ofHours(6));
107+
146108
CreateBackupRequest request =
147109
CreateBackupRequest.of(targetCluster, backupId)
148110
.setSourceTableId(testTable.getId())
@@ -185,9 +147,9 @@ public void createAndGetBackupTest() throws InterruptedException {
185147
}
186148

187149
@Test
188-
public void listBackupTest() throws InterruptedException {
189-
String backupId1 = generateId("list-1-" + TEST_BACKUP_SUFFIX);
190-
String backupId2 = generateId("list-2-" + TEST_BACKUP_SUFFIX);
150+
public void listBackupTest() {
151+
String backupId1 = testEnvRule.env().newPrefix();
152+
String backupId2 = testEnvRule.env().newPrefix();
191153

192154
try {
193155
tableAdmin.createBackup(createBackupRequest(backupId1));
@@ -206,8 +168,8 @@ public void listBackupTest() throws InterruptedException {
206168
}
207169

208170
@Test
209-
public void updateBackupTest() throws InterruptedException {
210-
String backupId = generateId("update-" + TEST_BACKUP_SUFFIX);
171+
public void updateBackupTest() {
172+
String backupId = testEnvRule.env().newPrefix();
211173
tableAdmin.createBackup(createBackupRequest(backupId));
212174

213175
Instant expireTime = Instant.now().plus(Duration.ofDays(20));
@@ -223,7 +185,7 @@ public void updateBackupTest() throws InterruptedException {
223185

224186
@Test
225187
public void deleteBackupTest() throws InterruptedException {
226-
String backupId = generateId("delete-" + TEST_BACKUP_SUFFIX);
188+
String backupId = testEnvRule.env().newPrefix();
227189

228190
tableAdmin.createBackup(createBackupRequest(backupId));
229191
tableAdmin.deleteBackup(targetCluster, backupId);
@@ -248,8 +210,8 @@ public void deleteBackupTest() throws InterruptedException {
248210

249211
@Test
250212
public void restoreTableTest() throws InterruptedException, ExecutionException {
251-
String backupId = generateId("restore-" + TEST_BACKUP_SUFFIX);
252-
String restoredTableId = generateId("restored-table");
213+
String backupId = testEnvRule.env().newPrefix();
214+
String restoredTableId = testEnvRule.env().newPrefix() + "-restore";
253215
tableAdmin.createBackup(createBackupRequest(backupId));
254216

255217
// Wait 2 minutes so that the RestoreTable API will trigger an optimize restored
@@ -282,62 +244,65 @@ public void restoreTableTest() throws InterruptedException, ExecutionException {
282244
@Test
283245
public void crossInstanceRestoreTest()
284246
throws InterruptedException, IOException, ExecutionException, TimeoutException {
285-
String backupId = generateId("cross-" + TEST_BACKUP_SUFFIX);
286-
String restoredTableId = generateId("restored-table-2");
287-
288-
// Set up a new instance to test cross-instance restore. The source backup is stored in this
289-
// instance.
290-
String sourceInstance =
291-
AbstractTestEnv.TEST_INSTANCE_PREFIX + "backup-" + Instant.now().getEpochSecond();
292-
String sourceCluster = AbstractTestEnv.TEST_CLUSTER_PREFIX + Instant.now().getEpochSecond();
247+
String backupId = testEnvRule.env().newPrefix();
248+
String restoredTableId = testEnvRule.env().newPrefix();
249+
250+
// Create the backup
251+
tableAdmin.createBackup(
252+
CreateBackupRequest.of(targetCluster, backupId)
253+
.setSourceTableId(testTable.getId())
254+
.setExpireTime(Instant.now().plus(Duration.ofHours(6))));
255+
256+
Stopwatch stopwatch = Stopwatch.createStarted();
257+
258+
// Set up a new instance to test cross-instance restore. The backup will be restored here
259+
String targetInstance = testEnvRule.env().newPrefix();
293260
instanceAdmin.createInstance(
294-
CreateInstanceRequest.of(sourceInstance)
295-
.addCluster(sourceCluster, testEnvRule.env().getSecondaryZone(), 3, StorageType.SSD)
296-
.setDisplayName("backups-source-test-instance")
261+
CreateInstanceRequest.of(targetInstance)
262+
.addCluster(targetInstance, testEnvRule.env().getSecondaryZone(), 1, StorageType.SSD)
263+
.setDisplayName("backups-dest-test-instance")
297264
.addLabel("state", "readytodelete")
298265
.setType(Type.PRODUCTION));
299-
BigtableTableAdminClient sourceTableAdmin =
300-
testEnvRule.env().getTableAdminClientForInstance(sourceInstance);
301-
Table sourceTable =
302-
createAndPopulateTestTable(
303-
sourceTableAdmin, testEnvRule.env().getDataClientForInstance(sourceInstance));
304-
sourceTableAdmin.createBackup(
305-
CreateBackupRequest.of(sourceCluster, backupId)
306-
.setSourceTableId(sourceTable.getId())
307-
.setExpireTime(Instant.now().plus(Duration.ofHours(6))));
308266

309-
// Wait 2 minutes so that the RestoreTable API will trigger an optimize restored
310-
// table operation.
311-
Thread.sleep(120 * 1000);
267+
try (BigtableTableAdminClient destTableAdmin =
268+
testEnvRule.env().getTableAdminClientForInstance(targetInstance)) {
312269

313-
try {
314-
RestoreTableRequest req =
315-
RestoreTableRequest.of(sourceInstance, sourceCluster, backupId)
316-
.setTableId(restoredTableId);
317-
RestoredTableResult result = tableAdmin.restoreTable(req);
318-
assertWithMessage("Incorrect restored table id")
319-
.that(result.getTable().getId())
320-
.isEqualTo(restoredTableId);
321-
assertWithMessage("Incorrect instance id")
322-
.that(result.getTable().getInstanceId())
323-
.isEqualTo(targetInstance);
324-
325-
// The assertion might be missing if the test is running against a HDD cluster or an
326-
// optimization is not necessary.
327-
assertWithMessage("Empty OptimizeRestoredTable token")
328-
.that(result.getOptimizeRestoredTableOperationToken())
329-
.isNotNull();
330-
tableAdmin.awaitOptimizeRestoredTable(result.getOptimizeRestoredTableOperationToken());
331-
tableAdmin.getTable(restoredTableId);
332-
} finally {
333-
sourceTableAdmin.deleteBackup(sourceCluster, backupId);
334-
instanceAdmin.deleteInstance(sourceInstance);
270+
// Wait 2 minutes so that the RestoreTable API will trigger an optimize restored
271+
// table operation.
272+
Thread.sleep(
273+
Duration.ofMinutes(2)
274+
.minus(Duration.ofMillis(stopwatch.elapsed(TimeUnit.MILLISECONDS)))
275+
.toMillis());
276+
277+
try {
278+
RestoreTableRequest req =
279+
RestoreTableRequest.of(testEnvRule.env().getInstanceId(), targetCluster, backupId)
280+
.setTableId(restoredTableId);
281+
RestoredTableResult result = destTableAdmin.restoreTable(req);
282+
assertWithMessage("Incorrect restored table id")
283+
.that(result.getTable().getId())
284+
.isEqualTo(restoredTableId);
285+
assertWithMessage("Incorrect instance id")
286+
.that(result.getTable().getInstanceId())
287+
.isEqualTo(targetInstance);
288+
289+
// The assertion might be missing if the test is running against a HDD cluster or an
290+
// optimization is not necessary.
291+
assertWithMessage("Empty OptimizeRestoredTable token")
292+
.that(result.getOptimizeRestoredTableOperationToken())
293+
.isNotNull();
294+
destTableAdmin.awaitOptimizeRestoredTable(result.getOptimizeRestoredTableOperationToken());
295+
destTableAdmin.getTable(restoredTableId);
296+
} finally {
297+
tableAdmin.deleteBackup(targetCluster, backupId);
298+
instanceAdmin.deleteInstance(targetInstance);
299+
}
335300
}
336301
}
337302

338303
@Test
339-
public void backupIamTest() throws InterruptedException {
340-
String backupId = generateId("iam-" + TEST_BACKUP_SUFFIX);
304+
public void backupIamTest() {
305+
String backupId = testEnvRule.env().newPrefix();
341306

342307
try {
343308
tableAdmin.createBackup(createBackupRequest(backupId));
@@ -373,31 +338,24 @@ private CreateBackupRequest createBackupRequest(String backupId) {
373338
.setExpireTime(Instant.now().plus(Duration.ofDays(15)));
374339
}
375340

376-
private static String generateId(String name) {
377-
return prefix + "-" + name;
378-
}
379-
380341
private static Table createAndPopulateTestTable(
381342
BigtableTableAdminClient tableAdmin, BigtableDataClient dataClient)
382-
throws InterruptedException, ExecutionException, TimeoutException {
383-
Table testTable =
384-
tableAdmin.createTable(
385-
CreateTableRequest.of(generateId(TEST_TABLE_SUFFIX)).addFamily("cf1"));
343+
throws InterruptedException {
344+
String tableId = testEnvRule.env().newPrefix();
345+
Table testTable = tableAdmin.createTable(CreateTableRequest.of(tableId).addFamily("cf1"));
386346

387347
// Populate test data.
388348
byte[] rowBytes = new byte[1024];
389349
Random random = new Random();
390350
random.nextBytes(rowBytes);
391351

392-
List<ApiFuture<?>> futures = Lists.newArrayList();
393-
for (int i = 0; i < 10; i++) {
394-
ApiFuture<Void> future =
395-
dataClient.mutateRowAsync(
396-
RowMutation.create(testTable.getId(), "test-row-" + i)
397-
.setCell("cf1", ByteString.EMPTY, ByteString.copyFrom(rowBytes)));
398-
futures.add(future);
352+
try (Batcher<RowMutationEntry, Void> batcher = dataClient.newBulkMutationBatcher(tableId)) {
353+
for (int i = 0; i < 10; i++) {
354+
batcher.add(
355+
RowMutationEntry.create("test-row-" + i)
356+
.setCell("cf1", ByteString.EMPTY, ByteString.copyFrom(rowBytes)));
357+
}
399358
}
400-
ApiFutures.allAsList(futures).get(3, TimeUnit.MINUTES);
401359
return testTable;
402360
}
403361
}

java-bigtable/google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/admin/v2/it/BigtableCmekIT.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import com.google.cloud.bigtable.admin.v2.models.StorageType;
3434
import com.google.cloud.bigtable.common.Status;
3535
import com.google.cloud.bigtable.common.Status.Code;
36-
import com.google.cloud.bigtable.test_helpers.env.AbstractTestEnv;
3736
import com.google.cloud.bigtable.test_helpers.env.EmulatorEnv;
3837
import com.google.cloud.bigtable.test_helpers.env.TestEnvRule;
3938
import com.google.common.collect.ImmutableSet;
@@ -89,7 +88,7 @@ public static void validatePlatform() throws IOException {
8988
assertThat(kmsKeyName).isNotNull();
9089
assertThat(kmsKeyName).isNotEmpty();
9190

92-
instanceId = AbstractTestEnv.TEST_INSTANCE_PREFIX + Instant.now().getEpochSecond();
91+
instanceId = testEnvRule.env().newPrefix();
9392
clusterId1 = instanceId + "-c1";
9493
clusterId2 = instanceId + "-c2";
9594
clusterId3 = instanceId + "-c3";

0 commit comments

Comments
 (0)