Skip to content

Commit 2927478

Browse files
committed
pr comments
raises exception if we cannot stop the emulator.
1 parent 55a7d1a commit 2927478

File tree

9 files changed

+88
-37
lines changed

9 files changed

+88
-37
lines changed

google-cloud-core/src/main/java/com/google/cloud/testing/BaseEmulatorHelper.java

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.google.cloud.ServiceOptions;
2020
import com.google.common.io.CharStreams;
21+
import com.google.common.util.concurrent.SettableFuture;
2122

2223
import java.io.BufferedInputStream;
2324
import java.io.BufferedOutputStream;
@@ -43,10 +44,14 @@
4344
import java.util.List;
4445
import java.util.Locale;
4546
import java.util.Map;
47+
import java.util.concurrent.ExecutionException;
48+
import java.util.concurrent.TimeUnit;
49+
import java.util.concurrent.TimeoutException;
4650
import java.util.logging.Level;
4751
import java.util.logging.Logger;
4852
import java.util.zip.ZipEntry;
4953
import java.util.zip.ZipInputStream;
54+
import org.joda.time.Duration;
5055

5156
/**
5257
* Utility class to start and stop a local service which is used by unit testing.
@@ -107,14 +112,47 @@ protected final void startProcess(String blockUntilOutput)
107112
* Waits for the local service's subprocess to terminate,
108113
* and stop any possible thread listening for its output.
109114
*/
110-
protected final void waitForProcess() throws IOException, InterruptedException {
115+
protected final int waitForProcess(Duration timeout) throws IOException, InterruptedException, TimeoutException {
111116
if (blockingProcessReader != null) {
112117
blockingProcessReader.terminate();
113118
blockingProcessReader = null;
114119
}
115120
if (activeRunner != null) {
116-
activeRunner.waitFor();
121+
int exitCode = activeRunner.waitFor(timeout);
117122
activeRunner = null;
123+
return exitCode;
124+
}
125+
return 0;
126+
}
127+
128+
private static int waitForProcess(final Process process, Duration timeout) throws InterruptedException, TimeoutException {
129+
if (process == null) {
130+
return 0;
131+
}
132+
133+
final SettableFuture<Integer> exitValue = SettableFuture.create();
134+
135+
Thread waiter = new Thread(new Runnable() {
136+
@Override
137+
public void run() {
138+
try {
139+
exitValue.set(process.waitFor());
140+
} catch (InterruptedException e) {
141+
exitValue.setException(e);
142+
}
143+
}
144+
});
145+
waiter.run();
146+
147+
try {
148+
return exitValue.get(timeout.getMillis(), TimeUnit.MILLISECONDS);
149+
} catch (ExecutionException e) {
150+
if (e.getCause() instanceof InterruptedException) {
151+
throw (InterruptedException) e.getCause();
152+
}
153+
throw new RuntimeException(e);
154+
} finally {
155+
waiter.interrupt();
118156
}
119157
}
120158

@@ -145,7 +183,7 @@ public String getProjectId() {
145183
/**
146184
* Stops the local emulator.
147185
*/
148-
public abstract void stop() throws IOException, InterruptedException;
186+
public abstract void stop(Duration timeout) throws IOException, InterruptedException, TimeoutException;
149187

150188
/**
151189
* Resets the internal state of the emulator.
@@ -196,9 +234,10 @@ protected interface EmulatorRunner {
196234
void start() throws IOException;
197235

198236
/**
199-
* Wait for the emulator associated to this runner to terminate.
237+
* Wait for the emulator associated to this runner to terminate,
238+
* returning the exit status.
200239
*/
201-
void waitFor() throws InterruptedException;
240+
int waitFor(Duration timeout) throws InterruptedException, TimeoutException;
202241

203242
/**
204243
* Returns the process associated to the emulator, if any.
@@ -240,10 +279,8 @@ public void start() throws IOException {
240279
}
241280

242281
@Override
243-
public void waitFor() throws InterruptedException {
244-
if (process != null) {
245-
process.waitFor();
246-
}
282+
public int waitFor(Duration timeout) throws InterruptedException, TimeoutException {
283+
return waitForProcess(process, timeout);
247284
}
248285

249286
@Override
@@ -337,10 +374,8 @@ public void start() throws IOException {
337374
}
338375

339376
@Override
340-
public void waitFor() throws InterruptedException {
341-
if (process != null) {
342-
process.waitFor();
343-
}
377+
public int waitFor(Duration timeout) throws InterruptedException, TimeoutException {
378+
return waitForProcess(process, timeout);
344379
}
345380

346381
@Override

google-cloud-core/src/test/java/com/google/cloud/testing/BaseEmulatorHelperTest.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
import com.google.common.collect.ImmutableList;
2323

2424
import org.easymock.EasyMock;
25+
import org.joda.time.Duration;
2526
import org.junit.Test;
2627

2728
import java.io.ByteArrayInputStream;
2829
import java.io.IOException;
2930
import java.io.InputStream;
3031
import java.util.List;
32+
import java.util.concurrent.TimeoutException;
3133
import java.util.logging.Logger;
3234

3335
public class BaseEmulatorHelperTest {
@@ -66,8 +68,8 @@ public void start() throws IOException, InterruptedException {
6668
}
6769

6870
@Override
69-
public void stop() throws IOException, InterruptedException {
70-
waitForProcess();
71+
public void stop(Duration timeout) throws IOException, InterruptedException, TimeoutException {
72+
waitForProcess(timeout);
7173
}
7274

7375
@Override
@@ -77,7 +79,7 @@ public void reset() throws IOException {
7779
}
7880

7981
@Test
80-
public void testEmulatorHelper() throws IOException, InterruptedException {
82+
public void testEmulatorHelper() throws IOException, InterruptedException, TimeoutException {
8183
Process process = EasyMock.createStrictMock(Process.class);
8284
InputStream stream = new ByteArrayInputStream(BLOCK_UNTIL.getBytes(Charsets.UTF_8));
8385
EmulatorRunner emulatorRunner = EasyMock.createStrictMock(EmulatorRunner.class);
@@ -86,18 +88,18 @@ public void testEmulatorHelper() throws IOException, InterruptedException {
8688
emulatorRunner.start();
8789
EasyMock.expectLastCall();
8890
EasyMock.expect(emulatorRunner.getProcess()).andReturn(process);
89-
emulatorRunner.waitFor();
90-
EasyMock.expectLastCall();
91+
emulatorRunner.waitFor(Duration.standardMinutes(1));
92+
EasyMock.expectLastCall().andReturn(0);
9193
EasyMock.replay(process, emulatorRunner);
9294
TestEmulatorHelper helper =
9395
new TestEmulatorHelper(ImmutableList.of(emulatorRunner), BLOCK_UNTIL);
9496
helper.start();
95-
helper.stop();
97+
helper.stop(Duration.standardMinutes(1));
9698
EasyMock.verify();
9799
}
98100

99101
@Test
100-
public void testEmulatorHelperMultipleRunners() throws IOException, InterruptedException {
102+
public void testEmulatorHelperMultipleRunners() throws IOException, InterruptedException, TimeoutException {
101103
Process process = EasyMock.createStrictMock(Process.class);
102104
InputStream stream = new ByteArrayInputStream(BLOCK_UNTIL.getBytes(Charsets.UTF_8));
103105
EmulatorRunner firstRunner = EasyMock.createStrictMock(EmulatorRunner.class);
@@ -108,13 +110,13 @@ public void testEmulatorHelperMultipleRunners() throws IOException, InterruptedE
108110
secondRunner.start();
109111
EasyMock.expectLastCall();
110112
EasyMock.expect(secondRunner.getProcess()).andReturn(process);
111-
secondRunner.waitFor();
112-
EasyMock.expectLastCall();
113+
secondRunner.waitFor(Duration.standardMinutes(1));
114+
EasyMock.expectLastCall().andReturn(0);
113115
EasyMock.replay(process, secondRunner);
114116
TestEmulatorHelper helper =
115117
new TestEmulatorHelper(ImmutableList.of(firstRunner, secondRunner), BLOCK_UNTIL);
116118
helper.start();
117-
helper.stop();
119+
helper.stop(Duration.standardMinutes(1));
118120
EasyMock.verify();
119121
}
120122
}

google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/LocalDatastoreHelper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import com.google.cloud.testing.BaseEmulatorHelper;
2323
import com.google.common.collect.ImmutableList;
2424

25+
import org.joda.time.Duration;
26+
2527
import java.io.IOException;
2628
import java.net.MalformedURLException;
2729
import java.net.URL;
@@ -34,6 +36,7 @@
3436
import java.util.Arrays;
3537
import java.util.List;
3638
import java.util.UUID;
39+
import java.util.concurrent.TimeoutException;
3740
import java.util.logging.Level;
3841
import java.util.logging.Logger;
3942

@@ -225,9 +228,9 @@ public void reset() throws IOException {
225228
/**
226229
* Stops the Datastore emulator.
227230
*/
228-
public void stop() throws IOException, InterruptedException {
231+
public void stop(Duration timeout) throws IOException, InterruptedException, TimeoutException {
229232
sendPostRequest("/shutdown");
230-
waitForProcess();
233+
waitForProcess(timeout);
231234
deleteRecursively(gcdPath);
232235
}
233236

google-cloud-datastore/src/test/java/com/google/cloud/datastore/DatastoreTest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,15 @@
4747
import com.google.protobuf.ByteString;
4848

4949
import org.easymock.EasyMock;
50+
import org.joda.time.Duration;
5051
import org.junit.AfterClass;
5152
import org.junit.Before;
5253
import org.junit.BeforeClass;
5354
import org.junit.Rule;
54-
import org.junit.Test;
5555
import org.junit.rules.ExpectedException;
5656
import org.junit.runner.RunWith;
5757
import org.junit.runners.JUnit4;
58+
import org.junit.Test;
5859

5960
import java.io.IOException;
6061
import java.util.ArrayList;
@@ -63,6 +64,7 @@
6364
import java.util.Iterator;
6465
import java.util.List;
6566
import java.util.Set;
67+
import java.util.concurrent.TimeoutException;
6668

6769
@RunWith(JUnit4.class)
6870
public class DatastoreTest {
@@ -150,8 +152,8 @@ public void setUp() {
150152
}
151153

152154
@AfterClass
153-
public static void afterClass() throws IOException, InterruptedException {
154-
helper.stop();
155+
public static void afterClass() throws IOException, InterruptedException, TimeoutException {
156+
helper.stop(Duration.standardMinutes(1));
155157
}
156158

157159
@Test

google-cloud-datastore/src/test/java/com/google/cloud/datastore/testing/LocalDatastoreHelperTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@
2929
import com.google.cloud.datastore.Entity;
3030
import com.google.cloud.datastore.Key;
3131

32+
import org.joda.time.Duration;
3233
import org.junit.Rule;
3334
import org.junit.Test;
3435
import org.junit.rules.ExpectedException;
3536
import org.junit.runner.RunWith;
3637
import org.junit.runners.JUnit4;
3738

3839
import java.io.IOException;
40+
import java.util.concurrent.TimeoutException;
3941

4042
@RunWith(JUnit4.class)
4143
public class LocalDatastoreHelperTest {
@@ -82,7 +84,7 @@ public void testOptions() {
8284
}
8385

8486
@Test
85-
public void testStartStopReset() throws IOException, InterruptedException {
87+
public void testStartStopReset() throws IOException, InterruptedException, TimeoutException {
8688
LocalDatastoreHelper helper = LocalDatastoreHelper.create();
8789
helper.start();
8890
Datastore datastore = helper.getOptions().getService();
@@ -91,7 +93,7 @@ public void testStartStopReset() throws IOException, InterruptedException {
9193
assertNotNull(datastore.get(key));
9294
helper.reset();
9395
assertNull(datastore.get(key));
94-
helper.stop();
96+
helper.stop(Duration.standardMinutes(1));
9597
thrown.expect(DatastoreException.class);
9698
datastore.get(key);
9799
}

google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/testing/LocalPubSubHelper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@
3333
import java.util.Arrays;
3434
import java.util.List;
3535
import java.util.UUID;
36+
import java.util.concurrent.TimeoutException;
3637
import java.util.logging.Logger;
3738

39+
import org.joda.time.Duration;
40+
3841
/**
3942
* A class that runs a Pubsub emulator instance for use in tests.
4043
*/
@@ -144,8 +147,8 @@ public void reset() throws IOException {
144147
* Stops the PubSub emulator and related local service.
145148
*/
146149
@Override
147-
public void stop() throws IOException, InterruptedException {
150+
public void stop(Duration timeout) throws IOException, InterruptedException, TimeoutException {
148151
sendPostRequest("/shutdown");
149-
waitForProcess();
152+
waitForProcess(timeout);
150153
}
151154
}

google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/LocalSystemTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.google.cloud.pubsub.testing.LocalPubSubHelper;
2020

21+
import org.joda.time.Duration;
2122
import org.junit.AfterClass;
2223
import org.junit.BeforeClass;
2324

@@ -49,6 +50,6 @@ public static void startServer() throws IOException, InterruptedException {
4950
public static void stopServer() throws Exception {
5051
pubsub.close();
5152
pubsubHelper.reset();
52-
pubsubHelper.stop();
53+
pubsubHelper.stop(Duration.standardMinutes(1));
5354
}
5455
}

google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/spi/v1/PublisherClientTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.ArrayList;
4141
import java.util.Collections;
4242
import java.util.List;
43+
import java.util.concurrent.TimeoutException;
4344

4445
public class PublisherClientTest {
4546
private static LocalPubSubHelper pubsubHelper;
@@ -55,8 +56,8 @@ public static void startServer() throws IOException, InterruptedException {
5556
}
5657

5758
@AfterClass
58-
public static void stopServer() throws IOException, InterruptedException {
59-
pubsubHelper.stop();
59+
public static void stopServer() throws IOException, InterruptedException, TimeoutException {
60+
pubsubHelper.stop(Duration.standardMinutes(1));
6061
}
6162

6263
@Before

google-cloud-pubsub/src/test/java/com/google/cloud/pubsub/testing/LocalPubSubHelperTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
import com.google.cloud.pubsub.PubSubOptions;
2828
import com.google.cloud.pubsub.TopicInfo;
2929

30+
import org.joda.time.Duration;
3031
import org.junit.Rule;
3132
import org.junit.Test;
3233
import org.junit.rules.ExpectedException;
3334

3435
import java.io.IOException;
36+
import java.util.concurrent.TimeoutException;
3537

3638
public class LocalPubSubHelperTest {
3739

@@ -57,15 +59,15 @@ public void testOptions() {
5759
}
5860

5961
@Test
60-
public void testStartStopReset() throws IOException, InterruptedException {
62+
public void testStartStopReset() throws IOException, InterruptedException, TimeoutException {
6163
LocalPubSubHelper helper = LocalPubSubHelper.create();
6264
helper.start();
6365
PubSub pubsub = helper.getOptions().getService();
6466
pubsub.create(TopicInfo.of(TOPIC));
6567
assertNotNull(pubsub.getTopic(TOPIC));
6668
helper.reset();
6769
assertNull(pubsub.getTopic(TOPIC));
68-
helper.stop();
70+
helper.stop(Duration.standardMinutes(1));
6971
thrown.expect(PubSubException.class);
7072
pubsub.getTopic(TOPIC);
7173
}

0 commit comments

Comments
 (0)