diff --git a/java-spanner/samples/snippets/pom.xml b/java-spanner/samples/snippets/pom.xml
index 4f41d624282d..e7fcde94aa85 100644
--- a/java-spanner/samples/snippets/pom.xml
+++ b/java-spanner/samples/snippets/pom.xml
@@ -25,6 +25,7 @@
1.8
UTF-8
0.31.1
+ mysample
@@ -137,7 +138,7 @@
us-east1
cmek-test-key-ring
cmek-test-key
- mysample
+ ${spanner.sample.database}
quick-db
@@ -166,7 +167,7 @@
us-east1
cmek-test-key-ring
cmek-test-key
- mysample
+ ${spanner.sample.database}
quick-db
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateFullBackupScheduleSampleIT.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateFullBackupScheduleSampleIT.java
index 82b67c4dfe85..4f4a5cfcbb53 100644
--- a/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateFullBackupScheduleSampleIT.java
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateFullBackupScheduleSampleIT.java
@@ -20,6 +20,7 @@
import com.google.spanner.admin.database.v1.BackupScheduleName;
import java.util.UUID;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -27,7 +28,12 @@
@RunWith(JUnit4.class)
public class CreateFullBackupScheduleSampleIT extends SampleTestBaseV2 {
// Default instance and given db should exist for tests to pass.
- private static String databaseId = System.getProperty("spanner.sample.database", "mysample");
+ private static String databaseId = getSampleDatabase();
+
+ @Before
+ public void cleanUpPreExistingBackupSchedules() {
+ cleanUpStaleBackupSchedules(instanceId, databaseId);
+ }
@Test
public void testCreateFullBackupScheduleSample() throws Exception {
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateIncrementalBackupScheduleSampleIT.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateIncrementalBackupScheduleSampleIT.java
index ac38150f5203..61af70935f59 100644
--- a/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateIncrementalBackupScheduleSampleIT.java
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/CreateIncrementalBackupScheduleSampleIT.java
@@ -20,6 +20,7 @@
import com.google.spanner.admin.database.v1.BackupScheduleName;
import java.util.UUID;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -27,7 +28,12 @@
@RunWith(JUnit4.class)
public class CreateIncrementalBackupScheduleSampleIT extends SampleTestBaseV2 {
// Default instance and given db should exist for tests to pass.
- private static String databaseId = System.getProperty("spanner.sample.database", "mysample");
+ private static String databaseId = getSampleDatabase();
+
+ @Before
+ public void cleanUpPreExistingBackupSchedules() {
+ cleanUpStaleBackupSchedules(multiRegionalInstanceId, databaseId);
+ }
@Test
public void testCreateIncrementalBackupScheduleSample() throws Exception {
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/DeleteBackupScheduleSampleIT.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/DeleteBackupScheduleSampleIT.java
index f379c9bfe47d..8d89754d7c5e 100644
--- a/java-spanner/samples/snippets/src/test/java/com/example/spanner/DeleteBackupScheduleSampleIT.java
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/DeleteBackupScheduleSampleIT.java
@@ -20,6 +20,7 @@
import com.google.spanner.admin.database.v1.BackupScheduleName;
import java.util.UUID;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -27,7 +28,12 @@
@RunWith(JUnit4.class)
public class DeleteBackupScheduleSampleIT extends SampleTestBaseV2 {
// Default instance and given db should exist for tests to pass.
- private static String databaseId = System.getProperty("spanner.sample.database", "mysample");
+ private static String databaseId = getSampleDatabase();
+
+ @Before
+ public void cleanUpPreExistingBackupSchedules() {
+ cleanUpStaleBackupSchedules(instanceId, databaseId);
+ }
@Test
public void testDeleteBackupScheduleSample() throws Exception {
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/GetBackupScheduleSampleIT.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/GetBackupScheduleSampleIT.java
index 366093cddd5e..a7c523b8bd5a 100644
--- a/java-spanner/samples/snippets/src/test/java/com/example/spanner/GetBackupScheduleSampleIT.java
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/GetBackupScheduleSampleIT.java
@@ -20,6 +20,7 @@
import com.google.spanner.admin.database.v1.BackupScheduleName;
import java.util.UUID;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -27,7 +28,12 @@
@RunWith(JUnit4.class)
public class GetBackupScheduleSampleIT extends SampleTestBaseV2 {
// Default instance and given db should exist for tests to pass.
- private static String databaseId = System.getProperty("spanner.sample.database", "mysample");
+ private static String databaseId = getSampleDatabase();
+
+ @Before
+ public void cleanUpPreExistingBackupSchedules() {
+ cleanUpStaleBackupSchedules(instanceId, databaseId);
+ }
@Test
public void testGetBackupScheduleSample() throws Exception {
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/ListBackupSchedulesSampleIT.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/ListBackupSchedulesSampleIT.java
index 97feb2d7e9ba..eca11a2ed813 100644
--- a/java-spanner/samples/snippets/src/test/java/com/example/spanner/ListBackupSchedulesSampleIT.java
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/ListBackupSchedulesSampleIT.java
@@ -20,6 +20,7 @@
import com.google.spanner.admin.database.v1.BackupScheduleName;
import java.util.UUID;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -27,7 +28,12 @@
@RunWith(JUnit4.class)
public class ListBackupSchedulesSampleIT extends SampleTestBaseV2 {
// Default instance and given db should exist for tests to pass.
- private static String databaseId = System.getProperty("spanner.sample.database", "mysample");
+ private static String databaseId = getSampleDatabase();
+
+ @Before
+ public void cleanUpPreExistingBackupSchedules() {
+ cleanUpStaleBackupSchedules(instanceId, databaseId);
+ }
@Test
public void testListBackupSchedulesSample() throws Exception {
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2.java
index 5a43261269d9..5c9bcddcbeb3 100644
--- a/java-spanner/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2.java
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2.java
@@ -23,8 +23,10 @@
import com.google.cloud.spanner.admin.database.v1.DatabaseAdminSettings;
import com.google.cloud.spanner.admin.instance.v1.InstanceAdminClient;
import com.google.cloud.spanner.admin.instance.v1.InstanceAdminSettings;
+import com.google.spanner.admin.database.v1.BackupSchedule;
import com.google.spanner.admin.database.v1.DatabaseDialect;
import java.io.IOException;
+import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -37,12 +39,45 @@ public class SampleTestBaseV2 {
private static final String BASE_INSTANCE_ID =
System.getProperty("spanner.sample.instance", "mysample-instance");
- private static final String BASE_DATABASE_ID =
- System.getProperty("spanner.sample.database", "sampledb");
+ private static final String BASE_DATABASE_ID = getSampleDatabase();
private static final String BASE_BACKUP_ID = "samplebk";
private static final String BASE_INSTANCE_CONFIG_ID = "sampleconfig";
private static final int AWAIT_TERMINATION_SECONDS = 10;
+ static String resolveSampleDatabase(String sysProp, String envDb, String kokoroJob) {
+ if (sysProp != null && !sysProp.trim().isEmpty() && !sysProp.equals("mysample")) {
+ return sysProp.trim();
+ }
+ if (envDb != null && !envDb.trim().isEmpty()) {
+ return envDb.trim();
+ }
+ if (kokoroJob != null) {
+ if (kokoroJob.contains("java8-samples")) {
+ return "mysample_java8";
+ } else if (kokoroJob.contains("java11-samples")) {
+ return "mysample_java11";
+ }
+ }
+ if (sysProp != null && !sysProp.trim().isEmpty()) {
+ return sysProp.trim();
+ }
+ return "mysample";
+ }
+
+ public static String getSampleDatabase() {
+ String kokoroJob = System.getenv("KOKORO_JOB_NAME");
+ if (kokoroJob == null || kokoroJob.isEmpty()) {
+ kokoroJob = System.getenv("JOB_NAME");
+ }
+ if (kokoroJob == null || kokoroJob.isEmpty()) {
+ kokoroJob = System.getenv("JOB_TYPE");
+ }
+ return resolveSampleDatabase(
+ System.getProperty("spanner.sample.database"),
+ System.getenv("SPANNER_SAMPLE_DATABASE"),
+ kokoroJob);
+ }
+
protected static String projectId;
protected static final String instanceId = System.getProperty("spanner.test.instance");
protected static DatabaseAdminClient databaseAdminClient;
@@ -148,6 +183,40 @@ public static void afterClass() throws InterruptedException {
instanceAdminClient.awaitTermination(AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS);
}
+ protected static void cleanUpStaleBackupSchedules(
+ final String targetInstanceId, final String targetDatabaseId) {
+ try {
+ final long nowSeconds = Instant.now().getEpochSecond();
+ final long staleThresholdSeconds = TimeUnit.HOURS.toSeconds(3);
+
+ for (BackupSchedule schedule :
+ databaseAdminClient
+ .listBackupSchedules(getDatabaseName(projectId, targetInstanceId, targetDatabaseId))
+ .iterateAll()) {
+ if (schedule.hasUpdateTime()) {
+ long ageSeconds = nowSeconds - schedule.getUpdateTime().getSeconds();
+ if (ageSeconds > staleThresholdSeconds) {
+ try {
+ databaseAdminClient.deleteBackupSchedule(schedule.getName());
+ } catch (Exception e) {
+ System.out.println(
+ "Failed to delete stale backup schedule "
+ + schedule.getName()
+ + " due to "
+ + e.getMessage()
+ + ", skipping...");
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ System.out.println(
+ "Failed to list or clean up stale backup schedules due to "
+ + e.getMessage()
+ + ", skipping...");
+ }
+ }
+
static String getDatabaseName(final String projectId,
final String instanceId, final String databaseId) {
return String.format(
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2Test.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2Test.java
new file mode 100644
index 000000000000..5eab66f50f99
--- /dev/null
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/SampleTestBaseV2Test.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.spanner;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class SampleTestBaseV2Test {
+
+ @Test
+ public void testDefaultFallbackToMySample() {
+ assertThat(SampleTestBaseV2.resolveSampleDatabase(null, null, null)).isEqualTo("mysample");
+ assertThat(SampleTestBaseV2.resolveSampleDatabase("", "", "")).isEqualTo("mysample");
+ }
+
+ @Test
+ public void testDefaultPropertyReturnsMySample() {
+ assertThat(SampleTestBaseV2.resolveSampleDatabase("mysample", null, null)).isEqualTo("mysample");
+ }
+
+ @Test
+ public void testKokoroJava8SamplesAutoDetection() {
+ assertThat(
+ SampleTestBaseV2.resolveSampleDatabase(
+ "mysample", null, "cloud-devrel/client-libraries/java/java-spanner/nightly/java8-samples"))
+ .isEqualTo("mysample_java8");
+ }
+
+ @Test
+ public void testKokoroJava11SamplesAutoDetection() {
+ assertThat(
+ SampleTestBaseV2.resolveSampleDatabase(
+ "mysample", null, "cloud-devrel/client-libraries/java/java-spanner/nightly/java11-samples"))
+ .isEqualTo("mysample_java11");
+ }
+
+ @Test
+ public void testKokoroSamplesJobFallback() {
+ assertThat(
+ SampleTestBaseV2.resolveSampleDatabase(
+ "mysample", null, "cloud-devrel/client-libraries/java/java-spanner/nightly/samples"))
+ .isEqualTo("mysample");
+ }
+
+ @Test
+ public void testExplicitSystemPropertyOverrideTakesPrecedence() {
+ assertThat(
+ SampleTestBaseV2.resolveSampleDatabase(
+ "custom-db", null, "cloud-devrel/client-libraries/java/java-spanner/nightly/java8-samples"))
+ .isEqualTo("custom-db");
+ }
+
+ @Test
+ public void testExplicitEnvVarOverrideTakesPrecedence() {
+ assertThat(
+ SampleTestBaseV2.resolveSampleDatabase(
+ "mysample", "env-custom-db", "cloud-devrel/client-libraries/java/java-spanner/nightly/java8-samples"))
+ .isEqualTo("env-custom-db");
+ }
+}
diff --git a/java-spanner/samples/snippets/src/test/java/com/example/spanner/UpdateBackupScheduleSampleIT.java b/java-spanner/samples/snippets/src/test/java/com/example/spanner/UpdateBackupScheduleSampleIT.java
index eff037459f91..39bae31a2b0b 100644
--- a/java-spanner/samples/snippets/src/test/java/com/example/spanner/UpdateBackupScheduleSampleIT.java
+++ b/java-spanner/samples/snippets/src/test/java/com/example/spanner/UpdateBackupScheduleSampleIT.java
@@ -20,6 +20,7 @@
import com.google.spanner.admin.database.v1.BackupScheduleName;
import java.util.UUID;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -27,7 +28,12 @@
@RunWith(JUnit4.class)
public class UpdateBackupScheduleSampleIT extends SampleTestBaseV2 {
// Default instance and given db should exist for tests to pass.
- private static String databaseId = System.getProperty("spanner.sample.database", "mysample");
+ private static String databaseId = getSampleDatabase();
+
+ @Before
+ public void cleanUpPreExistingBackupSchedules() {
+ cleanUpStaleBackupSchedules(instanceId, databaseId);
+ }
@Test
public void testUpdateBackupScheduleSample() throws Exception {