Updates related to SDN-IP submitting intent operations:
* Updated IntentSynchronizer.submitPeerIntents() to use intent batch
operation
* Refactored the SDN-IP unit tests:
The verification for intent service operations is moved to a new class
TestIntentServiceHeler
Change-Id: Id6766ebb4d6bf492e8f9787c2c2247ac38d42964
diff --git a/apps/sdnip/src/test/java/org/onlab/onos/sdnip/TestIntentServiceHelper.java b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/TestIntentServiceHelper.java
new file mode 100644
index 0000000..4cc9053
--- /dev/null
+++ b/apps/sdnip/src/test/java/org/onlab/onos/sdnip/TestIntentServiceHelper.java
@@ -0,0 +1,213 @@
+package org.onlab.onos.sdnip;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.easymock.IArgumentMatcher;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.intent.IntentOperation;
+import org.onlab.onos.net.intent.IntentOperations;
+import org.onlab.onos.net.intent.PointToPointIntent;
+import org.onlab.onos.sdnip.IntentSynchronizer.IntentKey;
+
+import static org.easymock.EasyMock.reportMatcher;
+
+/**
+ * Helper class for testing operations submitted to the IntentService.
+ */
+public final class TestIntentServiceHelper {
+ /**
+ * Default constructor to prevent instantiation.
+ */
+ private TestIntentServiceHelper() {
+ }
+
+ /**
+ * Matcher method to set the expected intent operations to match against
+ * (ignoring the intent ID for each intent).
+ *
+ * @param intentOperations the expected Intent Operations
+ * @return the submitted Intent Operations
+ */
+ static IntentOperations eqExceptId(IntentOperations intentOperations) {
+ reportMatcher(new IdAgnosticIntentOperationsMatcher(intentOperations));
+ return intentOperations;
+ }
+
+
+ /**
+ * Matcher method to set an expected point-to-point intent to match
+ * against (ignoring the intent ID).
+ *
+ * @param intent the expected point-to-point intent
+ * @return the submitted point-to-point intent
+ */
+ private static PointToPointIntent eqExceptId(
+ PointToPointIntent intent) {
+ reportMatcher(new IdAgnosticPointToPointIntentMatcher(intent));
+ return intent;
+ }
+
+ /*
+ * EasyMock matcher that matches {@link IntenOperations} but
+ * ignores the {@link IntentId} when matching.
+ * <p/>
+ * The normal intent equals method tests that the intent IDs are equal,
+ * however in these tests we can't know what the intent IDs will be in
+ * advance, so we can't set up expected intents with the correct IDs. Thus,
+ * the solution is to use an EasyMock matcher that verifies that all the
+ * value properties of the provided intent match the expected values, but
+ * ignores the intent ID when testing equality.
+ */
+ private static final class IdAgnosticIntentOperationsMatcher implements
+ IArgumentMatcher {
+
+ private final IntentOperations intentOperations;
+ private String providedString;
+
+ /**
+ * Constructor taking the expected intent operations to match against.
+ *
+ * @param intentOperations the expected intent operations
+ */
+ public IdAgnosticIntentOperationsMatcher(
+ IntentOperations intentOperations) {
+ this.intentOperations = intentOperations;
+ }
+
+ @Override
+ public void appendTo(StringBuffer strBuffer) {
+ strBuffer.append("IntentOperationsMatcher unable to match: "
+ + providedString);
+ }
+
+ @Override
+ public boolean matches(Object object) {
+ if (!(object instanceof IntentOperations)) {
+ return false;
+ }
+
+ IntentOperations providedIntentOperations =
+ (IntentOperations) object;
+ providedString = providedIntentOperations.toString();
+
+ List<IntentKey> thisSubmitIntents = new LinkedList<>();
+ List<IntentId> thisWithdrawIntentIds = new LinkedList<>();
+ List<IntentKey> thisReplaceIntents = new LinkedList<>();
+ List<IntentKey> thisUpdateIntents = new LinkedList<>();
+ List<IntentKey> providedSubmitIntents = new LinkedList<>();
+ List<IntentId> providedWithdrawIntentIds = new LinkedList<>();
+ List<IntentKey> providedReplaceIntents = new LinkedList<>();
+ List<IntentKey> providedUpdateIntents = new LinkedList<>();
+
+ extractIntents(intentOperations, thisSubmitIntents,
+ thisWithdrawIntentIds, thisReplaceIntents,
+ thisUpdateIntents);
+ extractIntents(providedIntentOperations, providedSubmitIntents,
+ providedWithdrawIntentIds, providedReplaceIntents,
+ providedUpdateIntents);
+
+ return CollectionUtils.isEqualCollection(thisSubmitIntents,
+ providedSubmitIntents) &&
+ CollectionUtils.isEqualCollection(thisWithdrawIntentIds,
+ providedWithdrawIntentIds) &&
+ CollectionUtils.isEqualCollection(thisUpdateIntents,
+ providedUpdateIntents) &&
+ CollectionUtils.isEqualCollection(thisReplaceIntents,
+ providedReplaceIntents);
+ }
+
+ /**
+ * Extracts the intents per operation type. Each intent is encapsulated
+ * in IntentKey so it can be compared by excluding the Intent ID.
+ *
+ * @param intentOperations the container with the intent operations
+ * to extract the intents from
+ * @param submitIntents the SUBMIT intents
+ * @param withdrawIntentIds the WITHDRAW intents IDs
+ * @param replaceIntents the REPLACE intents
+ * @param updateIntents the UPDATE intens
+ */
+ private void extractIntents(IntentOperations intentOperations,
+ List<IntentKey> submitIntents,
+ List<IntentId> withdrawIntentIds,
+ List<IntentKey> replaceIntents,
+ List<IntentKey> updateIntents) {
+ for (IntentOperation oper : intentOperations.operations()) {
+ IntentId intentId;
+ IntentKey intentKey;
+ switch (oper.type()) {
+ case SUBMIT:
+ intentKey = new IntentKey(oper.intent());
+ submitIntents.add(intentKey);
+ break;
+ case WITHDRAW:
+ intentId = oper.intentId();
+ withdrawIntentIds.add(intentId);
+ break;
+ case REPLACE:
+ intentKey = new IntentKey(oper.intent());
+ replaceIntents.add(intentKey);
+ break;
+ case UPDATE:
+ intentKey = new IntentKey(oper.intent());
+ updateIntents.add(intentKey);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * EasyMock matcher that matches {@link PointToPointIntent}s but
+ * ignores the {@link IntentId} when matching.
+ * <p/>
+ * The normal intent equals method tests that the intent IDs are equal,
+ * however in these tests we can't know what the intent IDs will be in
+ * advance, so we can't set up expected intents with the correct IDs. Thus,
+ * the solution is to use an EasyMock matcher that verifies that all the
+ * value properties of the provided intent match the expected values, but
+ * ignores the intent ID when testing equality.
+ */
+ private static final class IdAgnosticPointToPointIntentMatcher implements
+ IArgumentMatcher {
+
+ private final PointToPointIntent intent;
+ private String providedIntentString;
+
+ /**
+ * Constructor taking the expected intent to match against.
+ *
+ * @param intent the expected intent
+ */
+ public IdAgnosticPointToPointIntentMatcher(PointToPointIntent intent) {
+ this.intent = intent;
+ }
+
+ @Override
+ public void appendTo(StringBuffer strBuffer) {
+ strBuffer.append("PointToPointIntentMatcher unable to match: "
+ + providedIntentString);
+ }
+
+ @Override
+ public boolean matches(Object object) {
+ if (!(object instanceof PointToPointIntent)) {
+ return false;
+ }
+
+ PointToPointIntent providedIntent = (PointToPointIntent) object;
+ providedIntentString = providedIntent.toString();
+
+ PointToPointIntent matchIntent =
+ new PointToPointIntent(providedIntent.appId(),
+ intent.selector(), intent.treatment(),
+ intent.ingressPoint(), intent.egressPoint());
+
+ return matchIntent.equals(providedIntent);
+ }
+ }
+}