package jetbrains.buildServer.clouds.base.connector; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicBoolean; import jetbrains.buildServer.BaseTestCase; import jetbrains.buildServer.util.WaitFor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * Created by Sergey.Pak on 3/11/2016. */ @Test public class CloudAsyncTaskExecutorTest extends BaseTestCase { private CloudAsyncTaskExecutor myCloudAsyncTaskExecutor; @BeforeMethod @Override protected void setUp() throws Exception { super.setUp(); myCloudAsyncTaskExecutor = new CloudAsyncTaskExecutor("Test executor"); } public void should_not_stuck_all_queue_on_single_task_failure() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(2); final MyAsyncCloudTask task1 = new MyAsyncCloudTask("task1", new CloudTaskResult(), 1000, null); final MyAsyncCloudTask task3 = new MyAsyncCloudTask("task3", new CloudTaskResult(), 1000, null); final TaskCallbackHandler countdownHandler = new TaskCallbackHandler() { @Override public void onComplete() { latch.countDown(); } }; myCloudAsyncTaskExecutor.executeAsync(task1, countdownHandler); myCloudAsyncTaskExecutor.executeAsync( new MyAsyncCloudTask("task2", new CloudTaskResult(), 5000, new NullPointerException()), countdownHandler); myCloudAsyncTaskExecutor.executeAsync(task3, countdownHandler); assertTrue(latch.await(2, TimeUnit.SECONDS)); } private static class MyAsyncCloudTask implements AsyncCloudTask { private String myName; private long myStartDate; private CloudTaskResult myResult; private final long myTaskTime; private final Throwable myException; public MyAsyncCloudTask(String name, CloudTaskResult result, long time, Throwable exception) { myName = name; myResult = result; myTaskTime = time; myException = exception; myStartDate = System.currentTimeMillis(); } @Override public Future<CloudTaskResult> executeOrGetResultAsync() { return new FutureTask<CloudTaskResult>(new Runnable() { @Override public void run() { } }, myResult) { @Override public CloudTaskResult get() throws InterruptedException, ExecutionException { final long millis = myTaskTime - (System.currentTimeMillis() - myStartDate); if (millis > 0) { Thread.sleep(millis); } throwMyExceptionIfNecessary(); return myResult; } @Override public boolean isDone() { final long millis = myTaskTime - (System.currentTimeMillis() - myStartDate); try { throwMyExceptionIfNecessary(); } catch (ExecutionException | InterruptedException e) { e.printStackTrace(); } return millis < 0; } private void throwMyExceptionIfNecessary() throws ExecutionException, InterruptedException { if (myException != null) { if (myException instanceof ExecutionException) { throw (ExecutionException)myException; } else if (myException instanceof InterruptedException) { throw (InterruptedException)myException; } else { throw new RuntimeException(myException); } } } }; } @NotNull @Override public String getName() { return myName; } @Nullable @Override public long getStartTime() { return myStartDate; } } @AfterMethod @Override protected void tearDown() throws Exception { myCloudAsyncTaskExecutor.dispose(); super.tearDown(); } }