X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=mdsalutil%2Fmdsalutil-api%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fgenius%2Fmdsalutil%2Finterfaces%2Ftestutils%2FTestIMdsalApiManager.java;h=a6707428baf9fdf2130a226231463f62c2bca1c6;hb=d57cb92801374e693e09f988be38f0996adad697;hp=3e58e65b4cc51e30a2877251d5e3f4ecca0af7fc;hpb=87b92e9b662b634a06144a51d7d2f29ac757ecf6;p=genius.git diff --git a/mdsalutil/mdsalutil-api/src/test/java/org/opendaylight/genius/mdsalutil/interfaces/testutils/TestIMdsalApiManager.java b/mdsalutil/mdsalutil-api/src/test/java/org/opendaylight/genius/mdsalutil/interfaces/testutils/TestIMdsalApiManager.java index 3e58e65b4..a6707428b 100644 --- a/mdsalutil/mdsalutil-api/src/test/java/org/opendaylight/genius/mdsalutil/interfaces/testutils/TestIMdsalApiManager.java +++ b/mdsalutil/mdsalutil-api/src/test/java/org/opendaylight/genius/mdsalutil/interfaces/testutils/TestIMdsalApiManager.java @@ -7,9 +7,12 @@ */ package org.opendaylight.genius.mdsalutil.interfaces.testutils; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertTrue; +import static org.opendaylight.mdsal.binding.testutils.AssertDataObjects.assertEqualBeans; import static org.opendaylight.yangtools.testutils.mockito.MoreAnswers.realOrException; +import com.google.common.collect.ComparisonChain; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -17,12 +20,14 @@ import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.Futures; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.mockito.Mockito; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.genius.mdsalutil.FlowEntity; import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager; -import org.opendaylight.mdsal.binding.testutils.AssertDataObjects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Fake IMdsalApiManager useful for tests. @@ -39,6 +44,8 @@ import org.opendaylight.mdsal.binding.testutils.AssertDataObjects; */ public abstract class TestIMdsalApiManager implements IMdsalApiManager { + private static final Logger LOG = LoggerFactory.getLogger(TestIMdsalApiManager.class); + private List flows; public static TestIMdsalApiManager newInstance() { @@ -62,13 +69,75 @@ public abstract class TestIMdsalApiManager implements IMdsalApiManager { } public synchronized void assertFlows(Iterable expectedFlows) { + checkNonEmptyFlows(expectedFlows); List nonNullFlows = getOrNewFlows(); if (!Iterables.isEmpty(expectedFlows)) { assertTrue("No Flows created (bean wiring may be broken?)", !nonNullFlows.isEmpty()); } // TODO Support Iterable <-> List directly within XtendBeanGenerator List expectedFlowsAsNewArrayList = Lists.newArrayList(expectedFlows); - AssertDataObjects.assertEqualBeans(expectedFlowsAsNewArrayList, nonNullFlows); + assertEqualBeans(expectedFlowsAsNewArrayList, nonNullFlows); + } + + + private synchronized void checkNonEmptyFlows(Iterable expectedFlows) { + if (!Iterables.isEmpty(expectedFlows)) { + assertTrue("No Flows created (bean wiring may be broken?)", !getOrNewFlows().isEmpty()); + } + } + + public synchronized void assertFlowsInAnyOrder(Iterable expectedFlows) { + checkNonEmptyFlows(expectedFlows); + // TODO Support Iterable <-> List directly within XtendBeanGenerator + List expectedFlowsAsNewArrayList = Lists.newArrayList(expectedFlows); + + List sortedFlows = sortFlows(flows); + List sortedExpectedFlows = sortFlows(expectedFlowsAsNewArrayList); + + // FYI: This containsExactlyElementsIn() assumes that FlowEntity, and everything in it, + // has correctly working equals() implementations. assertEqualBeans() does not assume + // that, and would work even without equals, because it only uses property reflection. + // Normally this will lead to the same result, but if one day it doesn't (because of + // a bug in an equals() implementation somewhere), then it's worth to keep this diff + // in mind. + + // FTR: This use of G Truth and then catch AssertionError and using assertEqualBeans iff NOK + // (thus discarding the message from G Truth) is a bit of a hack, but it works well... + // If you're tempted to improve this, please remember that correctly re-implementing + // containsExactlyElementsIn (or Hamcrest's similar containsInAnyOrder) isn't a 1 line + // trivia... e.g. a.containsAll(b) && b.containsAll(a) isn't sufficient, because it + // won't work for duplicates (which we frequently have here); and ordering before is + // not viable because FlowEntity is not Comparable, and Comparator based on hashCode + // is not a good idea (different instances can have same hashCode), and e.g. on + // System#identityHashCode even less so. + try { + assertThat(sortedFlows).containsExactlyElementsIn(sortedExpectedFlows); + } catch (AssertionError e) { + // We LOG the AssertionError just for clarity why containsExactlyElementsIn() failed + LOG.warn("assert containsExactlyElementsIn() failed", e); + // We LOG the expected and actual flow in case of a failed assertion + // because, even though that is typically just a HUGE String that's + // hard to read (the diff printed subsequently by assertEqualBeans + // is, much, more readable), there are cases when looking more closely + // at the full toString() output of the flows is still useful, so: + LOG.warn("assert failed [order ignored!]; expected flows: {}", sortedExpectedFlows); + LOG.warn("assert failed [order ignored!]; actual flows : {}", sortedFlows); + // The point of this is basically just that our assertEqualBeans output, + // in case of a comparison failure, is *A LOT* more clearly readable + // than what G Truth (or Hamcrest) can do based on toString. + assertEqualBeans(sortedExpectedFlows, sortedFlows); + } + } + + private List sortFlows(Iterable flowsToSort) { + List sortedFlows = Lists.newArrayList(flowsToSort); + Collections.sort(sortedFlows, + (flow1, flow2) -> ComparisonChain.start() + .compare(flow1.getTableId(), flow2.getTableId()) + .compare(flow1.getPriority(), flow2.getPriority()) + .compare(flow1.getFlowId(), flow2.getFlowId()) + .result()); + return sortedFlows; } @Override @@ -76,6 +145,13 @@ public abstract class TestIMdsalApiManager implements IMdsalApiManager { getOrNewFlows().add(flowEntity); } + @Override + public synchronized CheckedFuture installFlow(BigInteger dpId, + FlowEntity flowEntity) { + installFlow(flowEntity); + return Futures.immediateCheckedFuture(null); + } + @Override public synchronized CheckedFuture removeFlow(BigInteger dpnId, FlowEntity flowEntity) { @@ -83,4 +159,14 @@ public abstract class TestIMdsalApiManager implements IMdsalApiManager { return Futures.immediateCheckedFuture(null); } + @Override + public synchronized void batchedAddFlow(BigInteger dpId, FlowEntity flowEntity) { + getOrNewFlows().add(flowEntity); + } + + @Override + public synchronized void batchedRemoveFlow(BigInteger dpId, FlowEntity flowEntity) { + getOrNewFlows().remove(flowEntity); + } + }