Skip to content

Commit f3399e3

Browse files
authored
android-interop-testing: Use java.util.concurrent (#10312)
Instead of the deprecated Android AsyncTask, let's use the standard Java concurrency library with a Callable and an ExecutorService.
1 parent ac8908e commit f3399e3

File tree

4 files changed

+67
-88
lines changed

4 files changed

+67
-88
lines changed

android-interop-testing/src/androidTest/java/io/grpc/android/integrationtest/InteropInstrumentationTest.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
2626
import com.google.android.gms.common.GooglePlayServicesRepairableException;
2727
import com.google.android.gms.security.ProviderInstaller;
28-
import com.google.common.util.concurrent.SettableFuture;
29-
import io.grpc.android.integrationtest.InteropTask.Listener;
3028
import java.io.InputStream;
29+
import java.util.concurrent.ExecutionException;
30+
import java.util.concurrent.ExecutorService;
31+
import java.util.concurrent.Executors;
3132
import java.util.concurrent.TimeUnit;
3233
import org.junit.Before;
3334
import org.junit.Test;
@@ -44,6 +45,7 @@ public class InteropInstrumentationTest {
4445
private String serverHostOverride;
4546
private boolean useTestCa;
4647
private String testCase;
48+
private ExecutorService executor = Executors.newSingleThreadExecutor();
4749

4850
@Before
4951
public void setUp() throws Exception {
@@ -101,26 +103,21 @@ public void interopTests() throws Exception {
101103
}
102104

103105
private void runTest(String testCase) throws Exception {
104-
final SettableFuture<String> resultFuture = SettableFuture.create();
105-
InteropTask.Listener listener =
106-
new Listener() {
107-
@Override
108-
public void onComplete(String result) {
109-
resultFuture.set(result);
110-
}
111-
};
112106
InputStream testCa;
113107
if (useTestCa) {
114108
testCa = ApplicationProvider.getApplicationContext().getResources().openRawResource(R.raw.ca);
115109
} else {
116110
testCa = null;
117111
}
118-
new InteropTask(
119-
listener,
120-
TesterOkHttpChannelBuilder.build(host, port, serverHostOverride, useTls, testCa),
121-
testCase)
122-
.execute();
123-
String result = resultFuture.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
124-
assertEquals(testCase + " failed", InteropTask.SUCCESS_MESSAGE, result);
112+
113+
String result = null;
114+
try {
115+
result = executor.submit(new TestCallable(
116+
TesterOkHttpChannelBuilder.build(host, port, serverHostOverride, useTls, testCa),
117+
testCase)).get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
118+
assertEquals(testCase + " failed", TestCallable.SUCCESS_MESSAGE, result);
119+
} catch (ExecutionException | InterruptedException e) {
120+
result = e.getMessage();
121+
}
125122
}
126123
}

android-interop-testing/src/androidTest/java/io/grpc/android/integrationtest/UdsChannelInteropTest.java

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,22 @@
1616

1717
package io.grpc.android.integrationtest;
1818

19-
import static java.util.concurrent.TimeUnit.SECONDS;
2019
import static org.junit.Assert.assertEquals;
2120

2221
import android.net.LocalSocketAddress.Namespace;
2322
import androidx.test.InstrumentationRegistry;
2423
import androidx.test.ext.junit.runners.AndroidJUnit4;
2524
import androidx.test.rule.ActivityTestRule;
26-
import com.google.common.util.concurrent.SettableFuture;
2725
import io.grpc.Server;
2826
import io.grpc.android.UdsChannelBuilder;
29-
import io.grpc.android.integrationtest.InteropTask.Listener;
3027
import io.grpc.netty.NettyServerBuilder;
3128
import io.grpc.testing.integration.TestServiceImpl;
3229
import java.io.IOException;
30+
import java.util.concurrent.ExecutionException;
31+
import java.util.concurrent.ExecutorService;
3332
import java.util.concurrent.Executors;
3433
import java.util.concurrent.ScheduledExecutorService;
34+
import java.util.concurrent.TimeUnit;
3535
import org.junit.After;
3636
import org.junit.Before;
3737
import org.junit.Rule;
@@ -53,7 +53,8 @@ public class UdsChannelInteropTest {
5353
private Server server;
5454
private UdsTcpEndpointConnector endpointConnector;
5555

56-
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
56+
private ScheduledExecutorService serverExecutor = Executors.newScheduledThreadPool(2);
57+
private ExecutorService testExecutor = Executors.newSingleThreadExecutor();
5758

5859
// Ensures Looper is initialized for tests running on API level 15. Otherwise instantiating an
5960
// AsyncTask throws an exception.
@@ -69,7 +70,7 @@ public void setUp() throws IOException {
6970
server =
7071
NettyServerBuilder.forPort(0)
7172
.maxInboundMessageSize(16 * 1024 * 1024)
72-
.addService(new TestServiceImpl(executor))
73+
.addService(new TestServiceImpl(serverExecutor))
7374
.build();
7475
server.start();
7576

@@ -112,23 +113,16 @@ public void interopTests() throws Exception {
112113
}
113114

114115
private void runTest(String testCase) throws Exception {
115-
final SettableFuture<String> resultFuture = SettableFuture.create();
116-
InteropTask.Listener listener =
117-
new Listener() {
118-
@Override
119-
public void onComplete(String result) {
120-
resultFuture.set(result);
121-
}
122-
};
123-
124-
new InteropTask(
125-
listener,
126-
UdsChannelBuilder.forPath(UDS_PATH, Namespace.ABSTRACT)
127-
.maxInboundMessageSize(16 * 1024 * 1024)
128-
.build(),
129-
testCase)
130-
.execute();
131-
String result = resultFuture.get(TIMEOUT_SECONDS, SECONDS);
132-
assertEquals(testCase + " failed", InteropTask.SUCCESS_MESSAGE, result);
116+
String result = null;
117+
try {
118+
result = testExecutor.submit(new TestCallable(
119+
UdsChannelBuilder.forPath(UDS_PATH, Namespace.ABSTRACT)
120+
.maxInboundMessageSize(16 * 1024 * 1024)
121+
.build(),
122+
testCase)).get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
123+
assertEquals(testCase + " failed", TestCallable.SUCCESS_MESSAGE, result);
124+
} catch (ExecutionException | InterruptedException e) {
125+
result = e.getMessage();
126+
}
133127
}
134128
}

android-interop-testing/src/main/java/io/grpc/android/integrationtest/InteropTask.java renamed to android-interop-testing/src/main/java/io/grpc/android/integrationtest/TestCallable.java

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018 The gRPC Authors
2+
* Copyright 2023 The gRPC Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,49 +16,36 @@
1616

1717
package io.grpc.android.integrationtest;
1818

19-
import android.os.AsyncTask;
2019
import android.util.Log;
2120
import io.grpc.ManagedChannel;
2221
import io.grpc.ManagedChannelBuilder;
2322
import io.grpc.testing.integration.AbstractInteropTest;
2423
import java.io.PrintWriter;
2524
import java.io.StringWriter;
26-
import java.lang.ref.WeakReference;
25+
import java.util.concurrent.Callable;
2726
import org.junit.AssumptionViolatedException;
2827

29-
/** AsyncTask for interop test cases. */
30-
final class InteropTask extends AsyncTask<Void, Void, String> {
31-
private static final String LOG_TAG = "GrpcInteropTask";
32-
33-
interface Listener {
34-
void onComplete(String result);
35-
}
28+
/**
29+
* Used to run a single test case against a channel in a separate thread.
30+
*/
31+
public class TestCallable implements Callable<String> {
32+
private final ManagedChannel channel;
33+
private final String testCase;
3634

35+
private static final String LOG_TAG = "GrpcInteropTask";
3736
static final String SUCCESS_MESSAGE = "Success!";
3837

39-
private final WeakReference<Listener> listenerReference;
40-
private final String testCase;
41-
private final Tester tester;
42-
43-
InteropTask(
44-
Listener listener,
45-
ManagedChannel channel,
46-
String testCase) {
47-
this.listenerReference = new WeakReference<Listener>(listener);
38+
public TestCallable(ManagedChannel channel, String testCase) {
39+
this.channel = channel;
4840
this.testCase = testCase;
49-
this.tester = new Tester(channel);
5041
}
5142

5243
@Override
53-
protected void onPreExecute() {
44+
public String call() {
45+
Tester tester = new Tester(channel);
5446
tester.setUp();
55-
}
56-
57-
@SuppressWarnings("Finally")
58-
@Override
59-
protected String doInBackground(Void... ignored) {
6047
try {
61-
runTest(testCase);
48+
runTest(tester, testCase);
6249
return SUCCESS_MESSAGE;
6350
} catch (Throwable t) {
6451
// Print the stack trace to logcat.
@@ -78,7 +65,7 @@ protected String doInBackground(Void... ignored) {
7865
}
7966
}
8067

81-
private void runTest(String testCase) throws Exception {
68+
private void runTest(Tester tester, String testCase) throws Exception {
8269
Log.i(LOG_TAG, "Running test case: " + testCase);
8370
if ("empty_unary".equals(testCase)) {
8471
tester.emptyUnary();
@@ -138,14 +125,6 @@ private void runTest(String testCase) throws Exception {
138125
}
139126
}
140127

141-
@Override
142-
protected void onPostExecute(String result) {
143-
Listener listener = listenerReference.get();
144-
if (listener != null) {
145-
listener.onComplete(result);
146-
}
147-
}
148-
149128
private static class Tester extends AbstractInteropTest {
150129

151130
private Tester(ManagedChannel channel) {

android-interop-testing/src/main/java/io/grpc/android/integrationtest/TesterActivity.java

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@
3636
import java.io.InputStream;
3737
import java.util.ArrayList;
3838
import java.util.List;
39+
import java.util.concurrent.ExecutionException;
40+
import java.util.concurrent.ExecutorService;
41+
import java.util.concurrent.Executors;
3942

4043
public class TesterActivity extends AppCompatActivity
41-
implements ProviderInstaller.ProviderInstallListener, InteropTask.Listener {
44+
implements ProviderInstaller.ProviderInstallListener {
4245
private static final String LOG_TAG = "GrpcTesterActivity";
4346

4447
private List<Button> buttons;
@@ -51,6 +54,8 @@ public class TesterActivity extends AppCompatActivity
5154

5255
private UdsTcpEndpointConnector endpointConnector;
5356

57+
private ExecutorService executor;
58+
5459
@Override
5560
protected void onCreate(Bundle savedInstanceState) {
5661
super.onCreate(savedInstanceState);
@@ -72,6 +77,8 @@ protected void onCreate(Bundle savedInstanceState) {
7277
ProviderInstaller.installIfNeededAsync(this, this);
7378
// Disable buttons until the security provider installing finishes.
7479
enableButtons(false);
80+
81+
executor = Executors.newSingleThreadExecutor();
7582
}
7683

7784
/** Click handler for unix domain socket. */
@@ -110,16 +117,6 @@ private void enableButtons(boolean enable) {
110117
}
111118
}
112119

113-
@Override
114-
public void onComplete(String result) {
115-
if (endpointConnector != null) {
116-
endpointConnector.shutDown();
117-
endpointConnector = null;
118-
}
119-
resultText.setText(result);
120-
enableButtons(true);
121-
}
122-
123120
private void startTest(String testCase) {
124121
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
125122
hostEdit.getWindowToken(), 0);
@@ -162,7 +159,19 @@ private void startTest(String testCase) {
162159
}
163160

164161
// Start Test.
165-
new InteropTask(TesterActivity.this, channel, testCase).execute();
162+
String result = null;
163+
try {
164+
result = executor.submit(new TestCallable(channel, testCase)).get();
165+
} catch (ExecutionException | InterruptedException e) {
166+
result = e.getMessage();
167+
} finally {
168+
if (endpointConnector != null) {
169+
endpointConnector.shutDown();
170+
endpointConnector = null;
171+
}
172+
resultText.setText(result);
173+
enableButtons(true);
174+
}
166175
}
167176

168177
@Override

0 commit comments

Comments
 (0)