Skip to content
This repository was archived by the owner on Apr 7, 2026. It is now read-only.

Commit 4bab789

Browse files
committed
test: add tests for location API
1 parent a4fb7f8 commit 4bab789

4 files changed

Lines changed: 162 additions & 4 deletions

File tree

google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java

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

1919
import static com.google.api.gax.util.TimeConversionUtils.toJavaTimeDuration;
2020
import static com.google.api.gax.util.TimeConversionUtils.toThreetenDuration;
21+
import static com.google.cloud.spanner.spi.v1.GapicSpannerRpc.EXPERIMENTAL_LOCATION_API_ENV_VAR;
2122

2223
import com.google.api.core.ApiFunction;
2324
import com.google.api.core.BetaApi;
@@ -257,6 +258,7 @@ public static GcpChannelPoolOptions createDefaultDynamicChannelPoolOptions() {
257258
private final OpenTelemetry openTelemetry;
258259
private final boolean enableApiTracing;
259260
private final boolean enableBuiltInMetrics;
261+
private final boolean enableLocationApi;
260262
private final boolean enableExtendedTracing;
261263
private final boolean enableEndToEndTracing;
262264
private final String monitoringHost;
@@ -926,6 +928,7 @@ protected SpannerOptions(Builder builder) {
926928
} else {
927929
enableBuiltInMetrics = builder.enableBuiltInMetrics;
928930
}
931+
enableLocationApi = builder.enableLocationApi;
929932
enableEndToEndTracing = builder.enableEndToEndTracing;
930933
monitoringHost = builder.monitoringHost;
931934
defaultTransactionOptions = builder.defaultTransactionOptions;
@@ -993,6 +996,10 @@ default boolean isEnableEndToEndTracing() {
993996
return false;
994997
}
995998

999+
default boolean isEnableLocationApi() {
1000+
return false;
1001+
}
1002+
9961003
@Deprecated
9971004
@ObsoleteApi(
9981005
"This will be removed in an upcoming version without a major version bump. You should use"
@@ -1084,6 +1091,11 @@ public boolean isEnableEndToEndTracing() {
10841091
return Boolean.parseBoolean(System.getenv(SPANNER_ENABLE_END_TO_END_TRACING));
10851092
}
10861093

1094+
@Override
1095+
public boolean isEnableLocationApi() {
1096+
return Boolean.parseBoolean(System.getenv(EXPERIMENTAL_LOCATION_API_ENV_VAR));
1097+
}
1098+
10871099
@Override
10881100
public String getMonitoringHost() {
10891101
return System.getenv(SPANNER_MONITORING_HOST);
@@ -1164,6 +1176,7 @@ public static class Builder
11641176
private boolean enableExtendedTracing = SpannerOptions.environment.isEnableExtendedTracing();
11651177
private boolean enableEndToEndTracing = SpannerOptions.environment.isEnableEndToEndTracing();
11661178
private boolean enableBuiltInMetrics = SpannerOptions.environment.isEnableBuiltInMetrics();
1179+
private boolean enableLocationApi = SpannerOptions.environment.isEnableLocationApi();
11671180
private String monitoringHost = SpannerOptions.environment.getMonitoringHost();
11681181
private SslContext mTLSContext = null;
11691182
private String experimentalHost = null;
@@ -1270,6 +1283,7 @@ protected Builder() {
12701283
this.enableApiTracing = options.enableApiTracing;
12711284
this.enableExtendedTracing = options.enableExtendedTracing;
12721285
this.enableBuiltInMetrics = options.enableBuiltInMetrics;
1286+
this.enableLocationApi = options.enableLocationApi;
12731287
this.enableEndToEndTracing = options.enableEndToEndTracing;
12741288
this.monitoringHost = options.monitoringHost;
12751289
this.defaultTransactionOptions = options.defaultTransactionOptions;
@@ -2434,6 +2448,11 @@ public boolean isEnableBuiltInMetrics() {
24342448
return enableBuiltInMetrics;
24352449
}
24362450

2451+
@InternalApi
2452+
public boolean isEnableLocationApi() {
2453+
return enableLocationApi;
2454+
}
2455+
24372456
/** Returns the override metrics Host. */
24382457
String getMonitoringHost() {
24392458
return monitoringHost;

google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@
226226
public class GapicSpannerRpc implements SpannerRpc {
227227
private static final PathTemplate PROJECT_NAME_TEMPLATE =
228228
PathTemplate.create("projects/{project}");
229-
private static final String EXPERIMENTAL_LOCATION_API_ENV_VAR =
229+
public static final String EXPERIMENTAL_LOCATION_API_ENV_VAR =
230230
"GOOGLE_SPANNER_EXPERIMENTAL_LOCATION_API";
231231
private static final PathTemplate OPERATION_NAME_TEMPLATE =
232232
PathTemplate.create("{database=projects/*/instances/*/databases/*}/operations/{operation}");
@@ -399,8 +399,7 @@ public GapicSpannerRpc(final SpannerOptions options) {
399399
// If it is enabled in options uses the channel pool provided by the gRPC-GCP extension.
400400
maybeEnableGrpcGcpExtension(defaultChannelProviderBuilder, options);
401401

402-
boolean enableLocationApi =
403-
Boolean.parseBoolean(System.getenv(EXPERIMENTAL_LOCATION_API_ENV_VAR));
402+
boolean enableLocationApi = options.isEnableLocationApi();
404403
TransportChannelProvider baseChannelProvider =
405404
MoreObjects.firstNonNull(
406405
options.getChannelProvider(), defaultChannelProviderBuilder.build());
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright 2026 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.cloud.spanner;
18+
19+
import static org.junit.Assert.assertEquals;
20+
21+
import com.google.cloud.NoCredentials;
22+
import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult;
23+
import com.google.cloud.spanner.connection.AbstractMockServerTest;
24+
import com.google.cloud.spanner.connection.RandomResultSetGenerator;
25+
import com.google.common.util.concurrent.Futures;
26+
import com.google.common.util.concurrent.ListenableFuture;
27+
import com.google.common.util.concurrent.ListeningExecutorService;
28+
import com.google.common.util.concurrent.MoreExecutors;
29+
import io.grpc.ManagedChannelBuilder;
30+
import java.util.ArrayList;
31+
import java.util.List;
32+
import java.util.concurrent.Executors;
33+
import java.util.concurrent.ThreadLocalRandom;
34+
import org.junit.AfterClass;
35+
import org.junit.BeforeClass;
36+
import org.junit.Test;
37+
import org.junit.runner.RunWith;
38+
import org.junit.runners.JUnit4;
39+
40+
@RunWith(JUnit4.class)
41+
public class SpanFEBypassTest extends AbstractMockServerTest {
42+
private static final Statement SELECT_RANDOM_STATEMENT = Statement.of("select * from random");
43+
private static final int RANDOM_RESULT_ROW_COUNT = 20;
44+
private static Spanner spanner;
45+
private static DatabaseClient client;
46+
47+
@BeforeClass
48+
public static void enableLocationApiAndSetupClient() {
49+
SpannerOptions.useEnvironment(
50+
new SpannerOptions.SpannerEnvironment() {
51+
@Override
52+
public boolean isEnableLocationApi() {
53+
return true;
54+
}
55+
});
56+
spanner =
57+
SpannerOptions.newBuilder()
58+
.setProjectId("my-project")
59+
.setHost(String.format("http://localhost:%d", getPort()))
60+
.setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
61+
.setCredentials(NoCredentials.getInstance())
62+
.build()
63+
.getService();
64+
client = spanner.getDatabaseClient(DatabaseId.of("my-project", "my-instance", "my-database"));
65+
66+
RandomResultSetGenerator generator = new RandomResultSetGenerator(RANDOM_RESULT_ROW_COUNT);
67+
mockSpanner.putStatementResult(
68+
StatementResult.query(SELECT_RANDOM_STATEMENT, generator.generate()));
69+
}
70+
71+
@AfterClass
72+
public static void cleanup() {
73+
SpannerOptions.useDefaultEnvironment();
74+
if (spanner != null) {
75+
spanner.close();
76+
}
77+
}
78+
79+
@Test
80+
public void testSingleQuery() {
81+
int rowCount = 0;
82+
try (ResultSet resultSet = client.singleUse().executeQuery(SELECT_RANDOM_STATEMENT)) {
83+
while (resultSet.next()) {
84+
rowCount++;
85+
}
86+
}
87+
assertEquals(RANDOM_RESULT_ROW_COUNT, rowCount);
88+
}
89+
90+
@Test
91+
public void testParallelQueries() throws Exception {
92+
int numThreads = 10;
93+
ListeningExecutorService executor =
94+
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(numThreads));
95+
List<ListenableFuture<Void>> results = new ArrayList<>();
96+
for (int i = 0; i < numThreads; i++) {
97+
results.add(
98+
executor.submit(
99+
() -> {
100+
try (ResultSet resultSet =
101+
client.singleUse().executeQuery(SELECT_RANDOM_STATEMENT)) {
102+
while (resultSet.next()) {
103+
// Randomly stop consuming results somewhere halfway the results (sometimes).
104+
if (ThreadLocalRandom.current().nextInt(RANDOM_RESULT_ROW_COUNT * 2) == 5) {
105+
break;
106+
}
107+
}
108+
}
109+
return null;
110+
}));
111+
}
112+
executor.shutdown();
113+
Futures.allAsList(results).get();
114+
}
115+
116+
@Test
117+
public void testSingleReadWriteTransaction() {
118+
client.readWriteTransaction().run(transaction -> transaction.executeUpdate(INSERT_STATEMENT));
119+
}
120+
121+
@Test
122+
public void testParallelReadWriteTransactions() throws Exception {
123+
int numThreads = 10;
124+
ListeningExecutorService executor =
125+
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(numThreads));
126+
List<ListenableFuture<Void>> results = new ArrayList<>();
127+
for (int i = 0; i < numThreads; i++) {
128+
results.add(
129+
executor.submit(
130+
() -> {
131+
client
132+
.readWriteTransaction()
133+
.run(transaction -> transaction.executeUpdate(INSERT_STATEMENT));
134+
return null;
135+
}));
136+
}
137+
executor.shutdown();
138+
Futures.allAsList(results).get();
139+
}
140+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ protected String getBaseUrl() {
314314
server.getPort());
315315
}
316316

317-
protected int getPort() {
317+
protected static int getPort() {
318318
return server.getPort();
319319
}
320320

0 commit comments

Comments
 (0)