From 2c5f32385fd19d98703ad6e07e14ebe0a73a5ef3 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Mon, 30 May 2016 08:23:53 +0200 Subject: [PATCH] Add vararg options (WaitForOption) to waitFor method --- .../java/com/google/cloud/bigquery/Job.java | 53 +++-- .../com/google/cloud/bigquery/JobTest.java | 66 ++++-- .../cloud/bigquery/it/ITBigQueryTest.java | 11 +- .../com/google/cloud/compute/Operation.java | 53 +++-- .../google/cloud/compute/OperationTest.java | 64 ++++-- .../cloud/compute/it/ITComputeTest.java | 41 ++-- .../java/com/google/cloud/WaitForOption.java | 204 ++++++++++++++++++ .../com/google/cloud/SerializationTest.java | 5 +- .../com/google/cloud/WaitForOptionTest.java | 115 ++++++++++ .../snippets/CreateTableAndLoadData.java | 4 +- .../CreateAddressDiskAndInstance.java | 4 +- .../compute/snippets/CreateInstance.java | 4 +- .../compute/snippets/CreateSnapshot.java | 4 +- 13 files changed, 535 insertions(+), 93 deletions(-) create mode 100644 gcloud-java-core/src/main/java/com/google/cloud/WaitForOption.java create mode 100644 gcloud-java-core/src/test/java/com/google/cloud/WaitForOptionTest.java diff --git a/gcloud-java-bigquery/src/main/java/com/google/cloud/bigquery/Job.java b/gcloud-java-bigquery/src/main/java/com/google/cloud/bigquery/Job.java index 0089bff21dd7..38e64b1318e8 100644 --- a/gcloud-java-bigquery/src/main/java/com/google/cloud/bigquery/Job.java +++ b/gcloud-java-bigquery/src/main/java/com/google/cloud/bigquery/Job.java @@ -16,12 +16,21 @@ package com.google.cloud.bigquery; +import static com.google.cloud.WaitForOption.Option.CHECKING_PERIOD; +import static com.google.cloud.WaitForOption.Option.TIMEOUT; +import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.cloud.ServiceOptions; +import com.google.cloud.WaitForOption; +import com.google.cloud.WaitForOption.CheckingPeriod; + import java.io.IOException; import java.io.ObjectInputStream; +import java.util.Map; import java.util.Objects; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * A Google BigQuery Job. @@ -145,9 +154,13 @@ public boolean isDone() { } /** - * Blocks until this job completes its execution, either failing or succeeding. The job status is - * checked every 500 milliseconds. This method returns current job's latest information. If the - * job no longer exists, this method returns {@code null}. + * Blocks until this job completes its execution, either failing or succeeding. This method + * returns current job's latest information. If the job no longer exists, this method returns + * {@code null}. By default, the job status is checked every 500 milliseconds, to configure this + * value use {@link WaitForOption#checkEvery(long, TimeUnit)}. Use + * {@link WaitForOption#timeout(long, TimeUnit)} to set the maximum time to wait. + * + *

Example usage of {@code waitFor()}: *

 {@code
    * Job completedJob = job.waitFor();
    * if (completedJob == null) {
@@ -158,21 +171,10 @@ public boolean isDone() {
    *   // job completed successfully
    * }}
* - * @throws BigQueryException upon failure - * @throws InterruptedException if the current thread gets interrupted while waiting for the job - * to complete - */ - public Job waitFor() throws InterruptedException { - return waitFor(500, TimeUnit.MILLISECONDS); - } - - /** - * Blocks until this job completes its execution, either failing or succeeding. The - * {@code checkEvery} and {@code unit} parameters determine how often the job's status is checked. - * This method returns current job's latest information. If the job no longer exists, this method - * returns {@code null}. + *

Example usage of {@code waitFor()} with checking period and timeout: *

 {@code
-   * Job completedJob = job.waitFor(1, TimeUnit.SECONDS);
+   * Job completedJob = job.waitFor(WaitForOption.checkEvery(1, TimeUnit.SECONDS),
+   *     WaitForOption.timeout(60, TimeUnit.SECONDS));
    * if (completedJob == null) {
    *   // job no longer exists
    * } else if (completedJob.status().error() != null) {
@@ -181,13 +183,26 @@ public Job waitFor() throws InterruptedException {
    *   // job completed successfully
    * }}
* + * @param waitOptions options to configure checking period and timeout * @throws BigQueryException upon failure * @throws InterruptedException if the current thread gets interrupted while waiting for the job * to complete + * @throws TimeoutException if the timeout provided with + * {@link WaitForOption#timeout(long, TimeUnit)} is exceeded. If no such option is provided + * this exception is never thrown. */ - public Job waitFor(int checkEvery, TimeUnit unit) throws InterruptedException { + public Job waitFor(WaitForOption... waitOptions) throws InterruptedException, TimeoutException { + Map optionMap = WaitForOption.asMap(waitOptions); + CheckingPeriod checkingPeriod = firstNonNull(CHECKING_PERIOD.getCheckingPeriod(optionMap), + CheckingPeriod.defaultInstance()); + long timeout = firstNonNull(TIMEOUT.getLong(optionMap), -1L); + ServiceOptions.Clock clock = options.clock(); + long startTime = clock.millis(); while (!isDone()) { - unit.sleep(checkEvery); + if (timeout != -1 && (clock.millis() - startTime) >= timeout) { + throw new TimeoutException(); + } + checkingPeriod.sleep(); } return reload(); } diff --git a/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/JobTest.java b/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/JobTest.java index 26178054d304..377c34e81a01 100644 --- a/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/JobTest.java +++ b/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/JobTest.java @@ -27,13 +27,18 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import com.google.cloud.ServiceOptions.Clock; +import com.google.cloud.WaitForOption; import com.google.cloud.bigquery.JobStatistics.CopyStatistics; import org.easymock.EasyMock; import org.junit.After; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public class JobTest { @@ -69,6 +74,9 @@ public class JobTest { private Job expectedJob; private Job job; + @Rule + public final ExpectedException thrown = ExpectedException.none(); + private void initializeExpectedJob(int optionsCalls) { expect(serviceMockReturnsOptions.options()).andReturn(mockOptions).times(optionsCalls); replay(serviceMockReturnsOptions); @@ -181,35 +189,38 @@ public void testIsDone_NotExists() throws Exception { } @Test - public void testWaitFor() throws InterruptedException { + public void testWaitFor() throws InterruptedException, TimeoutException { initializeExpectedJob(2); BigQuery.JobOption[] expectedOptions = {BigQuery.JobOption.fields(BigQuery.JobField.STATUS)}; JobStatus status = createStrictMock(JobStatus.class); expect(status.state()).andReturn(JobStatus.State.DONE); expect(bigquery.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); Job completedJob = expectedJob.toBuilder().status(status).build(); expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(completedJob); expect(bigquery.getJob(JOB_INFO.jobId())).andReturn(completedJob); - replay(status, bigquery); + replay(status, bigquery, mockOptions); initializeJob(); assertSame(completedJob, job.waitFor()); - verify(status); + verify(status, mockOptions); } @Test - public void testWaitFor_Null() throws InterruptedException { + public void testWaitFor_Null() throws InterruptedException, TimeoutException { initializeExpectedJob(1); BigQuery.JobOption[] expectedOptions = {BigQuery.JobOption.fields(BigQuery.JobField.STATUS)}; expect(bigquery.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(null); expect(bigquery.getJob(JOB_INFO.jobId())).andReturn(null); - replay(bigquery); + replay(bigquery, mockOptions); initializeJob(); assertNull(job.waitFor()); + verify(mockOptions); } @Test - public void testWaitForWithTimeUnit() throws InterruptedException { + public void testWaitForWithCheckingPeriod() throws InterruptedException, TimeoutException { initializeExpectedJob(3); BigQuery.JobOption[] expectedOptions = {BigQuery.JobOption.fields(BigQuery.JobField.STATUS)}; TimeUnit timeUnit = createStrictMock(TimeUnit.class); @@ -219,33 +230,62 @@ public void testWaitForWithTimeUnit() throws InterruptedException { expect(status.state()).andReturn(JobStatus.State.RUNNING); expect(status.state()).andReturn(JobStatus.State.DONE); expect(bigquery.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); Job runningJob = expectedJob.toBuilder().status(status).build(); Job completedJob = expectedJob.toBuilder().status(status).build(); expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(runningJob); expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(completedJob); expect(bigquery.getJob(JOB_INFO.jobId())).andReturn(completedJob); - replay(status, bigquery, timeUnit); + replay(status, bigquery, timeUnit, mockOptions); initializeJob(); - assertSame(completedJob, job.waitFor(42, timeUnit)); - verify(status, timeUnit); + assertSame(completedJob, job.waitFor(WaitForOption.checkEvery(42, timeUnit))); + verify(status, timeUnit, mockOptions); } @Test - public void testWaitForWithTimeUnit_Null() throws InterruptedException { + public void testWaitForWithCheckingPeriod_Null() throws InterruptedException, TimeoutException { initializeExpectedJob(2); BigQuery.JobOption[] expectedOptions = {BigQuery.JobOption.fields(BigQuery.JobField.STATUS)}; TimeUnit timeUnit = createStrictMock(TimeUnit.class); timeUnit.sleep(42); EasyMock.expectLastCall(); expect(bigquery.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); Job runningJob = expectedJob.toBuilder().status(new JobStatus(JobStatus.State.RUNNING)).build(); expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(runningJob); expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(null); expect(bigquery.getJob(JOB_INFO.jobId())).andReturn(null); - replay(bigquery, timeUnit); + replay(bigquery, timeUnit, mockOptions); + initializeJob(); + assertNull(job.waitFor(WaitForOption.checkEvery(42, timeUnit))); + verify(bigquery, timeUnit, mockOptions); + } + + @Test + public void testWaitForWithTimeout() throws InterruptedException, TimeoutException { + initializeExpectedJob(2); + BigQuery.JobOption[] expectedOptions = {BigQuery.JobOption.fields(BigQuery.JobField.STATUS)}; + TimeUnit timeUnit = createStrictMock(TimeUnit.class); + timeUnit.sleep(1); + EasyMock.expectLastCall(); + Clock clock = createStrictMock(Clock.class); + EasyMock.expect(clock.millis()).andReturn(0L); + EasyMock.expect(clock.millis()).andReturn(1L); + EasyMock.expect(clock.millis()).andReturn(3L); + JobStatus status = createStrictMock(JobStatus.class); + expect(status.state()).andReturn(JobStatus.State.RUNNING); + expect(status.state()).andReturn(JobStatus.State.RUNNING); + expect(bigquery.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(clock); + Job runningJob = expectedJob.toBuilder().status(status).build(); + expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(runningJob); + expect(bigquery.getJob(JOB_INFO.jobId(), expectedOptions)).andReturn(runningJob); + replay(status, bigquery, timeUnit, clock, mockOptions); initializeJob(); - assertNull(job.waitFor(42, timeUnit)); - verify(bigquery, timeUnit); + thrown.expect(TimeoutException.class); + job.waitFor(WaitForOption.checkEvery(1, timeUnit), + WaitForOption.timeout(3, TimeUnit.MILLISECONDS)); + verify(status, timeUnit, clock, mockOptions); } @Test diff --git a/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java b/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java index 92151ea8bc4c..dde170f87859 100644 --- a/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java +++ b/gcloud-java-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java @@ -82,6 +82,7 @@ import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; @@ -169,7 +170,7 @@ public class ITBigQueryTest { public Timeout globalTimeout = Timeout.seconds(300); @BeforeClass - public static void beforeClass() throws InterruptedException { + public static void beforeClass() throws InterruptedException, TimeoutException { RemoteBigQueryHelper bigqueryHelper = RemoteBigQueryHelper.create(); RemoteStorageHelper storageHelper = RemoteStorageHelper.create(); bigquery = bigqueryHelper.options().service(); @@ -783,7 +784,7 @@ public void testCreateAndGetJobWithSelectedFields() { } @Test - public void testCopyJob() throws InterruptedException { + public void testCopyJob() throws InterruptedException, TimeoutException { String sourceTableName = "test_copy_job_source_table"; String destinationTableName = "test_copy_job_destination_table"; TableId sourceTable = TableId.of(DATASET, sourceTableName); @@ -808,7 +809,7 @@ public void testCopyJob() throws InterruptedException { } @Test - public void testQueryJob() throws InterruptedException { + public void testQueryJob() throws InterruptedException, TimeoutException { String tableName = "test_query_job_table"; String query = new StringBuilder() .append("SELECT TimestampField, StringField, BooleanField FROM ") @@ -851,7 +852,7 @@ public void testQueryJob() throws InterruptedException { } @Test - public void testExtractJob() throws InterruptedException { + public void testExtractJob() throws InterruptedException, TimeoutException { String tableName = "test_export_job_table"; TableId destinationTable = TableId.of(DATASET, tableName); LoadJobConfiguration configuration = @@ -875,7 +876,7 @@ public void testExtractJob() throws InterruptedException { } @Test - public void testCancelJob() throws InterruptedException { + public void testCancelJob() throws InterruptedException, TimeoutException { String destinationTableName = "test_cancel_query_job_table"; String query = "SELECT TimestampField, StringField, BooleanField FROM " + TABLE_ID.table(); TableId destinationTable = TableId.of(DATASET, destinationTableName); diff --git a/gcloud-java-compute/src/main/java/com/google/cloud/compute/Operation.java b/gcloud-java-compute/src/main/java/com/google/cloud/compute/Operation.java index cf8afb04cfbb..8c8c39918b2a 100644 --- a/gcloud-java-compute/src/main/java/com/google/cloud/compute/Operation.java +++ b/gcloud-java-compute/src/main/java/com/google/cloud/compute/Operation.java @@ -16,8 +16,14 @@ package com.google.cloud.compute; +import static com.google.cloud.WaitForOption.Option.CHECKING_PERIOD; +import static com.google.cloud.WaitForOption.Option.TIMEOUT; +import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.cloud.ServiceOptions; +import com.google.cloud.WaitForOption; +import com.google.cloud.WaitForOption.CheckingPeriod; import com.google.cloud.compute.Compute.OperationOption; import com.google.common.base.Function; import com.google.common.base.MoreObjects; @@ -37,6 +43,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * Google Compute Engine operations. Operation identity can be obtained via {@link #operationId()}. @@ -660,9 +667,13 @@ public boolean isDone() { } /** - * Blocks until this operation completes its execution, either failing or succeeding. The - * operation status is checked every 500 milliseconds. This method returns current operation's - * latest information. If the operation no longer exists, this method returns {@code null}. + * Blocks until this operation completes its execution, either failing or succeeding. This method + * returns current operation's latest information. If the operation no longer exists, this method + * returns {@code null}. By default, the operation status is checked every 500 milliseconds, to + * configure this value use {@link WaitForOption#checkEvery(long, TimeUnit)}. Use + * {@link WaitForOption#timeout(long, TimeUnit)} to set the maximum time to wait. + * + *

Example usage of {@code waitFor()}: *

 {@code
    * Operation completedOperation = operation.waitFor();
    * if (completedOperation == null) {
@@ -673,21 +684,11 @@ public boolean isDone() {
    *   // operation completed successfully
    * }}
* - * @throws ComputeException upon failure - * @throws InterruptedException if the current thread gets interrupted while waiting for the - * operation to complete - */ - public Operation waitFor() throws InterruptedException { - return waitFor(500, TimeUnit.MILLISECONDS); - } - - /** - * Blocks until this operation completes its execution, either failing or succeeding. The - * {@code checkEvery} and {@code unit} parameters determine how often the operation status is - * checked. This method returns current operation's latest information. If the operation no longer - * exists, this method returns {@code null}. + *

Example usage of {@code waitFor()} with checking period and timeout: *

 {@code
-   * Operation completedOperation = operation.waitFor(1, TimeUnit.SECONDS);
+   * Operation completedOperation =
+   *     operation.waitFor(WaitForOption.checkEvery(1, TimeUnit.SECONDS),
+   *         WaitForOption.timeout(60, TimeUnit.SECONDS));
    * if (completedOperation == null) {
    *   // operation no longer exists
    * } else if (completedOperation.errors() != null) {
@@ -696,13 +697,27 @@ public Operation waitFor() throws InterruptedException {
    *   // operation completed successfully
    * }}
* + * @param waitOptions options to configure checking period and timeout * @throws ComputeException upon failure * @throws InterruptedException if the current thread gets interrupted while waiting for the * operation to complete + * @throws TimeoutException if the timeout provided with + * {@link WaitForOption#timeout(long, TimeUnit)} is exceeded. If no such option is provided + * this exception is never thrown. */ - public Operation waitFor(int checkEvery, TimeUnit unit) throws InterruptedException { + public Operation waitFor(WaitForOption... waitOptions) + throws InterruptedException, TimeoutException { + Map optionMap = WaitForOption.asMap(waitOptions); + CheckingPeriod checkingPeriod = firstNonNull(CHECKING_PERIOD.getCheckingPeriod(optionMap), + CheckingPeriod.defaultInstance()); + long timeout = firstNonNull(TIMEOUT.getLong(optionMap), -1L); + ServiceOptions.Clock clock = options.clock(); + long startTime = clock.millis(); while (!isDone()) { - unit.sleep(checkEvery); + if (timeout != -1 && (clock.millis() - startTime) >= timeout) { + throw new TimeoutException(); + } + checkingPeriod.sleep(); } return reload(); } diff --git a/gcloud-java-compute/src/test/java/com/google/cloud/compute/OperationTest.java b/gcloud-java-compute/src/test/java/com/google/cloud/compute/OperationTest.java index 63a0fc511d26..a4c5a5b0358a 100644 --- a/gcloud-java-compute/src/test/java/com/google/cloud/compute/OperationTest.java +++ b/gcloud-java-compute/src/test/java/com/google/cloud/compute/OperationTest.java @@ -28,6 +28,8 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import com.google.cloud.ServiceOptions.Clock; +import com.google.cloud.WaitForOption; import com.google.cloud.compute.Operation.OperationError; import com.google.cloud.compute.Operation.OperationWarning; import com.google.common.collect.ImmutableList; @@ -35,10 +37,13 @@ import org.easymock.EasyMock; import org.junit.After; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; public class OperationTest { @@ -76,6 +81,9 @@ public class OperationTest { private static final RegionOperationId REGION_OPERATION_ID = RegionOperationId.of("project", "region", "op"); + @Rule + public final ExpectedException thrown = ExpectedException.none(); + private final Compute serviceMockReturnsOptions = createStrictMock(Compute.class); private final ComputeOptions mockOptions = createMock(ComputeOptions.class); private Compute compute; @@ -357,35 +365,39 @@ public void testIsDone_NotExists() throws Exception { } @Test - public void testWaitFor() throws InterruptedException { + public void testWaitFor() throws InterruptedException, TimeoutException { initializeExpectedOperation(4); Compute.OperationOption[] expectedOptions = {Compute.OperationOption.fields(Compute.OperationField.STATUS)}; Operation successOperation = Operation.fromPb(serviceMockReturnsOptions, globalOperation.toPb().setError(null)); expect(compute.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)).andReturn(successOperation); expect(compute.getOperation(GLOBAL_OPERATION_ID)).andReturn(successOperation); - replay(compute); + replay(compute, mockOptions); initializeOperation(); assertSame(successOperation, operation.waitFor()); + verify(mockOptions); } @Test - public void testWaitFor_Null() throws InterruptedException { + public void testWaitFor_Null() throws InterruptedException, TimeoutException { initializeExpectedOperation(3); Compute.OperationOption[] expectedOptions = {Compute.OperationOption.fields(Compute.OperationField.STATUS)}; expect(compute.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)).andReturn(null); expect(compute.getOperation(GLOBAL_OPERATION_ID)).andReturn(null); - replay(compute); + replay(compute, mockOptions); initializeOperation(); assertNull(operation.waitFor()); + verify(mockOptions); } @Test - public void testWaitForWithTimeUnit() throws InterruptedException { + public void testWaitForCheckingPeriod() throws InterruptedException, TimeoutException { initializeExpectedOperation(5); Compute.OperationOption[] expectedOptions = {Compute.OperationOption.fields(Compute.OperationField.STATUS)}; @@ -397,18 +409,19 @@ public void testWaitForWithTimeUnit() throws InterruptedException { Operation completedOperation = Operation.fromPb(serviceMockReturnsOptions, globalOperation.toPb().setError(null)); expect(compute.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)).andReturn(runningOperation); expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)) .andReturn(completedOperation); expect(compute.getOperation(GLOBAL_OPERATION_ID)).andReturn(completedOperation); - replay(compute, timeUnit); + replay(compute, timeUnit, mockOptions); initializeOperation(); - assertSame(completedOperation, operation.waitFor(42, timeUnit)); - verify(timeUnit); + assertSame(completedOperation, operation.waitFor(WaitForOption.checkEvery(42, timeUnit))); + verify(timeUnit, mockOptions); } @Test - public void testWaitForWithTimeUnit_Null() throws InterruptedException { + public void testWaitForCheckingPeriod_Null() throws InterruptedException, TimeoutException { initializeExpectedOperation(4); Compute.OperationOption[] expectedOptions = {Compute.OperationOption.fields(Compute.OperationField.STATUS)}; @@ -418,13 +431,40 @@ public void testWaitForWithTimeUnit_Null() throws InterruptedException { Operation runningOperation = Operation.fromPb(serviceMockReturnsOptions, globalOperation.toPb().setError(null).setStatus("RUNNING")); expect(compute.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(Clock.defaultClock()); expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)).andReturn(runningOperation); expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)).andReturn(null); expect(compute.getOperation(GLOBAL_OPERATION_ID)).andReturn(null); - replay(compute, timeUnit); + replay(compute, timeUnit, mockOptions); + initializeOperation(); + assertNull(operation.waitFor(WaitForOption.checkEvery(42, timeUnit))); + verify(compute, timeUnit, mockOptions); + } + + @Test + public void testWaitForWithTimeout() throws InterruptedException, TimeoutException { + initializeExpectedOperation(4); + Compute.OperationOption[] expectedOptions = + {Compute.OperationOption.fields(Compute.OperationField.STATUS)}; + TimeUnit timeUnit = createStrictMock(TimeUnit.class); + timeUnit.sleep(1); + EasyMock.expectLastCall(); + Clock clock = createStrictMock(Clock.class); + EasyMock.expect(clock.millis()).andReturn(0L); + EasyMock.expect(clock.millis()).andReturn(1L); + EasyMock.expect(clock.millis()).andReturn(3L); + Operation runningOperation = Operation.fromPb(serviceMockReturnsOptions, + globalOperation.toPb().setError(null).setStatus("RUNNING")); + expect(compute.options()).andReturn(mockOptions); + expect(mockOptions.clock()).andReturn(clock); + expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)).andReturn(runningOperation); + expect(compute.getOperation(GLOBAL_OPERATION_ID, expectedOptions)).andReturn(runningOperation); + replay(compute, timeUnit, clock, mockOptions); initializeOperation(); - assertNull(operation.waitFor(42, timeUnit)); - verify(compute, timeUnit); + thrown.expect(TimeoutException.class); + operation.waitFor(WaitForOption.checkEvery(1, timeUnit), + WaitForOption.timeout(3, TimeUnit.MILLISECONDS)); + verify(compute, timeUnit, clock, mockOptions); } @Test diff --git a/gcloud-java-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java b/gcloud-java-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java index ba9b58d775e1..5ee58c6bfda4 100644 --- a/gcloud-java-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java +++ b/gcloud-java-compute/src/test/java/com/google/cloud/compute/it/ITComputeTest.java @@ -88,6 +88,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeoutException; public class ITComputeTest { @@ -681,7 +682,7 @@ public void testListZoneOperationsWithFilter() { } @Test - public void testCreateGetAndDeleteRegionAddress() throws InterruptedException { + public void testCreateGetAndDeleteRegionAddress() throws InterruptedException, TimeoutException { String name = BASE_RESOURCE_NAME + "create-and-get-region-address"; AddressId addressId = RegionAddressId.of(REGION, name); AddressInfo addressInfo = AddressInfo.of(addressId); @@ -712,7 +713,7 @@ public void testCreateGetAndDeleteRegionAddress() throws InterruptedException { } @Test - public void testListRegionAddresses() throws InterruptedException { + public void testListRegionAddresses() throws InterruptedException, TimeoutException { String prefix = BASE_RESOURCE_NAME + "list-region-address"; String[] addressNames = {prefix + "1", prefix + "2"}; AddressId firstAddressId = RegionAddressId.of(REGION, addressNames[0]); @@ -764,7 +765,7 @@ public void testListRegionAddresses() throws InterruptedException { } @Test - public void testAggregatedListAddresses() throws InterruptedException { + public void testAggregatedListAddresses() throws InterruptedException, TimeoutException { String prefix = BASE_RESOURCE_NAME + "aggregated-list-address"; String[] addressNames = {prefix + "1", prefix + "2"}; AddressId firstAddressId = RegionAddressId.of(REGION, addressNames[0]); @@ -795,7 +796,7 @@ public void testAggregatedListAddresses() throws InterruptedException { } @Test - public void testCreateGetAndDeleteGlobalAddress() throws InterruptedException { + public void testCreateGetAndDeleteGlobalAddress() throws InterruptedException, TimeoutException { String name = BASE_RESOURCE_NAME + "create-and-get-global-address"; AddressId addressId = GlobalAddressId.of(name); AddressInfo addressInfo = AddressInfo.of(addressId); @@ -824,7 +825,7 @@ public void testCreateGetAndDeleteGlobalAddress() throws InterruptedException { } @Test - public void testListGlobalAddresses() throws InterruptedException { + public void testListGlobalAddresses() throws InterruptedException, TimeoutException { String prefix = BASE_RESOURCE_NAME + "list-global-address"; String[] addressNames = {prefix + "1", prefix + "2"}; AddressId firstAddressId = GlobalAddressId.of(addressNames[0]); @@ -874,7 +875,7 @@ public void testListGlobalAddresses() throws InterruptedException { } @Test - public void testCreateGetResizeAndDeleteStandardDisk() throws InterruptedException { + public void testCreateGetResizeAndDeleteStandardDisk() throws InterruptedException, TimeoutException { String name = BASE_RESOURCE_NAME + "create-and-get-standard-disk"; DiskId diskId = DiskId.of(ZONE, name); DiskInfo diskInfo = @@ -917,7 +918,7 @@ public void testCreateGetResizeAndDeleteStandardDisk() throws InterruptedExcepti } @Test - public void testCreateGetAndDeleteImageDisk() throws InterruptedException { + public void testCreateGetAndDeleteImageDisk() throws InterruptedException, TimeoutException { String name = BASE_RESOURCE_NAME + "create-and-get-image-disk"; DiskId diskId = DiskId.of(ZONE, name); DiskInfo diskInfo = DiskInfo.of(diskId, ImageDiskConfiguration.of(IMAGE_ID)); @@ -962,7 +963,7 @@ public void testCreateGetAndDeleteImageDisk() throws InterruptedException { } @Test - public void testCreateGetAndDeleteSnapshotAndSnapshotDisk() throws InterruptedException { + public void testCreateGetAndDeleteSnapshotAndSnapshotDisk() throws InterruptedException, TimeoutException { String diskName = BASE_RESOURCE_NAME + "create-and-get-snapshot-disk1"; String snapshotDiskName = BASE_RESOURCE_NAME + "create-and-get-snapshot-disk2"; DiskId diskId = DiskId.of(ZONE, diskName); @@ -1048,7 +1049,7 @@ public void testCreateGetAndDeleteSnapshotAndSnapshotDisk() throws InterruptedEx } @Test - public void testListDisksAndSnapshots() throws InterruptedException { + public void testListDisksAndSnapshots() throws InterruptedException, TimeoutException { String prefix = BASE_RESOURCE_NAME + "list-disks-and-snapshots-disk"; String[] diskNames = {prefix + "1", prefix + "2"}; DiskId firstDiskId = DiskId.of(ZONE, diskNames[0]); @@ -1159,7 +1160,7 @@ public void testListDisksAndSnapshots() throws InterruptedException { } @Test - public void testAggregatedListDisks() throws InterruptedException { + public void testAggregatedListDisks() throws InterruptedException, TimeoutException { String prefix = BASE_RESOURCE_NAME + "list-aggregated-disk"; String[] diskZones = {"us-central1-a", "us-east1-c"}; String[] diskNames = {prefix + "1", prefix + "2"}; @@ -1198,7 +1199,7 @@ public void testAggregatedListDisks() throws InterruptedException { } @Test - public void testCreateGetAndDeprecateImage() throws InterruptedException { + public void testCreateGetAndDeprecateImage() throws InterruptedException, TimeoutException { String diskName = BASE_RESOURCE_NAME + "create-and-get-image-disk"; String imageName = BASE_RESOURCE_NAME + "create-and-get-image"; DiskId diskId = DiskId.of(ZONE, diskName); @@ -1316,7 +1317,7 @@ public void testListImagesWithFilter() { } @Test - public void testCreateAndGetNetwork() throws InterruptedException { + public void testCreateAndGetNetwork() throws InterruptedException, TimeoutException { String name = BASE_RESOURCE_NAME + "create-and-get-network"; NetworkId networkId = NetworkId.of(name); NetworkInfo networkInfo = @@ -1347,7 +1348,7 @@ public void testCreateAndGetNetwork() throws InterruptedException { } @Test - public void testListNetworks() throws InterruptedException { + public void testListNetworks() throws InterruptedException, TimeoutException { String name = BASE_RESOURCE_NAME + "list-network"; NetworkId networkId = NetworkId.of(name); NetworkInfo networkInfo = @@ -1393,7 +1394,7 @@ public void testListNetworks() throws InterruptedException { } @Test - public void testCreateNetworkAndSubnetwork() throws InterruptedException { + public void testCreateNetworkAndSubnetwork() throws InterruptedException, TimeoutException { String networkName = BASE_RESOURCE_NAME + "create-subnetwork-network"; NetworkId networkId = NetworkId.of(networkName); NetworkInfo networkInfo = NetworkInfo.of(networkId, SubnetNetworkConfiguration.of(false)); @@ -1474,7 +1475,7 @@ public void testCreateNetworkAndSubnetwork() throws InterruptedException { } @Test - public void testAggregatedListSubnetworks() throws InterruptedException { + public void testAggregatedListSubnetworks() throws InterruptedException, TimeoutException { String networkName = BASE_RESOURCE_NAME + "list-subnetwork-network"; NetworkId networkId = NetworkId.of(networkName); NetworkInfo networkInfo = NetworkInfo.of(networkId, SubnetNetworkConfiguration.of(false)); @@ -1525,7 +1526,7 @@ public void testAggregatedListSubnetworks() throws InterruptedException { } @Test - public void testCreateGetAndDeleteInstance() throws InterruptedException { + public void testCreateGetAndDeleteInstance() throws InterruptedException, TimeoutException { String instanceName = BASE_RESOURCE_NAME + "create-and-get-instance"; String addressName = BASE_RESOURCE_NAME + "create-and-get-instance-address"; // Create an address to assign to the instance @@ -1608,7 +1609,7 @@ public void testCreateGetAndDeleteInstance() throws InterruptedException { } @Test - public void testStartStopAndResetInstance() throws InterruptedException { + public void testStartStopAndResetInstance() throws InterruptedException, TimeoutException { String instanceName = BASE_RESOURCE_NAME + "start-stop-reset-instance"; InstanceId instanceId = InstanceId.of(ZONE, instanceName); NetworkId networkId = NetworkId.of("default"); @@ -1644,7 +1645,7 @@ public void testStartStopAndResetInstance() throws InterruptedException { } @Test - public void testSetInstanceProperties() throws InterruptedException { + public void testSetInstanceProperties() throws InterruptedException, TimeoutException { String instanceName = BASE_RESOURCE_NAME + "set-properties-instance"; InstanceId instanceId = InstanceId.of(ZONE, instanceName); NetworkId networkId = NetworkId.of("default"); @@ -1689,7 +1690,7 @@ public void testSetInstanceProperties() throws InterruptedException { } @Test - public void testAttachAndDetachDisk() throws InterruptedException { + public void testAttachAndDetachDisk() throws InterruptedException, TimeoutException { String instanceName = BASE_RESOURCE_NAME + "attach-and-detach-disk-instance"; String diskName = BASE_RESOURCE_NAME + "attach-and-detach-disk"; InstanceId instanceId = InstanceId.of(ZONE, instanceName); @@ -1739,7 +1740,7 @@ public void testAttachAndDetachDisk() throws InterruptedException { } @Test - public void testAddAndRemoveAccessConfig() throws InterruptedException { + public void testAddAndRemoveAccessConfig() throws InterruptedException, TimeoutException { String instanceName = BASE_RESOURCE_NAME + "add-and-remove-access-instance"; String addressName = BASE_RESOURCE_NAME + "add-and-remove-access-address"; InstanceId instanceId = InstanceId.of(ZONE, instanceName); diff --git a/gcloud-java-core/src/main/java/com/google/cloud/WaitForOption.java b/gcloud-java-core/src/main/java/com/google/cloud/WaitForOption.java new file mode 100644 index 000000000000..85be6bdd0eb1 --- /dev/null +++ b/gcloud-java-core/src/main/java/com/google/cloud/WaitForOption.java @@ -0,0 +1,204 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * 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.google.cloud; + +import static com.google.cloud.WaitForOption.Option.CHECKING_PERIOD; +import static com.google.cloud.WaitForOption.Option.TIMEOUT; +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.Maps; + +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * This class represents options for methods that wait for changes in the status of a resource. + */ +public final class WaitForOption implements Serializable { + + private static final long serialVersionUID = 8443451708032349243L; + + private final Option option; + private final Object value; + + /** + * This class holds the actual period and related time unit for the checking period. + */ + public static final class CheckingPeriod implements Serializable { + + private static final long serialVersionUID = -2481062893220539210L; + + private final long period; + private final TimeUnit unit; + + private CheckingPeriod(long period, TimeUnit unit) { + this.period = period; + this.unit = unit; + } + + /** + * Returns the checking period. + */ + public long period() { + return period; + } + + /** + * Returns the time unit for {@link #period()}. + */ + public TimeUnit unit() { + return unit; + } + + /** + * Blocks the current thread for the amount of time specified by this object. + * + * @throws InterruptedException if the current thread was interrupted + */ + public void sleep() throws InterruptedException { + unit.sleep(period); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || !(obj instanceof CheckingPeriod)) { + return false; + } + CheckingPeriod other = (CheckingPeriod) obj; + return Objects.equals(period, other.period) && Objects.equals(unit, other.unit); + } + + @Override + public int hashCode() { + return Objects.hash(period, unit); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("period", period) + .add("unit", unit) + .toString(); + } + + /** + * Returns the default checking period (500 milliseconds). + */ + public static CheckingPeriod defaultInstance() { + return new CheckingPeriod(500, TimeUnit.MILLISECONDS); + } + } + + public enum Option { + CHECKING_PERIOD, + TIMEOUT; + + @SuppressWarnings("unchecked") + T get(Map options) { + return (T) options.get(this); + } + + public Long getLong(Map options) { + return get(options); + } + + public CheckingPeriod getCheckingPeriod(Map options) { + return get(options); + } + } + + private WaitForOption(Option option, Object value) { + this.option = option; + this.value = value; + } + + /** + * Returns the option's type. + */ + public Option option() { + return option; + } + + /** + * Returns the option's value. + */ + public Object value() { + return value; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || !(obj instanceof WaitForOption)) { + return false; + } + WaitForOption other = (WaitForOption) obj; + return Objects.equals(option, other.option) && Objects.equals(value, other.value); + } + + @Override + public int hashCode() { + return Objects.hash(option, value); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("name", option.name().toLowerCase()) + .add("value", value) + .toString(); + } + + /** + * Returns an option to set how frequently the resource status should be checked. + * + * @param checkEvery the checking period + * @param unit the time unit of the checking period + */ + public static WaitForOption checkEvery(long checkEvery, TimeUnit unit) { + checkArgument(checkEvery >= 0, "checkEvery must be >= 0"); + return new WaitForOption(CHECKING_PERIOD, new CheckingPeriod(checkEvery, unit)); + } + + /** + * Returns an option to set the maximum time to wait. + * + * @param timeout the maximum time to wait, expressed in {@code unit} + * @param unit the time unit of the timeout + */ + public static WaitForOption timeout(long timeout, TimeUnit unit) { + checkArgument(timeout >= 0, "timeout must be >= 0"); + return new WaitForOption(TIMEOUT, TimeUnit.MILLISECONDS.convert(timeout, unit)); + } + + public static Map asMap(WaitForOption... options) { + Map optionMap = Maps.newEnumMap(Option.class); + for (WaitForOption waitOption : options) { + Object prev = optionMap.put(waitOption.option(), waitOption.value()); + checkArgument(prev == null, "Duplicate option %s", waitOption); + } + return optionMap; + } +} diff --git a/gcloud-java-core/src/test/java/com/google/cloud/SerializationTest.java b/gcloud-java-core/src/test/java/com/google/cloud/SerializationTest.java index 75347b250227..46f8fafa4ed9 100644 --- a/gcloud-java-core/src/test/java/com/google/cloud/SerializationTest.java +++ b/gcloud-java-core/src/test/java/com/google/cloud/SerializationTest.java @@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.Serializable; +import java.util.concurrent.TimeUnit; public class SerializationTest extends BaseSerializationTest { @@ -35,6 +36,8 @@ public class SerializationTest extends BaseSerializationTest { new SigningException("message", BASE_SERVICE_EXCEPTION); private static final RetryParams RETRY_PARAMS = RetryParams.defaultInstance(); private static final SomeIamPolicy SOME_IAM_POLICY = new SomeIamPolicy.Builder().build(); + private static final WaitForOption CHECKING_PERIOD = + WaitForOption.checkEvery(42, TimeUnit.SECONDS); private static final String JSON_KEY = "{\n" + " \"private_key_id\": \"somekeyid\",\n" + " \"private_key\": \"-----BEGIN PRIVATE KEY-----\\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggS" @@ -87,7 +90,7 @@ public Builder toBuilder() { @Override protected Serializable[] serializableObjects() { return new Serializable[]{BASE_SERVICE_EXCEPTION, EXCEPTION_HANDLER, IDENTITY, PAGE, - RETRY_PARAMS, SOME_IAM_POLICY, SIGNING_EXCEPTION}; + RETRY_PARAMS, SOME_IAM_POLICY, SIGNING_EXCEPTION, CHECKING_PERIOD}; } @Override diff --git a/gcloud-java-core/src/test/java/com/google/cloud/WaitForOptionTest.java b/gcloud-java-core/src/test/java/com/google/cloud/WaitForOptionTest.java new file mode 100644 index 000000000000..c1003bbe467c --- /dev/null +++ b/gcloud-java-core/src/test/java/com/google/cloud/WaitForOptionTest.java @@ -0,0 +1,115 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * 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.google.cloud; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.WaitForOption.CheckingPeriod; +import com.google.cloud.WaitForOption.Option; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class WaitForOptionTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private static final WaitForOption CHECKING_PERIOD_OPTION = + WaitForOption.checkEvery(42, TimeUnit.MILLISECONDS); + private static final WaitForOption TIMEOUT_OPTION = + WaitForOption.timeout(43, TimeUnit.MILLISECONDS); + + @Test + public void testCheckEvery() { + assertEquals(Option.CHECKING_PERIOD, CHECKING_PERIOD_OPTION.option()); + assertTrue(CHECKING_PERIOD_OPTION.value() instanceof CheckingPeriod); + CheckingPeriod checkingPeriod = (CheckingPeriod) CHECKING_PERIOD_OPTION.value(); + assertEquals(42, checkingPeriod.period()); + assertEquals(TimeUnit.MILLISECONDS, checkingPeriod.unit()); + } + + @Test + public void testCheckEvery_InvalidPeriod() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("checkEvery must be >= 0"); + WaitForOption.checkEvery(-1, TimeUnit.MILLISECONDS); + } + + @Test + public void testTimeout() { + assertEquals(Option.TIMEOUT, TIMEOUT_OPTION.option()); + assertEquals(43L, TIMEOUT_OPTION.value()); + } + + @Test + public void testTimeout_InvalidTimeout() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("timeout must be >= 0"); + WaitForOption.timeout(-1, TimeUnit.MILLISECONDS); + } + + @Test + public void testEqualsAndHashCode() { + assertEquals(CHECKING_PERIOD_OPTION, CHECKING_PERIOD_OPTION); + assertEquals(TIMEOUT_OPTION, TIMEOUT_OPTION); + assertEquals(CHECKING_PERIOD_OPTION.hashCode(), CHECKING_PERIOD_OPTION.hashCode()); + assertEquals(TIMEOUT_OPTION.hashCode(), TIMEOUT_OPTION.hashCode()); + WaitForOption checkingPeriodOption = WaitForOption.checkEvery(42, TimeUnit.MILLISECONDS); + assertEquals(CHECKING_PERIOD_OPTION, checkingPeriodOption); + assertEquals(CHECKING_PERIOD_OPTION.hashCode(), checkingPeriodOption.hashCode()); + WaitForOption timeoutOption = WaitForOption.timeout(43, TimeUnit.MILLISECONDS); + assertEquals(TIMEOUT_OPTION, timeoutOption); + assertEquals(TIMEOUT_OPTION.hashCode(), timeoutOption.hashCode()); + assertNotEquals(CHECKING_PERIOD_OPTION, TIMEOUT_OPTION); + assertNotEquals(CHECKING_PERIOD_OPTION.hashCode(), TIMEOUT_OPTION.hashCode()); + checkingPeriodOption = WaitForOption.checkEvery(43, TimeUnit.MILLISECONDS); + assertNotEquals(CHECKING_PERIOD_OPTION, checkingPeriodOption); + assertNotEquals(CHECKING_PERIOD_OPTION.hashCode(), checkingPeriodOption.hashCode()); + checkingPeriodOption = WaitForOption.checkEvery(42, TimeUnit.SECONDS); + assertNotEquals(CHECKING_PERIOD_OPTION, checkingPeriodOption); + assertNotEquals(CHECKING_PERIOD_OPTION.hashCode(), checkingPeriodOption.hashCode()); + timeoutOption = WaitForOption.timeout(42, TimeUnit.MILLISECONDS); + assertNotEquals(TIMEOUT_OPTION, timeoutOption); + assertNotEquals(TIMEOUT_OPTION.hashCode(), timeoutOption.hashCode()); + timeoutOption = WaitForOption.timeout(43, TimeUnit.SECONDS); + assertNotEquals(TIMEOUT_OPTION, timeoutOption); + assertNotEquals(TIMEOUT_OPTION.hashCode(), timeoutOption.hashCode()); + } + + @Test + public void testAsMap() { + Map optionMap = WaitForOption.asMap(CHECKING_PERIOD_OPTION, TIMEOUT_OPTION); + CheckingPeriod checkingPeriod = Option.CHECKING_PERIOD.getCheckingPeriod(optionMap); + assertEquals(42, checkingPeriod.period()); + assertEquals(TimeUnit.MILLISECONDS, checkingPeriod.unit()); + assertEquals(43, (long) Option.TIMEOUT.getLong(optionMap)); + } + + @Test + public void testAsMap_DuplicateOption() { + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage(String.format("Duplicate option %s", CHECKING_PERIOD_OPTION)); + WaitForOption.asMap(CHECKING_PERIOD_OPTION, CHECKING_PERIOD_OPTION); + } +} diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/CreateTableAndLoadData.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/CreateTableAndLoadData.java index 8dd76b0265f8..6772d79a73ca 100644 --- a/gcloud-java-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/CreateTableAndLoadData.java +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/bigquery/snippets/CreateTableAndLoadData.java @@ -33,6 +33,8 @@ import com.google.cloud.bigquery.TableId; import com.google.cloud.bigquery.TableInfo; +import java.util.concurrent.TimeoutException; + /** * A snippet for Google Cloud BigQuery showing how to get a BigQuery table or create it if it does * not exist. The snippet also starts a BigQuery job to load data into the table from a Cloud @@ -40,7 +42,7 @@ */ public class CreateTableAndLoadData { - public static void main(String... args) throws InterruptedException { + public static void main(String... args) throws InterruptedException, TimeoutException { BigQuery bigquery = BigQueryOptions.defaultInstance().service(); TableId tableId = TableId.of("dataset", "table"); Table table = bigquery.getTable(tableId); diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateAddressDiskAndInstance.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateAddressDiskAndInstance.java index 8b87302398e9..0a63865904e0 100644 --- a/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateAddressDiskAndInstance.java +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateAddressDiskAndInstance.java @@ -35,13 +35,15 @@ import com.google.cloud.compute.Operation; import com.google.cloud.compute.RegionAddressId; +import java.util.concurrent.TimeoutException; + /** * A snippet for Google Cloud Compute Engine showing how to create a disk and an address. The * snippet also shows how to create a virtual machine instance using the created disk and address. */ public class CreateAddressDiskAndInstance { - public static void main(String... args) throws InterruptedException { + public static void main(String... args) throws InterruptedException, TimeoutException { // Create a service object // Credentials are inferred from the environment. Compute compute = ComputeOptions.defaultInstance().service(); diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateInstance.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateInstance.java index 3608c29e8ee9..66c10bace269 100644 --- a/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateInstance.java +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateInstance.java @@ -28,12 +28,14 @@ import com.google.cloud.compute.NetworkInterface; import com.google.cloud.compute.Operation; +import java.util.concurrent.TimeoutException; + /** * A snippet for Google Cloud Compute Engine showing how to create a virtual machine instance. */ public class CreateInstance { - public static void main(String... args) throws InterruptedException { + public static void main(String... args) throws InterruptedException, TimeoutException { Compute compute = ComputeOptions.defaultInstance().service(); ImageId imageId = ImageId.of("debian-cloud", "debian-8-jessie-v20160329"); NetworkId networkId = NetworkId.of("default"); diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateSnapshot.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateSnapshot.java index 9e14904e86cc..35d19e38e18e 100644 --- a/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateSnapshot.java +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/compute/snippets/CreateSnapshot.java @@ -23,13 +23,15 @@ import com.google.cloud.compute.Operation; import com.google.cloud.compute.Snapshot; +import java.util.concurrent.TimeoutException; + /** * A snippet for Google Cloud Compute Engine showing how to create a snapshot of a disk if the disk * exists. */ public class CreateSnapshot { - public static void main(String... args) throws InterruptedException { + public static void main(String... args) throws InterruptedException, TimeoutException { Compute compute = ComputeOptions.defaultInstance().service(); DiskId diskId = DiskId.of("us-central1-a", "disk-name"); Disk disk = compute.getDisk(diskId, Compute.DiskOption.fields());