Skip to content

Commit 4560bcb

Browse files
committed
chore: reduce test time by skipping mtls
The Google Auth libraries have added support for mtls. A check for what type of MtlsProvider is available is executed multiple times every time a Spanner client is created, and this check is relatively expensive. This causes all mock server tests to become slow. This change introduces a temporary hack to work around this, until we have a solution in the auth libraries that allow us to turn off this feature during tests that do not care about mtls.
1 parent 7d752d6 commit 4560bcb

27 files changed

+202
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.auth.mtls;
18+
19+
import java.io.IOException;
20+
import java.util.concurrent.atomic.AtomicBoolean;
21+
22+
// TODO: Remove once the actual implementation of this class in the auth library has a config
23+
// option that allows us to skip the most expensive code paths during tests.
24+
public class DefaultMtlsProviderFactory {
25+
public static final AtomicBoolean SKIP_MTLS = new AtomicBoolean(false);
26+
27+
public static MtlsProvider create() throws IOException {
28+
if (SKIP_MTLS.get()) {
29+
return null;
30+
}
31+
// Note: The caller should handle CertificateSourceUnavailableException gracefully, since
32+
// it is an expected error case. All other IOExceptions are unexpected and should be surfaced
33+
// up the call stack.
34+
MtlsProvider mtlsProvider = new X509Provider();
35+
if (mtlsProvider.isAvailable()) {
36+
return mtlsProvider;
37+
}
38+
mtlsProvider = new SecureConnectProvider();
39+
if (mtlsProvider.isAvailable()) {
40+
return mtlsProvider;
41+
}
42+
throw new CertificateSourceUnavailableException(
43+
"No Certificate Source is available on this device.");
44+
}
45+
}

google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractAsyncTransactionTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import static com.google.cloud.spanner.MockSpannerTestUtil.UPDATE_COUNT;
3131
import static com.google.cloud.spanner.MockSpannerTestUtil.UPDATE_STATEMENT;
3232

