@SuppressWarnings("unchecked")
@Test
public void testFlowReconcilePipeLine() throws Exception {
flowReconcileMgr.flowReconcileEnabled = true;
IFlowReconcileListener r1 =
EasyMock.createNiceMock(IFlowReconcileListener.class);
IFlowReconcileListener r2 =
EasyMock.createNiceMock(IFlowReconcileListener.class);
IFlowReconcileListener r3 =
EasyMock.createNiceMock(IFlowReconcileListener.class);
expect(r1.getName()).andReturn("r1").anyTimes();
expect(r2.getName()).andReturn("r2").anyTimes();
expect(r3.getName()).andReturn("r3").anyTimes();
// Set the listeners' order: r1 -> r2 -> r3
expect(r1.isCallbackOrderingPrereq((OFType)anyObject(),
(String)anyObject())).andReturn(false).anyTimes();
expect(r1.isCallbackOrderingPostreq((OFType)anyObject(),
(String)anyObject())).andReturn(false).anyTimes();
expect(r2.isCallbackOrderingPrereq((OFType)anyObject(),
eq("r1"))).andReturn(true).anyTimes();
expect(r2.isCallbackOrderingPrereq((OFType)anyObject(),
eq("r3"))).andReturn(false).anyTimes();
expect(r2.isCallbackOrderingPostreq((OFType)anyObject(),
eq("r1"))).andReturn(false).anyTimes();
expect(r2.isCallbackOrderingPostreq((OFType)anyObject(),
eq("r3"))).andReturn(true).anyTimes();
expect(r3.isCallbackOrderingPrereq((OFType)anyObject(),
eq("r1"))).andReturn(false).anyTimes();
expect(r3.isCallbackOrderingPrereq((OFType)anyObject(),
eq("r2"))).andReturn(true).anyTimes();
expect(r3.isCallbackOrderingPostreq((OFType)anyObject(),
(String)anyObject())).andReturn(false).anyTimes();
expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject())).
andThrow(new RuntimeException("This is NOT an error! " +
"We are testing exception catching."));
SimpleCounter cnt = (SimpleCounter)SimpleCounter.createCounter(
new Date(),
CounterType.LONG);
cnt.increment();
expect(counterStore.getCounter(
flowReconcileMgr.controllerPktInCounterName))
.andReturn(cnt)
.anyTimes();
replay(r1, r2, r3, counterStore);
flowReconcileMgr.clearFlowReconcileListeners();
flowReconcileMgr.addFlowReconcileListener(r1);
flowReconcileMgr.addFlowReconcileListener(r2);
flowReconcileMgr.addFlowReconcileListener(r3);
int pre_flowReconcileThreadRunCount =
flowReconcileMgr.flowReconcileThreadRunCount.get();
Date startTime = new Date();
OFMatchReconcile ofmRcIn = new OFMatchReconcile();
try {
flowReconcileMgr.reconcileFlow(ofmRcIn,EventPriority.HIGH);
flowReconcileMgr.doReconcile();
} catch (RuntimeException e) {
assertEquals(e.getMessage()
.startsWith("This is NOT an error!"), true);
}
verify(r1, r2, r3);
// verify STOP works
reset(r1, r2, r3);
// restart reconcileThread since it exited due to previous runtime
// exception.
flowReconcileMgr.startUp(fmc);
expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.STOP).times(1);
expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()));
expectLastCall().andAnswer(new IAnswer<Object>() {
public Object answer() {
fail("Unexpected call");
return Command.STOP;
}
}).anyTimes();
pre_flowReconcileThreadRunCount =
flowReconcileMgr.flowReconcileThreadRunCount.get();
startTime = new Date();
replay(r1, r2, r3);
flowReconcileMgr.reconcileFlow(ofmRcIn,EventPriority.HIGH);
while (flowReconcileMgr.flowReconcileThreadRunCount.get() <=
pre_flowReconcileThreadRunCount) {
Thread.sleep(10);
Date currTime = new Date();
assertTrue((currTime.getTime() - startTime.getTime()) < 1000);
}
verify(r1, r2, r3);
// verify CONTINUE works
reset(r1, r2, r3);
expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.CONTINUE).times(1);
expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.STOP).times(1);
expect(r3.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()));
expectLastCall().andAnswer(new IAnswer<Object>() {
public Object answer() {
fail("Unexpected call");
return Command.STOP;
}
}).anyTimes();
pre_flowReconcileThreadRunCount =
flowReconcileMgr.flowReconcileThreadRunCount.get();
startTime = new Date();
replay(r1, r2, r3);
flowReconcileMgr.reconcileFlow(ofmRcIn,EventPriority.HIGH);
while (flowReconcileMgr.flowReconcileThreadRunCount.get() <=
pre_flowReconcileThreadRunCount) {
Thread.sleep(10);
Date currTime = new Date();
assertTrue((currTime.getTime() - startTime.getTime()) < 1000);
}
verify(r1, r2, r3);
// verify CONTINUE works
reset(r1, r2, r3);
expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.CONTINUE).times(1);
expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.CONTINUE).times(1);
expect(r3.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.STOP).times(1);
pre_flowReconcileThreadRunCount =
flowReconcileMgr.flowReconcileThreadRunCount.get();
startTime = new Date();
replay(r1, r2, r3);
flowReconcileMgr.reconcileFlow(ofmRcIn,EventPriority.HIGH);
while (flowReconcileMgr.flowReconcileThreadRunCount.get() <=
pre_flowReconcileThreadRunCount) {
Thread.sleep(10);
Date currTime = new Date();
assertTrue((currTime.getTime() - startTime.getTime()) < 1000);
}
verify(r1, r2, r3);
// Verify removeFlowReconcileListener
flowReconcileMgr.removeFlowReconcileListener(r1);
reset(r1, r2, r3);
expect(r1.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()));
expectLastCall().andAnswer(new IAnswer<Object>() {
public Object answer() {
fail("Unexpected call to a listener that is " +
"removed from the chain.");
return Command.STOP;
}
}).anyTimes();
expect(r2.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.CONTINUE).times(1);
expect(r3.reconcileFlows((ArrayList<OFMatchReconcile>)anyObject()))
.andReturn(Command.STOP).times(1);
pre_flowReconcileThreadRunCount =
flowReconcileMgr.flowReconcileThreadRunCount.get();
startTime = new Date();