Skip to content

Commit efd2b05

Browse files
wip
1 parent 8624b3f commit efd2b05

6 files changed

Lines changed: 73 additions & 36 deletions

File tree

TESTING.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
This library provides tools to help write tests for code that uses the following google-cloud services:
44

55
- [BigQuery](#testing-code-that-uses-bigquery)
6+
- [Bigtable](#testing-code-that-uses-bigtable)
67
- [Compute](#testing-code-that-uses-compute)
78
- [Datastore](#testing-code-that-uses-datastore)
89
- [DNS](#testing-code-that-uses-dns)
@@ -41,6 +42,24 @@ Here is an example that clears the dataset created in Step 3.
4142
RemoteBigQueryHelper.forceDelete(bigquery, dataset);
4243
```
4344

45+
### Testing code that uses Bigtable
46+
47+
Bigtable integration tests can either be run against an emulator or a real Bigtable table. The
48+
target environment can be selected via the `bigtable.env` system property. By default it is set to
49+
`emulator` and the other option is `prod`.
50+
51+
To use the `emulator` environment, please install the gcloud sdk and use it to install the
52+
`cbtemulator` via `gcloud components install bigtable`.
53+
54+
To use the `prod` environment:
55+
1. Create a table with a column family named `cf`.
56+
2. Download the [JSON service account credentials file][create-service-account] from the Google
57+
Developer's Console.
58+
3. Set the environment variable `GOOGLE_APPLICATION_CREDENTIALS` to the path of the credentials file
59+
4. Set the system properties `bigtable.project`, `bigtable.instance` and `bigtable.table` to the
60+
table you created earlier.
61+
62+
4463
### Testing code that uses Compute
4564

4665
Currently, there isn't an emulator for Google Compute, so an alternative is to create a test

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/env/Emulator.java

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@
3434
import java.io.InputStreamReader;
3535
import java.net.ServerSocket;
3636
import java.net.Socket;
37+
import java.nio.file.Files;
38+
import java.nio.file.Path;
3739
import java.nio.file.Paths;
3840
import java.util.concurrent.Callable;
41+
import java.util.concurrent.ExecutionException;
3942
import java.util.concurrent.Future;
4043
import java.util.concurrent.FutureTask;
4144
import java.util.concurrent.TimeUnit;
@@ -49,7 +52,7 @@
4952
class Emulator {
5053
private static final Logger LOGGER = Logger.getLogger(Emulator.class.getName());
5154

52-
private final String executable;
55+
private final Path executable;
5356
private Process process;
5457
private ManagedChannel channel;
5558
private BigtableTableAdminClient tableAdminClient;
@@ -58,47 +61,32 @@ class Emulator {
5861
private static final InstanceName INSTANCE_NAME =
5962
InstanceName.of("fake-project", "fake-instance");
6063

64+
// Use the gcloud installed emulator
6165
static Emulator createGCloud() {
62-
final Process p;
66+
final Path gcloudSdkPath;
6367

6468
try {
65-
p = Runtime.getRuntime().exec("gcloud info --format=value(installation.sdk_root)");
66-
pipeStreamToLog(p.getErrorStream(), Level.WARNING);
67-
} catch (IOException e) {
68-
throw new RuntimeException("Failed to run gcloud info", e);
69-
}
70-
71-
String sdkRoot;
72-
try {
73-
sdkRoot = bufferOutput(p.getInputStream()).get(1, TimeUnit.MINUTES).trim();
69+
gcloudSdkPath = getGcloudSdkPath();
7470
} catch (Exception e) {
75-
throw new RuntimeException("Failed to get gcloud sdk install path", e);
76-
}
77-
78-
try {
79-
if (p.waitFor() != 0) {
80-
throw new RuntimeException("Failed to get sdk root, is gcloud sdk installed?");
81-
}
82-
} catch (InterruptedException e) {
83-
throw new RuntimeException("Interrupted invoking gcloud", e);
71+
throw new RuntimeException("Failed to get the gcloud SDK path. Is it installed?", e);
8472
}
8573

86-
String emulatorPath =
87-
Paths.get(sdkRoot, "platform", "bigtable-emulator", "cbtemulator").toString();
74+
Path emulatorPath =
75+
gcloudSdkPath.resolve(Paths.get("platform", "bigtable-emulator", "cbtemulator"));
8876

89-
if (!new File(emulatorPath).exists()) {
77+
if (!Files.exists(emulatorPath)) {
9078
throw new RuntimeException(
9179
"cbtemulator is not installed, please install with `gcloud components install bigtable`");
9280
}
9381

9482
return new Emulator(emulatorPath);
9583
}
9684

97-
private Emulator(String executable) {
85+
private Emulator(Path executable) {
9886
this.executable = executable;
9987
}
10088

101-
void start() throws InterruptedException, IOException, TimeoutException {
89+
void start() throws Exception {
10290
int availablePort = getAvailablePort();
10391

10492
process = Runtime.getRuntime().exec(executable + " -port " + "" + availablePort);
@@ -120,11 +108,14 @@ void start() throws InterruptedException, IOException, TimeoutException {
120108
}
121109

122110
void stop() throws Exception {
123-
dataClient.close();
124-
tableAdminClient.close();
125-
channel.shutdownNow();
126-
channel.awaitTermination(1, TimeUnit.MINUTES);
127-
process.destroy();
111+
try {
112+
dataClient.close();
113+
tableAdminClient.close();
114+
channel.shutdownNow();
115+
channel.awaitTermination(1, TimeUnit.MINUTES);
116+
} finally {
117+
process.destroy();
118+
}
128119
}
129120

130121
BigtableDataClient getDataClient() {
@@ -136,6 +127,18 @@ BigtableTableAdminClient getTableAdminClient() {
136127
}
137128

138129
// <editor-fold desc="Helpers">
130+
private static Path getGcloudSdkPath() throws Exception {
131+
Process p = Runtime.getRuntime().exec("gcloud info --format=value(installation.sdk_root)");
132+
pipeStreamToLog(p.getErrorStream(), Level.WARNING);
133+
134+
String sdkRoot = bufferOutput(p.getInputStream()).get(1, TimeUnit.MINUTES).trim();
135+
136+
if (p.waitFor() != 0) {
137+
throw new RuntimeException("Failed to get sdk root, is gcloud sdk installed?");
138+
}
139+
return Paths.get(sdkRoot);
140+
}
141+
139142
private static int getAvailablePort() {
140143
try (ServerSocket serverSocket = new ServerSocket(0)) {
141144
return serverSocket.getLocalPort();

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/env/EmulatorEnv.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class EmulatorEnv implements TestEnv {
3333
private Emulator emulator;
3434

3535
@Override
36-
public void start() throws IOException, InterruptedException, TimeoutException {
36+
public void start() throws Exception {
3737
emulator = Emulator.createGCloud();
3838
emulator.start();
3939

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/env/ProdEnv.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@
4141
* <li>{@code bigtable.instance}
4242
* <li>{@code bigtable.table}
4343
* </ul>
44-
*
45-
* Expects the instance to exist with a table created: cbt -project igorbernstein-dev -instance
46-
* integration-tests createtable my-table cbt -project igorbernstein-dev -instance integration-tests
47-
* createfamily my-table cf
4844
*/
4945
public class ProdEnv implements TestEnv {
5046
private static final String PROJECT_PROPERTY_NAME = "bigtable.project";

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/env/TestEnv.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@
2020
import java.io.IOException;
2121
import java.util.concurrent.TimeoutException;
2222

23+
/**
24+
* Defines the interface of a target environment.
25+
*
26+
* <p>This allows for integration tests to run against either production or an emulator.
27+
*/
2328
public interface TestEnv {
24-
void start() throws IOException, InterruptedException, TimeoutException;
29+
void start() throws Exception;
2530

2631
void stop() throws Exception;
2732

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/it/env/TestEnvRule.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@
1919
import java.util.logging.Logger;
2020
import org.junit.rules.ExternalResource;
2121

22+
/**
23+
* Simple JUnit rule to start and stop the target test environment.
24+
*
25+
* <p>The environment can be specified via the system property {@code bigtable.env}. The choices
26+
* are:
27+
*
28+
* <ul>
29+
* <li>{@code emulator}: uses the cbtemulator component that can be installed by gcloud
30+
* <li>{@code prod}: uses a pre-existing production table. The target table is defined using
31+
* system properties listed in {@link ProdEnv} and application default credentials
32+
* </ul>
33+
*
34+
* <p>By default, {@code emulator} will be used
35+
*/
2236
public class TestEnvRule extends ExternalResource {
2337
private static final Logger LOGGER = Logger.getLogger(TestEnvRule.class.getName());
2438

0 commit comments

Comments
 (0)