33+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
3334
import com.google.cloud.NoCredentials;
3435
import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
3536
import io.grpc.ManagedChannelBuilder;
@@ -54,8 +55,12 @@ public abstract class AbstractAsyncTransactionTest {
5455
Spanner spanner;
5556
Spanner spannerWithEmptySessionPool;
5657

58+
private static boolean originalSkipMtls;
59+
5760
@BeforeClass
5861
public static void setup() throws Exception {
62+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
63+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
5964
mockSpanner = new MockSpannerServiceImpl();
6065
mockSpanner.setAbortProbability(0.0D);
6166
mockSpanner.putStatementResult(
@@ -85,6 +90,7 @@ public static void teardown() throws Exception {
8590
server.shutdown();
8691
server.awaitTermination();
8792
executor.shutdown();
93+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
8894
}
8995

9096
@Before

google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractMockServerTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.cloud.spanner;
1818

1919
import com.google.api.gax.grpc.testing.LocalChannelProvider;
20+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
2021
import com.google.cloud.NoCredentials;
2122
import com.google.cloud.spanner.admin.database.v1.MockDatabaseAdminImpl;
2223
import com.google.cloud.spanner.admin.instance.v1.MockInstanceAdminImpl;
@@ -48,8 +49,12 @@ abstract class AbstractMockServerTest {
4849

4950
protected Spanner spanner;
5051

52+
private static boolean originalSkipMtls;
53+
5154
@BeforeClass
5255
public static void startMockServer() throws IOException {
56+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
57+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
5358
mockSpanner = new MockSpannerServiceImpl();
5459
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
5560
mockInstanceAdmin = new MockInstanceAdminImpl();
@@ -93,6 +98,7 @@ public void getOperation(
9398
public static void stopMockServer() throws InterruptedException {
9499
server.shutdown();
95100
server.awaitTermination();
101+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
96102
}
97103

98104
@Before

google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractNettyMockServerTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.cloud.spanner;
1818

1919
import com.google.api.gax.grpc.testing.LocalChannelProvider;
20+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
2021
import com.google.cloud.NoCredentials;
2122
import io.grpc.ForwardingServerCall;
2223
import io.grpc.ManagedChannelBuilder;
@@ -51,8 +52,12 @@ abstract class AbstractNettyMockServerTest {
5152

5253
protected Spanner spanner;
5354

55+
private static boolean originalSkipMtls;
56+
5457
@BeforeClass
5558
public static void startMockServer() throws IOException {
59+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
60+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
5661
mockSpanner = new MockSpannerServiceImpl();
5762
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
5863

@@ -93,6 +98,7 @@ public static void stopMockServer() throws InterruptedException {
9398
server.shutdown();
9499
server.awaitTermination();
95100
executor.shutdown();
101+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
96102
}
97103

98104
@Before

google-cloud-spanner/src/test/java/com/google/cloud/spanner/BackendExhaustedTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020

2121
import com.google.api.gax.grpc.testing.LocalChannelProvider;
22+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
2223
import com.google.cloud.NoCredentials;
2324
import com.google.cloud.grpc.GrpcTransportOptions;
2425
import com.google.cloud.grpc.GrpcTransportOptions.ExecutorFactory;
@@ -88,8 +89,12 @@ public class BackendExhaustedTest {
8889
private Spanner spanner;
8990
private DatabaseClientImpl client;
9091

92+
private static boolean originalSkipMtls;
93+
9194
@BeforeClass
9295
public static void startStaticServer() throws IOException {
96+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
97+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
9398
mockSpanner = new MockSpannerServiceImpl();
9499
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
95100
mockSpanner.putStatementResult(StatementResult.update(UPDATE_STATEMENT, UPDATE_COUNT));
@@ -115,6 +120,7 @@ public static void stopServer() throws InterruptedException {
115120
// Force a shutdown as there are still requests stuck in the server.
116121
server.shutdownNow();
117122
server.awaitTermination();
123+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
118124
}
119125

120126
@Before

google-cloud-spanner/src/test/java/com/google/cloud/spanner/BatchCreateSessionsSlowTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import static org.junit.Assume.assumeFalse;
2424

2525
import com.google.api.gax.grpc.testing.LocalChannelProvider;
26+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
2627
import com.google.cloud.NoCredentials;
2728
import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime;
2829
import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
@@ -58,8 +59,12 @@ public class BatchCreateSessionsSlowTest {
5859
private static LocalChannelProvider channelProvider;
5960
private Spanner spanner;
6061

62+
private static boolean originalSkipMtls;
63+
6164
@BeforeClass
6265
public static void startStaticServer() throws IOException {
66+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
67+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
6368
mockSpanner = new MockSpannerServiceImpl();
6469
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
6570
mockSpanner.putStatementResult(
@@ -82,6 +87,7 @@ public static void startStaticServer() throws IOException {
8287
public static void stopServer() throws InterruptedException {
8388
server.shutdown();
8489
server.awaitTermination();
90+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
8591
}
8692

8793
@Before

google-cloud-spanner/src/test/java/com/google/cloud/spanner/BatchCreateSessionsTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.hamcrest.MatcherAssert.assertThat;
2222

2323
import com.google.api.gax.grpc.testing.LocalChannelProvider;
24+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
2425
import com.google.cloud.NoCredentials;
2526
import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime;
2627
import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
@@ -77,8 +78,12 @@ public class BatchCreateSessionsTest {
7778
private static Server server;
7879
private static LocalChannelProvider channelProvider;
7980

81+
private static boolean originalSkipMtls;
82+
8083
@BeforeClass
8184
public static void startStaticServer() throws IOException {
85+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
86+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
8287
mockSpanner = new MockSpannerServiceImpl();
8388
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
8489
mockSpanner.putStatementResult(StatementResult.query(SELECT1AND2, SELECT1_RESULTSET));
@@ -97,6 +102,7 @@ public static void startStaticServer() throws IOException {
97102
public static void stopServer() throws InterruptedException {
98103
server.shutdown();
99104
server.awaitTermination();
105+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
100106
}
101107

102108
@Before

google-cloud-spanner/src/test/java/com/google/cloud/spanner/ChannelUsageTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static org.junit.Assert.assertTrue;
2222
import static org.junit.Assume.assumeFalse;
2323

24+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
2425
import com.google.cloud.NoCredentials;
2526
import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
2627
import com.google.common.util.concurrent.ListeningExecutorService;
@@ -112,8 +113,12 @@ public static Collection<Object[]> data() {
112113

113114
private static Level originalLogLevel;
114115

116+
private static boolean originalSkipMtls;
117+
115118
@BeforeClass
116119
public static void startServer() throws IOException {
120+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
121+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
117122
mockSpanner = new MockSpannerServiceImpl();
118123
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
119124
mockSpanner.putStatementResult(StatementResult.query(SELECT1, SELECT1_RESULTSET));
@@ -166,6 +171,7 @@ public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
166171
public static void stopServer() throws InterruptedException {
167172
server.shutdown();
168173
server.awaitTermination();
174+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
169175
}
170176

171177
@BeforeClass

google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import com.google.api.gax.rpc.ApiCallContext;
4747
import com.google.api.gax.rpc.ServerStream;
4848
import com.google.api.gax.rpc.StatusCode;
49+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
4950
import com.google.cloud.ByteArray;
5051
import com.google.cloud.NoCredentials;
5152
import com.google.cloud.Timestamp;
@@ -208,8 +209,12 @@ public class DatabaseClientImplTest {
208209
private Spanner spannerWithEmptySessionPool;
209210
private static ExecutorService executor;
210211

212+
private static boolean originalSkipMtls;
213+
211214
@BeforeClass
212215
public static void startStaticServer() throws IOException {
216+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
217+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
213218
mockSpanner = new MockSpannerServiceImpl();
214219
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
215220
mockSpanner.putStatementResult(StatementResult.update(UPDATE_STATEMENT, UPDATE_COUNT));
@@ -262,6 +267,7 @@ public static void stopServer() throws InterruptedException {
262267
server.shutdown();
263268
server.awaitTermination();
264269
executor.shutdown();
270+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
265271
}
266272

267273
@Before

google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplWithDefaultRWTransactionOptionsTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static org.junit.Assert.assertTrue;
2626

2727
import com.google.api.gax.grpc.testing.LocalChannelProvider;
28+
import com.google.auth.mtls.DefaultMtlsProviderFactory;
2829
import com.google.cloud.NoCredentials;
2930
import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
3031
import com.google.cloud.spanner.Options.RpcPriority;
@@ -82,8 +83,12 @@ public class DatabaseClientImplWithDefaultRWTransactionOptionsTest {
8283
private DatabaseClient clientWithSerializableOption;
8384
private DatabaseClient clientWithSerOptimisticOption;
8485

86+
private static boolean originalSkipMtls;
87+
8588
@BeforeClass
8689
public static void startStaticServer() throws IOException {
90+
originalSkipMtls = DefaultMtlsProviderFactory.SKIP_MTLS.get();
91+
DefaultMtlsProviderFactory.SKIP_MTLS.set(true);
8792
mockSpanner = new MockSpannerServiceImpl();
8893
mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
8994
mockSpanner.putStatementResult(StatementResult.update(UPDATE_STATEMENT, UPDATE_COUNT));
@@ -112,6 +117,7 @@ public static void startStaticServer() throws IOException {
112117
public static void stopServer() throws InterruptedException {
113118
server.shutdown();
114119
server.awaitTermination();
120+
DefaultMtlsProviderFactory.SKIP_MTLS.set(originalSkipMtls);
115121
}
116122

117123
@Before

0 commit comments

Comments
 (0)