diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index e7cc0f32..e83cf042 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -4,7 +4,7 @@ import com.cloudinary.api.ApiResponse; import com.cloudinary.api.exceptions.BadRequest; import com.cloudinary.api.exceptions.NotFound; -import com.cloudinary.metadata.StringMetadataField; +import com.cloudinary.test.rules.RetryRule; import com.cloudinary.transformation.TextLayer; import com.cloudinary.utils.ObjectUtils; import org.junit.*; @@ -53,6 +53,8 @@ abstract public class AbstractApiTest extends MockableTest { private static String assetId1; private static String assetId2; + private static final int SLEEP_TIMEOUT = 5000; + protected Api api; @@ -137,6 +139,9 @@ public static void tearDownClass() { @Rule public TestName currentTest = new TestName(); + @Rule + public RetryRule retryRule = new RetryRule(); + @Before public void setUp() { System.out.println("Running " + this.getClass().getName() + "." + currentTest.getMethodName()); @@ -909,8 +914,10 @@ public void testRestoreDifferentVersionsOfDeletedAsset() throws Exception { "tags", UPLOAD_TAGS )); assertEquals(firstUpload.get("public_id"), TEST_RESOURCE_PUBLIC_ID); + Thread.sleep(SLEEP_TIMEOUT); ApiResponse firstDelete = api.deleteResources(Collections.singletonList(TEST_RESOURCE_PUBLIC_ID), ObjectUtils.emptyMap()); assertTrue(firstDelete.containsKey("deleted")); + Thread.sleep(SLEEP_TIMEOUT); Map secondUpload = uploader.upload(SRC_TEST_IMAGE, ObjectUtils.asMap( @@ -920,13 +927,15 @@ public void testRestoreDifferentVersionsOfDeletedAsset() throws Exception { "tags", UPLOAD_TAGS )); assertEquals(secondUpload.get("public_id"), TEST_RESOURCE_PUBLIC_ID); + Thread.sleep(SLEEP_TIMEOUT); ApiResponse secondDelete = api.deleteResources(Collections.singletonList(TEST_RESOURCE_PUBLIC_ID), ObjectUtils.emptyMap()); assertTrue(secondDelete.containsKey("deleted")); - + Thread.sleep(SLEEP_TIMEOUT); assertNotEquals(firstUpload.get("bytes"), secondUpload.get("bytes")); ApiResponse getVersionsResp = api.resource(TEST_RESOURCE_PUBLIC_ID, ObjectUtils.asMap("versions", true)); List versions = (List) getVersionsResp.get("versions"); + Assert.assertTrue(versions.size() > 1); Object firstAssetVersion = versions.get(0).get("version_id"); Object secondAssetVersion = versions.get(1).get("version_id"); @@ -937,7 +946,7 @@ public void testRestoreDifferentVersionsOfDeletedAsset() throws Exception { ApiResponse secondVerRestore = api.restore(Collections.singletonList(TEST_RESOURCE_PUBLIC_ID), ObjectUtils.asMap("versions", Collections.singletonList(secondAssetVersion))); assertEquals(((Map) secondVerRestore.get(TEST_RESOURCE_PUBLIC_ID)).get("bytes"), secondUpload.get("bytes")); - + Thread.sleep(SLEEP_TIMEOUT); ApiResponse finalDeleteResp = api.deleteResources(Collections.singletonList(TEST_RESOURCE_PUBLIC_ID), ObjectUtils.emptyMap()); assertTrue(finalDeleteResp.containsKey("deleted")); } @@ -1157,7 +1166,7 @@ public void testQualityAnalysis() throws Exception { public void testDeleteFolder() throws Exception { String toDelete = "todelete_" + SUFFIX; Map uploadResult = cloudinary.uploader().upload(SRC_TEST_IMAGE, asMap("tags", UPLOAD_TAGS, "folder", toDelete)); - Thread.sleep(5000); + Thread.sleep(SLEEP_TIMEOUT); api.deleteResources(Collections.singletonList(uploadResult.get("public_id").toString()), emptyMap()); ApiResponse result = api.deleteFolder(toDelete, emptyMap()); assertTrue(((ArrayList) result.get("deleted")).contains(toDelete)); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java index 42303df1..2194afaf 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java @@ -3,6 +3,7 @@ import com.cloudinary.*; import com.cloudinary.api.ApiResponse; import com.cloudinary.metadata.StringMetadataField; +import com.cloudinary.test.rules.RetryRule; import com.cloudinary.utils.ObjectUtils; import com.cloudinary.utils.Rectangle; import org.cloudinary.json.JSONArray; @@ -81,6 +82,9 @@ public static void tearDownClass() { @Rule public TestName currentTest = new TestName(); + @Rule + public RetryRule retryRule = new RetryRule(); + @Before public void setUp() { System.out.println("Running " + this.getClass().getName() + "." + currentTest.getMethodName()); diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/rules/RetryRule.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/rules/RetryRule.java new file mode 100644 index 00000000..4d407610 --- /dev/null +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/rules/RetryRule.java @@ -0,0 +1,47 @@ +package com.cloudinary.test.rules; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.util.Objects; + +public class RetryRule implements TestRule { + private int retryCount; + private int delay; + + public RetryRule(int retryCount, int delay) { + this.retryCount = retryCount; + this.delay = delay; + } + + public RetryRule() { + this.retryCount = 3; + this.delay = 3; + } + + public Statement apply(Statement base, Description description) { + return statement(base, description); + } + + private Statement statement(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Throwable caughtThrowable = null; + for (int i = 0; i < retryCount; i++) { + try { + base.evaluate(); + return; + } catch (Throwable t) { + caughtThrowable = t; + System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed."); + Thread.sleep(delay * 1000); + } + } + System.err.println(description.getDisplayName() + ": Giving up after " + retryCount + " failures."); + throw Objects.requireNonNull(caughtThrowable); + } + }; + } +}