diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/RolloutManagementTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/RolloutManagementTest.java index a405e7b7d..22f9ee8b4 100644 --- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/RolloutManagementTest.java +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/RolloutManagementTest.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.Callable; import org.eclipse.hawkbit.AbstractIntegrationTest; import org.eclipse.hawkbit.TestDataUtil; @@ -34,6 +35,8 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.rsql.RSQLUtility; +import org.eclipse.hawkbit.repository.utils.MultipleInvokeHelper; +import org.eclipse.hawkbit.repository.utils.SuccessCondition; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Description; @@ -859,7 +862,7 @@ public class RolloutManagementTest extends AbstractIntegrationTest { @Test @Description("Verify the creation and the start of a rollout in asynchronous mode.") - public void createAndStartRolloutInAsync() { + public void createAndStartRolloutInAsync() throws Exception { final int amountTargetsForRollout = 500; final int amountGroups = 5; @@ -883,31 +886,18 @@ public class RolloutManagementTest extends AbstractIntegrationTest { myRollout = rolloutManagement.createRolloutAsync(myRollout, amountGroups, conditions); - int counter = 1; - int counterMax = 10; - while (!isRolloutInGivenStatus(myRollout.getId(), RolloutStatus.READY) && (counter <= counterMax)) { - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - counter++; - } + SuccessConditionRolloutStatus conditionRolloutTargetCount = new SuccessConditionRolloutStatus( + RolloutStatus.READY); + assertThat(MultipleInvokeHelper.doWithTimeout(new RolloutStatusCallable(myRollout.getId()), + conditionRolloutTargetCount, 15000, 500)).as("Rollout status").isNotNull(); myRollout = rolloutManagement.findRolloutById(myRollout.getId()); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.READY); rolloutManagement.startRolloutAsync(myRollout); - counter = 1; - counterMax = 10; - while (!isRolloutInGivenStatus(myRollout.getId(), RolloutStatus.RUNNING) && counter <= counterMax) { - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - counter++; - } + conditionRolloutTargetCount = new SuccessConditionRolloutStatus(RolloutStatus.RUNNING); + assertThat(MultipleInvokeHelper.doWithTimeout(new RolloutStatusCallable(myRollout.getId()), + conditionRolloutTargetCount, 15000, 500)).as("Rollout status").isNotNull(); myRollout = rolloutManagement.findRolloutById(myRollout.getId()); assertThat(myRollout.getStatus()).isEqualTo(RolloutStatus.RUNNING); @@ -917,14 +907,6 @@ public class RolloutManagementTest extends AbstractIntegrationTest { validateRolloutActionStatus(myRollout.getId(), expectedTargetCountStatus); } - private boolean isRolloutInGivenStatus(final Long rolloutID, final RolloutStatus status) { - final Rollout myRollout = rolloutManagement.findRolloutById(rolloutID); - if (myRollout.getStatus() == status) { - return true; - } - return false; - } - private void validateRolloutGroupActionStatus(final RolloutGroup rolloutGroup, final Map expectedTargetCountStatus) { final RolloutGroup rolloutGroupWithDetail = rolloutGroupManagement @@ -1021,4 +1003,35 @@ public class RolloutManagementTest extends AbstractIntegrationTest { return map; } + private static class SuccessConditionRolloutStatus implements SuccessCondition { + + private final RolloutStatus rolloutStatus; + + public SuccessConditionRolloutStatus(final RolloutStatus rolloutStatus) { + this.rolloutStatus = rolloutStatus; + } + + @Override + public boolean success(final RolloutStatus result) { + return result.equals(rolloutStatus); + } + } + + private class RolloutStatusCallable implements Callable { + + final Long rolloutId; + + RolloutStatusCallable(final Long rolloutId) { + this.rolloutId = rolloutId; + } + + @Override + public RolloutStatus call() throws Exception { + + final Rollout myRollout = rolloutManagement.findRolloutById(rolloutId); + return myRollout.getStatus(); + + } + } + } diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/utils/MultipleInvokeHelper.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/utils/MultipleInvokeHelper.java new file mode 100644 index 000000000..362636547 --- /dev/null +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/utils/MultipleInvokeHelper.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2011-2016 Bosch Software Innovations GmbH, Germany. All rights reserved. + */ +package org.eclipse.hawkbit.repository.utils; + +import java.util.concurrent.Callable; + +/** + * Helper to call a request multiple times regarding a given condition until + * timeout is reached. + * + * @author Jonathan Knoblauch + * + */ +public final class MultipleInvokeHelper { + + /** + * Call with timeout until result is not null. + * + * @param callable + * class + * @param timeout + * value + * @param pollInterval + * value + * @return + * @throws Exception + */ + public static T doWithTimeoutUntilResultIsNotNull(final Callable callable, final long timeout, + final long pollInterval) throws Exception // NOPMD + { + return doWithTimeout(callable, new SuccessCondition() { + @Override + public boolean success(final T result) { + return result != null; + }; + }, timeout, pollInterval); + } + + /** + * Call with timeout. + * + * @param callable + * class + * @param successCondition + * class + * @param timeout + * value + * @param pollInterval + * value + * @return + * @throws Exception + */ + public static T doWithTimeout(final Callable callable, final SuccessCondition successCondition, + final long timeout, final long pollInterval) throws Exception // NOPMD + { + + if (pollInterval < 0) { + throw new IllegalArgumentException("pollInterval must non negative"); + } + + long duration = 0; + Exception exception = null; + T returnValue = null; + while (untilTimeoutReached(timeout, duration)) { + try { + returnValue = callable.call(); + // clear exception + exception = null; + } catch (final Exception ex) { + exception = ex; + } + Thread.sleep(pollInterval); + duration += pollInterval > 0 ? pollInterval : 1; + if (exception == null && successCondition.success(returnValue)) { + return returnValue; + } else { + returnValue = null; + } + } + if (exception != null) { + throw exception; + } + return returnValue; + } + + private static boolean untilTimeoutReached(final long timeout, final long duration) { + return duration <= timeout || timeout < 0; + } + +} diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/utils/SuccessCondition.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/utils/SuccessCondition.java new file mode 100644 index 000000000..a22cdbdfe --- /dev/null +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/utils/SuccessCondition.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved. + */ +package org.eclipse.hawkbit.repository.utils; + +/** + * SuccessCondition Interface. + * + * @author Dennis Melzer + * + * @param + * type of the value to get verified + */ +public interface SuccessCondition { + + /** + * The implementation of the success condition. + * + * @param result + * @return + */ + boolean success(final T result); + +}