diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/GcloudEmulatorCommand.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/GcloudEmulatorCommand.java new file mode 100644 index 000000000..3961711c0 --- /dev/null +++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/GcloudEmulatorCommand.java @@ -0,0 +1,54 @@ +/* + * Copyright 2023 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 + * + * https://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.google.cloud.datastore.testing; + +import static com.google.cloud.datastore.testing.LocalDatastoreHelper.CONSISTENCY_FLAG; +import static com.google.cloud.datastore.testing.LocalDatastoreHelper.PROJECT_FLAG; +import static com.google.common.base.MoreObjects.firstNonNull; + +import com.google.api.core.InternalApi; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +/** Utility to configure gcloud datastore emulator command. */ +@InternalApi +public class GcloudEmulatorCommand { + + // Gcloud emulator settings + private static final String GCLOUD_CMD_TEXT = "gcloud --quiet beta emulators datastore start"; + private static final String GCLOUD_CMD_PORT_FLAG = "--host-port="; + public static final String VERSION_PREFIX = "cloud-datastore-emulator "; + + private static final String PROJECT_ID_PREFIX = "test-project-"; + private static final String DEFAULT_PROJECT_ID = PROJECT_ID_PREFIX + UUID.randomUUID(); + + public static List get(LocalDatastoreHelper.Builder builder, int port) { + String projectId = firstNonNull(builder.getProjectId(), DEFAULT_PROJECT_ID); + List gcloudCommand = new ArrayList<>(Arrays.asList(GCLOUD_CMD_TEXT.split(" "))); + gcloudCommand.add(GCLOUD_CMD_PORT_FLAG + "localhost:" + port); + gcloudCommand.add(CONSISTENCY_FLAG + builder.getConsistency()); + gcloudCommand.add(PROJECT_FLAG + projectId); + if (!builder.isStoreOnDisk()) { + gcloudCommand.add("--no-store-on-disk"); + } + if (builder.getDataDir() != null) { + gcloudCommand.add("--data-dir=" + builder.getDataDir()); + } + return gcloudCommand; + } +} diff --git a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/LocalDatastoreHelper.java b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/LocalDatastoreHelper.java index db4bd112e..c7f481920 100644 --- a/google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/LocalDatastoreHelper.java +++ b/google-cloud-datastore/src/main/java/com/google/cloud/datastore/testing/LocalDatastoreHelper.java @@ -16,6 +16,7 @@ package com.google.cloud.datastore.testing; +import static com.google.cloud.datastore.testing.GcloudEmulatorCommand.VERSION_PREFIX; import static com.google.common.base.MoreObjects.firstNonNull; import com.google.api.core.InternalApi; @@ -51,12 +52,10 @@ public class LocalDatastoreHelper extends BaseEmulatorHelper { private final List emulatorRunners; private final double consistency; private final Path gcdPath; - private boolean storeOnDisk; + private final boolean storeOnDisk; // Gcloud emulator settings - private static final String GCLOUD_CMD_TEXT = "gcloud beta emulators datastore start"; - private static final String GCLOUD_CMD_PORT_FLAG = "--host-port="; - private static final String VERSION_PREFIX = "cloud-datastore-emulator "; + private static final String MIN_VERSION = "1.2.0"; // Downloadable emulator settings @@ -69,8 +68,8 @@ public class LocalDatastoreHelper extends BaseEmulatorHelper { private static final String ACCESS_TOKEN = System.getenv("DATASTORE_EMULATOR_ACCESS_TOKEN"); // Common settings - private static final String CONSISTENCY_FLAG = "--consistency="; - private static final String PROJECT_FLAG = "--project="; + public static final String CONSISTENCY_FLAG = "--consistency="; + public static final String PROJECT_FLAG = "--project="; private static final double DEFAULT_CONSISTENCY = 0.9; private static final String DEFAULT_PROJECT_ID = PROJECT_ID_PREFIX + UUID.randomUUID(); @@ -129,6 +128,22 @@ public Builder setStoreOnDisk(boolean storeOnDisk) { return this; } + double getConsistency() { + return consistency; + } + + boolean isStoreOnDisk() { + return storeOnDisk; + } + + String getProjectId() { + return projectId; + } + + Path getDataDir() { + return dataDir; + } + /** Creates a {@code LocalDatastoreHelper} object. */ public LocalDatastoreHelper build() { return new LocalDatastoreHelper(this); @@ -140,7 +155,6 @@ private LocalDatastoreHelper(Builder builder) { "datastore", builder.port > 0 ? builder.port : BaseEmulatorHelper.findAvailablePort(DEFAULT_PORT), firstNonNull(builder.projectId, DEFAULT_PROJECT_ID)); - String projectId = firstNonNull(builder.projectId, DEFAULT_PROJECT_ID); this.consistency = builder.consistency > 0 ? builder.consistency : DEFAULT_CONSISTENCY; this.gcdPath = builder.dataDir; this.storeOnDisk = builder.storeOnDisk; @@ -148,22 +162,13 @@ private LocalDatastoreHelper(Builder builder) { if (isWindows()) { binName = BIN_NAME.replace("/", "\\"); } - List gcloudCommand = new ArrayList<>(Arrays.asList(GCLOUD_CMD_TEXT.split(" "))); - gcloudCommand.add(GCLOUD_CMD_PORT_FLAG + "localhost:" + getPort()); - gcloudCommand.add(CONSISTENCY_FLAG + builder.consistency); - gcloudCommand.add(PROJECT_FLAG + projectId); - if (!builder.storeOnDisk) { - gcloudCommand.add("--no-store-on-disk"); - } GcloudEmulatorRunner gcloudRunner = - new GcloudEmulatorRunner(gcloudCommand, VERSION_PREFIX, MIN_VERSION); + new GcloudEmulatorRunner( + GcloudEmulatorCommand.get(builder, getPort()), VERSION_PREFIX, MIN_VERSION); List binCommand = new ArrayList<>(Arrays.asList(binName, "start")); binCommand.add("--testing"); binCommand.add(BIN_CMD_PORT_FLAG + getPort()); binCommand.add(CONSISTENCY_FLAG + getConsistency()); - if (builder.dataDir != null) { - gcloudCommand.add("--data-dir=" + getGcdPath()); - } DownloadableEmulatorRunner downloadRunner = new DownloadableEmulatorRunner(binCommand, EMULATOR_URL, MD5_CHECKSUM, ACCESS_TOKEN); this.emulatorRunners = ImmutableList.of(gcloudRunner, downloadRunner); diff --git a/google-cloud-datastore/src/test/java/com/google/cloud/datastore/testing/GcloudEmulatorCommandTest.java b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/testing/GcloudEmulatorCommandTest.java new file mode 100644 index 000000000..5bf59cd8f --- /dev/null +++ b/google-cloud-datastore/src/test/java/com/google/cloud/datastore/testing/GcloudEmulatorCommandTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2023 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 + * + * https://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.google.cloud.datastore.testing; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.File; +import java.nio.file.Path; +import java.util.List; +import org.junit.Before; +import org.junit.Test; + +public class GcloudEmulatorCommandTest { + + private static Path TEMP_DIR = new File(System.getProperty("java.io.tmpdir")).toPath(); + + private List gcloudEmulatorCommand; + + @Before + public void setUp() throws Exception { + LocalDatastoreHelper.Builder builder = + LocalDatastoreHelper.newBuilder() + .setConsistency(0.75) + .setPort(8081) + .setProjectId("my-project-id") + .setDataDir(TEMP_DIR); + + gcloudEmulatorCommand = GcloudEmulatorCommand.get(builder, 8080); + } + + @Test + public void binNameWithDatastoreEmulatorStartOption() { + String commandText = String.join(" ", gcloudEmulatorCommand); + assertThat(commandText.startsWith("gcloud --quiet beta emulators datastore start")).isTrue(); + } + + @Test + public void portFlag() { + assertThat(gcloudEmulatorCommand.contains("--host-port=localhost:8080")).isTrue(); + } + + @Test + public void consistencyFlag() { + assertThat(gcloudEmulatorCommand.contains("--consistency=0.75")).isTrue(); + } + + @Test + public void projectIdFlag() { + assertThat(gcloudEmulatorCommand.contains("--project=my-project-id")).isTrue(); + } + + @Test + public void defaultProjectIdFlag() { + LocalDatastoreHelper.Builder builder = LocalDatastoreHelper.newBuilder().setProjectId(null); + + assertThat( + GcloudEmulatorCommand.get(builder, 0).stream() + .anyMatch(s -> s.startsWith("--project=test-project"))) + .isTrue(); + } + + @Test + public void dataDirFlag() { + assertThat(gcloudEmulatorCommand.contains("--data-dir=" + TEMP_DIR)).isTrue(); + } + + @Test + public void NoStoreOnDiskFlagShouldBeAbsent() { + assertThat(gcloudEmulatorCommand.contains("--no-store-on-disk")).isFalse(); + } + + @Test + public void NoStoreOnDiskFlagShouldBePresent() { + LocalDatastoreHelper.Builder builder = LocalDatastoreHelper.newBuilder().setStoreOnDisk(false); + + assertThat(GcloudEmulatorCommand.get(builder, 0).contains("--no-store-on-disk")).isTrue(); + } +}