Ray Milkey
Committed by Gerrit Code Review

Intent manager unit test enhancements

- add test to be sure that all flows are removed when intents
  are withdrawn
- add test to be sure that all flows are removed when an intent
  installation fails. Currently disabled, intent cleanup is
  not implemented
- enable installation time out test

Change-Id: I8c7a75292a97404ef89856647c67ef2f70ffcf6f
......@@ -330,18 +330,23 @@ public class IntentTestsMocks {
new IntentTestsMocks.MockTreatment();
public static class MockFlowRule implements FlowRule {
static int nextId = 0;
int priority;
Type type;
long timestamp;
int id;
public MockFlowRule(int priority) {
this.priority = priority;
this.type = Type.DEFAULT;
this.timestamp = System.currentTimeMillis();
this.id = nextId++;
}
@Override
public FlowId id() {
return FlowId.valueOf(1);
return FlowId.valueOf(id);
}
@Override
......@@ -398,7 +403,8 @@ public class IntentTestsMocks {
return false;
}
final MockFlowRule other = (MockFlowRule) obj;
return Objects.equals(this.priority, other.priority);
return Objects.equals(this.timestamp, other.timestamp) &&
this.id == other.id;
}
@Override
......
......@@ -23,6 +23,8 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
......@@ -57,6 +59,7 @@ import com.google.common.collect.Sets;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
......@@ -164,6 +167,18 @@ public class IntentManagerTest {
}
}
private static class TestIntentCompilerMultipleFlows implements IntentCompiler<MockIntent> {
@Override
public List<Intent> compile(MockIntent intent, List<Intent> installable,
Set<LinkResourceAllocations> resources) {
return IntStream.rangeClosed(1, 5)
.mapToObj(mock -> (new MockInstallableIntent()))
.collect(Collectors.toList());
}
}
private static class TestIntentCompilerError implements IntentCompiler<MockIntent> {
@Override
public List<Intent> compile(MockIntent intent, List<Intent> installable,
......@@ -173,7 +188,7 @@ public class IntentManagerTest {
}
/**
* Hamcrest matcher to check that a conllection of Intents contains an
* Hamcrest matcher to check that a collection of Intents contains an
* Intent with the specified Intent Id.
*/
public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
......@@ -375,7 +390,6 @@ public class IntentManagerTest {
* Tests handling a future that contains an unresolvable error as a result of
* installing an intent.
*/
@Ignore("test needs to be rewritten, so that the intent is resubmitted")
@Test
public void errorIntentInstallNeverTrue() {
final Long id = MockIntent.nextId();
......@@ -489,4 +503,78 @@ public class IntentManagerTest {
assertThat(intents, hasIntentWithId(intent2.id()));
verifyState();
}
/**
* Tests that removing all intents results in no flows remaining.
*/
@Test
public void testFlowRemoval() {
List<Intent> intents;
flowRuleService.setFuture(true);
intents = Lists.newArrayList(service.getIntents());
assertThat(intents, hasSize(0));
final MockIntent intent1 = new MockIntent(MockIntent.nextId());
final MockIntent intent2 = new MockIntent(MockIntent.nextId());
listener.setLatch(1, Type.INSTALL_REQ);
listener.setLatch(1, Type.INSTALLED);
service.submit(intent1);
listener.await(Type.INSTALL_REQ);
listener.await(Type.INSTALLED);
listener.setLatch(1, Type.INSTALL_REQ);
listener.setLatch(1, Type.INSTALLED);
service.submit(intent2);
listener.await(Type.INSTALL_REQ);
listener.await(Type.INSTALLED);
assertThat(listener.getCounts(Type.INSTALLED), is(2));
assertThat(flowRuleService.getFlowRuleCount(), is(2));
listener.setLatch(1, Type.WITHDRAWN);
service.withdraw(intent1);
listener.await(Type.WITHDRAWN);
listener.setLatch(1, Type.WITHDRAWN);
service.withdraw(intent2);
listener.await(Type.WITHDRAWN);
assertThat(listener.getCounts(Type.WITHDRAWN), is(2));
assertThat(flowRuleService.getFlowRuleCount(), is(0));
}
/**
* Tests that an intent that fails installation results in no flows remaining.
*/
@Test
@Ignore("Cleanup state is not yet implemented in the intent manager")
public void testFlowRemovalInstallError() {
final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
extensionService.registerCompiler(MockIntent.class, errorCompiler);
List<Intent> intents;
flowRuleService.setFuture(true);
flowRuleService.setErrorFlow(3);
intents = Lists.newArrayList(service.getIntents());
assertThat(intents, hasSize(0));
final MockIntent intent1 = new MockIntent(MockIntent.nextId());
listener.setLatch(1, Type.INSTALL_REQ);
listener.setLatch(1, Type.FAILED);
service.submit(intent1);
listener.await(Type.INSTALL_REQ);
listener.await(Type.FAILED);
assertThat(listener.getCounts(Type.FAILED), is(1));
assertThat(flowRuleService.getFlowRuleCount(), is(0));
}
}
......
......@@ -34,6 +34,11 @@ public class MockFlowRuleService extends FlowRuleServiceAdapter {
final Set<FlowRule> flows = Sets.newHashSet();
boolean success;
int errorFlow = -1;
public void setErrorFlow(int errorFlow) {
this.errorFlow = errorFlow;
}
public void setFuture(boolean success) {
this.success = success;
}
......@@ -41,6 +46,9 @@ public class MockFlowRuleService extends FlowRuleServiceAdapter {
@Override
public void apply(FlowRuleOperations ops) {
ops.stages().forEach(stage -> stage.forEach(flow -> {
if (errorFlow == flow.rule().id().value()) {
success = false;
} else {
switch (flow.type()) {
case ADD:
case MODIFY: //TODO is this the right behavior for modify?
......@@ -52,6 +60,7 @@ public class MockFlowRuleService extends FlowRuleServiceAdapter {
default:
break;
}
}
}));
if (success) {
ops.callback().onSuccess(ops);
......
......@@ -99,19 +99,19 @@ public class SimpleIntentStore
IntentData pendingData = pending.get(newData.key());
if (IntentData.isUpdateAcceptable(currentData, newData)) {
if (pendingData != null) {
if (pendingData.state() == PURGE_REQ) {
current.remove(newData.key(), newData);
} else {
current.put(newData.key(), new IntentData(newData));
}
if (pendingData != null
if (pendingData.version().compareTo(newData.version()) <= 0) {
// pendingData version is less than or equal to newData's
// Note: a new update for this key could be pending (it's version will be greater)
&& pendingData.version().compareTo(newData.version()) <= 0) {
pending.remove(newData.key());
}
}
notifyDelegateIfNotNull(IntentEvent.getEvent(newData));
}
}
......