[ONOS-6348] Intent installer redesign
Change-Id: I9ae2e8158dc1c686eaf848f330566f9dbb78405f
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/InstallCoordinatorTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/InstallCoordinatorTest.java
new file mode 100644
index 0000000..2bdf200
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/InstallCoordinatorTest.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.intent.impl;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.junit.TestTools;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentInstaller;
+import org.onosproject.net.intent.IntentOperationContext;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.TestInstallableIntent;
+import org.onosproject.store.intent.impl.IntentStoreAdapter;
+import org.onosproject.store.service.WallClockTimestamp;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for install coordinator.
+ */
+public class InstallCoordinatorTest {
+ private static final int INSTALL_DELAY = 100;
+ private static final int INSTALL_DURATION = 1000;
+ private static final IdGenerator ID_GENERATOR = new MockIdGenerator();
+
+ private InstallCoordinator installCoordinator;
+ private InstallerRegistry installerRegistry;
+ private TestIntentStore intentStore;
+ private TestIntentInstaller intentInstaller;
+
+
+ @Before
+ public void setup() {
+ Intent.unbindIdGenerator(ID_GENERATOR);
+ Intent.bindIdGenerator(ID_GENERATOR);
+ installerRegistry = new InstallerRegistry();
+ intentStore = new TestIntentStore();
+ intentInstaller = new TestIntentInstaller();
+ installerRegistry.registerInstaller(TestInstallableIntent.class, intentInstaller);
+
+ installCoordinator = new InstallCoordinator(installerRegistry, intentStore);
+ }
+
+ @After
+ public void tearDown() {
+ installerRegistry.unregisterInstaller(TestInstallableIntent.class);
+ Intent.unbindIdGenerator(ID_GENERATOR);
+ }
+
+ /**
+ * Installs test Intents.
+ */
+ @Test
+ public void testInstallIntent() {
+ IntentData toInstall = new IntentData(createTestIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ List<Intent> intents = Lists.newArrayList();
+ IntStream.range(0, 10).forEach(val -> {
+ intents.add(new TestInstallableIntent(val));
+ });
+ toInstall = new IntentData(toInstall, intents);
+ installCoordinator.installIntents(Optional.empty(), Optional.of(toInstall));
+ Intent toInstallIntent = toInstall.intent();
+ TestTools.assertAfter(INSTALL_DELAY, INSTALL_DURATION, () -> {
+ IntentData newData = intentStore.newData;
+ assertEquals(toInstallIntent, newData.intent());
+ assertEquals(IntentState.INSTALLED, newData.state());
+ assertEquals(intents, newData.installables());
+ });
+ }
+
+ /**
+ * Uninstalls test Intents.
+ */
+ @Test
+ public void testUninstallIntent() {
+ IntentData toUninstall = new IntentData(createTestIntent(),
+ IntentState.WITHDRAWING,
+ new WallClockTimestamp());
+ List<Intent> intents = Lists.newArrayList();
+
+ IntStream.range(0, 10).forEach(val -> {
+ intents.add(new TestInstallableIntent(val));
+ });
+
+ toUninstall = new IntentData(toUninstall, intents);
+
+ installCoordinator.installIntents(Optional.of(toUninstall), Optional.empty());
+ Intent toUninstallIntent = toUninstall.intent();
+ TestTools.assertAfter(INSTALL_DELAY, INSTALL_DURATION, () -> {
+ IntentData newData = intentStore.newData;
+ assertEquals(toUninstallIntent, newData.intent());
+ assertEquals(IntentState.WITHDRAWN, newData.state());
+ assertEquals(ImmutableList.of(), newData.installables());
+ });
+
+ }
+
+ /**
+ * Do both uninstall and install test Intents.
+ */
+ @Test
+ public void testUninstallAndInstallIntent() {
+ IntentData toUninstall = new IntentData(createTestIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ IntentData toInstall = new IntentData(createTestIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = Lists.newArrayList();
+
+ IntStream.range(0, 10).forEach(val -> {
+ intentsToUninstall.add(new TestInstallableIntent(val));
+ });
+
+ IntStream.range(10, 20).forEach(val -> {
+ intentsToInstall.add(new TestInstallableIntent(val));
+ });
+
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+ toInstall = new IntentData(toInstall, intentsToInstall);
+
+ installCoordinator.installIntents(Optional.of(toUninstall), Optional.of(toInstall));
+ Intent toInstallIntent = toInstall.intent();
+
+ TestTools.assertAfter(INSTALL_DELAY, INSTALL_DURATION, () -> {
+ IntentData newData = intentStore.newData;
+ assertEquals(toInstallIntent, newData.intent());
+ assertEquals(IntentState.INSTALLED, newData.state());
+ assertEquals(intentsToInstall, newData.installables());
+ });
+ }
+
+ /**
+ * Not uninstall nor install anything.
+ */
+ @Test
+ public void testInstallNothing() {
+ installCoordinator.installIntents(Optional.empty(), Optional.empty());
+ assertNull(intentStore.newData);
+ }
+
+ /**
+ * Test Intent install failed.
+ */
+ @Test
+ public void testInstallFailed() {
+ installerRegistry.unregisterInstaller(TestInstallableIntent.class);
+ installerRegistry.registerInstaller(TestInstallableIntent.class, new TestFailedIntentInstaller());
+ IntentData toUninstall = new IntentData(createTestIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ IntentData toInstall = new IntentData(createTestIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = Lists.newArrayList();
+
+ IntStream.range(0, 10).forEach(val -> {
+ intentsToUninstall.add(new TestInstallableIntent(val));
+ });
+
+ IntStream.range(10, 20).forEach(val -> {
+ intentsToInstall.add(new TestInstallableIntent(val));
+ });
+
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+ toInstall = new IntentData(toInstall, intentsToInstall);
+
+ installCoordinator.installIntents(Optional.of(toUninstall), Optional.of(toInstall));
+
+ Intent toUninstallIntent = toUninstall.intent();
+ TestTools.assertAfter(INSTALL_DELAY, INSTALL_DURATION, () -> {
+ IntentData newData = intentStore.newData;
+ assertEquals(toUninstallIntent, newData.intent());
+ assertEquals(IntentState.CORRUPT, newData.state());
+ assertEquals(intentsToUninstall, newData.installables());
+ });
+ }
+
+ /**
+ * Creates a test Intent.
+ *
+ * @return the test Intent.
+ */
+ private PointToPointIntent createTestIntent() {
+ FilteredConnectPoint ingress = new FilteredConnectPoint(ConnectPoint.deviceConnectPoint("s1/1"));
+ FilteredConnectPoint egress = new FilteredConnectPoint(ConnectPoint.deviceConnectPoint("s1/2"));
+ ApplicationId appId = TestApplicationId.create("test App");
+ return PointToPointIntent.builder()
+ .filteredIngressPoint(ingress)
+ .filteredEgressPoint(egress)
+ .appId(appId)
+ .key(Key.of("Test key", appId))
+ .build();
+ }
+
+ /**
+ * Test Intent store; records the newest Intent data.
+ */
+ class TestIntentStore extends IntentStoreAdapter {
+ IntentData newData;
+ @Override
+ public void write(IntentData newData) {
+ this.newData = newData;
+ }
+ }
+
+ /**
+ * Test Intent installer; always success for every Intent operation.
+ */
+ class TestIntentInstaller implements IntentInstaller<TestInstallableIntent> {
+ @Override
+ public void apply(IntentOperationContext<TestInstallableIntent> context) {
+ installCoordinator.success(context);
+ }
+ }
+
+ /**
+ * Test Intent installer; always failed for every Intent operation.
+ */
+ class TestFailedIntentInstaller implements IntentInstaller<TestInstallableIntent> {
+ @Override
+ public void apply(IntentOperationContext<TestInstallableIntent> context) {
+ installCoordinator.failed(context);
+ }
+ }
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java
index 585d3a0..45c90e7 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java
@@ -33,6 +33,9 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.impl.TestCoreManager;
import org.onosproject.net.NetworkResource;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
+import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompilationException;
@@ -42,7 +45,10 @@
import org.onosproject.net.intent.IntentEvent.Type;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.intent.IntentInstallCoordinator;
+import org.onosproject.net.intent.IntentInstaller;
import org.onosproject.net.intent.IntentListener;
+import org.onosproject.net.intent.IntentOperationContext;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
@@ -93,8 +99,11 @@
protected IntentService service;
protected IntentExtensionService extensionService;
+ protected IntentInstallCoordinator intentInstallCoordinator;
protected TestListener listener = new TestListener();
protected TestIntentCompiler compiler = new TestIntentCompiler();
+ protected TestIntentInstaller installer;
+ protected TestIntentTracker trackerService = new TestIntentTracker();
private static class TestListener implements IntentListener {
final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
@@ -217,6 +226,56 @@
}
}
+ public static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> {
+
+ protected IntentExtensionService intentExtensionService;
+ protected ObjectiveTrackerService trackerService;
+ protected IntentInstallCoordinator intentInstallCoordinator;
+ protected FlowRuleService flowRuleService;
+
+ public TestIntentInstaller(IntentExtensionService intentExtensionService,
+ ObjectiveTrackerService trackerService,
+ IntentInstallCoordinator intentInstallCoordinator,
+ FlowRuleService flowRuleService) {
+ this.intentExtensionService = intentExtensionService;
+ this.trackerService = trackerService;
+ this.intentInstallCoordinator = intentInstallCoordinator;
+ this.flowRuleService = flowRuleService;
+ }
+
+ @Override
+ public void apply(IntentOperationContext<MockInstallableIntent> context) {
+ List<MockInstallableIntent> uninstallIntents = context.intentsToUninstall();
+ List<MockInstallableIntent> installIntents = context.intentsToInstall();
+
+ FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
+
+ uninstallIntents.stream()
+ .map(FlowRuleIntent::flowRules)
+ .flatMap(Collection::stream)
+ .forEach(builder::remove);
+
+ installIntents.stream()
+ .map(FlowRuleIntent::flowRules)
+ .flatMap(Collection::stream)
+ .forEach(builder::add);
+
+ FlowRuleOperationsContext ctx = new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ intentInstallCoordinator.intentInstallSuccess(context);
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ intentInstallCoordinator.intentInstallFailed(context);
+ }
+ };
+
+ flowRuleService.apply(builder.build(ctx));
+ }
+ }
+
private static EntryForIntentMatcher hasIntentWithId(IntentId id) {
return new EntryForIntentMatcher(id);
}
@@ -227,17 +286,24 @@
flowRuleService = new MockFlowRuleService();
manager.store = new SimpleIntentStore();
injectEventDispatcher(manager, new TestEventDispatcher());
- manager.trackerService = new TestIntentTracker();
+ manager.trackerService = trackerService;
manager.flowRuleService = flowRuleService;
manager.coreService = new TestCoreManager();
manager.configService = mock(ComponentConfigService.class);
service = manager;
extensionService = manager;
+ intentInstallCoordinator = manager;
+
manager.activate();
service.addListener(listener);
extensionService.registerCompiler(MockIntent.class, compiler);
+ installer = new TestIntentInstaller(extensionService, trackerService,
+ intentInstallCoordinator, flowRuleService);
+
+ extensionService.registerInstaller(MockInstallableIntent.class, installer);
+
assertTrue("store should be empty",
Sets.newHashSet(service.getIntents()).isEmpty());
assertEquals(0L, flowRuleService.getFlowRuleCount());
@@ -269,6 +335,7 @@
@After
public void tearDown() {
extensionService.unregisterCompiler(MockIntent.class);
+ extensionService.unregisterInstaller(MockInstallableIntent.class);
service.removeListener(listener);
manager.deactivate();
// TODO null the other refs?
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/AbstractIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/AbstractIntentInstallerTest.java
new file mode 100644
index 0000000..caa07be
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/AbstractIntentInstallerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.intent.impl.installer;
+
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.ResourceGroup;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.IntentInstallCoordinator;
+import org.onosproject.net.intent.IntentOperationContext;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.impl.ObjectiveTrackerService;
+
+import static org.easymock.EasyMock.createMock;
+
+/**
+ * Abstract class to hold the common variables and pieces of code for Intent
+ * installer test.
+ */
+public class AbstractIntentInstallerTest {
+ protected static final ApplicationId APP_ID = TestApplicationId.create("IntentInstallerTest");
+ protected static final ConnectPoint CP1 = ConnectPoint.deviceConnectPoint("s1/1");
+ protected static final ConnectPoint CP2 = ConnectPoint.deviceConnectPoint("s1/2");
+ protected static final ConnectPoint CP3 = ConnectPoint.deviceConnectPoint("s1/3");
+ protected static final Key KEY1 = Key.of("test intent 1", APP_ID);
+ protected static final ResourceGroup RG1 = ResourceGroup.of("test resource group 1");
+ protected static final int DEFAULT_PRIORITY = 30000;
+ protected static final IdGenerator ID_GENERATOR = new MockIdGenerator();
+
+ protected IntentExtensionService intentExtensionService;
+ protected ObjectiveTrackerService trackerService;
+ protected TestIntentInstallCoordinator intentInstallCoordinator;
+
+ public void setup() {
+ Intent.unbindIdGenerator(ID_GENERATOR);
+ Intent.bindIdGenerator(ID_GENERATOR);
+ intentExtensionService = createMock(IntentExtensionService.class);
+ trackerService = createMock(ObjectiveTrackerService.class);
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ }
+
+ public void tearDown() {
+ Intent.unbindIdGenerator(ID_GENERATOR);
+ }
+
+ /**
+ * Creates point to point Intent for test.
+ *
+ * @return the point to point Intent
+ */
+ public PointToPointIntent createP2PIntent() {
+ PointToPointIntent intent;
+ TrafficSelector selector = DefaultTrafficSelector.emptySelector();
+ TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+
+ FilteredConnectPoint ingress = new FilteredConnectPoint(CP1);
+ FilteredConnectPoint egress = new FilteredConnectPoint(CP2);
+
+ intent = PointToPointIntent.builder()
+ .selector(selector)
+ .treatment(treatment)
+ .filteredIngressPoint(ingress)
+ .filteredEgressPoint(egress)
+ .appId(APP_ID)
+ .build();
+
+ return intent;
+ }
+
+ /**
+ * The Intent install coordinator for test.
+ * Records success and fail context.
+ */
+ class TestIntentInstallCoordinator implements IntentInstallCoordinator {
+
+ IntentOperationContext successContext;
+ IntentOperationContext failedContext;
+
+ @Override
+ public void intentInstallSuccess(IntentOperationContext context) {
+ successContext = context;
+ }
+
+ @Override
+ public void intentInstallFailed(IntentOperationContext context) {
+ failedContext = context;
+ }
+ }
+
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/DomainIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/DomainIntentInstallerTest.java
new file mode 100644
index 0000000..2542322
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/DomainIntentInstallerTest.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.intent.impl.installer;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.domain.DomainIntent;
+import org.onosproject.net.domain.DomainIntentOperations;
+import org.onosproject.net.domain.DomainIntentService;
+import org.onosproject.net.domain.DomainPointToPointIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentInstallationContext;
+import org.onosproject.net.intent.IntentOperationContext;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.store.service.WallClockTimestamp;
+
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for domain Intent installer.
+ */
+public class DomainIntentInstallerTest extends AbstractIntentInstallerTest {
+ protected DomainIntentInstaller installer;
+ protected TestDomainIntentService domainIntentService;
+
+ @Before
+ public void setup() {
+ super.setup();
+ domainIntentService = new TestDomainIntentService();
+ installer = new DomainIntentInstaller();
+ installer.domainIntentService = domainIntentService;
+ installer.trackerService = trackerService;
+ installer.intentExtensionService = intentExtensionService;
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+
+ installer.activated();
+ }
+
+ @After
+ public void tearDown() {
+ super.tearDown();
+ installer.deactivated();
+ }
+
+ /**
+ * Installs domain Intents.
+ */
+ @Test
+ public void testInstall() {
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createDomainIntents();
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentOperationContext<DomainIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.successContext, operationContext);
+ }
+
+ /**
+ * Uninstall domain Intents.
+ */
+ @Test
+ public void testUninstall() {
+ List<Intent> intentsToUninstall = createDomainIntents();
+ List<Intent> intentsToInstall = Lists.newArrayList();
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.WITHDRAWING,
+ new WallClockTimestamp());
+ IntentData toInstall = null;
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+ IntentOperationContext<DomainIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.successContext, operationContext);
+ }
+
+ /**
+ * Do both uninstall and install domain Intents.
+ */
+ @Test
+ public void testUninstallAndInstall() {
+ List<Intent> intentsToUninstall = createDomainIntents();
+ List<Intent> intentsToInstall = createAnotherDomainIntents();
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentOperationContext<DomainIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.successContext, operationContext);
+ }
+
+ /**
+ * Nothing to uninstall or install.
+ */
+ @Test
+ public void testNoAnyIntentToApply() {
+ IntentData toInstall = null;
+ IntentData toUninstall = null;
+ IntentOperationContext<DomainIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context);
+ installer.apply(operationContext);
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+ }
+
+ /**
+ * Test if domain Intent installation operations failed.
+ */
+ @Test
+ public void testInstallFailed() {
+ domainIntentService = new TestFailedDomainIntentService();
+ installer.domainIntentService = domainIntentService;
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createDomainIntents();
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentOperationContext<DomainIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.failedContext, operationContext);
+ }
+
+ /**
+ * Creates domain Intents.
+ *
+ * @return the domain Intents
+ */
+ private List<Intent> createDomainIntents() {
+ FilteredConnectPoint ingress = new FilteredConnectPoint(CP1);
+ FilteredConnectPoint egress = new FilteredConnectPoint(CP2);
+ DomainPointToPointIntent intent = DomainPointToPointIntent.builder()
+ .appId(APP_ID)
+ .key(KEY1)
+ .priority(DEFAULT_PRIORITY)
+ .filteredIngressPoint(ingress)
+ .filteredEgressPoint(egress)
+ .links(ImmutableList.of())
+ .build();
+
+ return ImmutableList.of(intent);
+ }
+
+ /**
+ * Create another domain Intents.
+ *
+ * @return the domain Intents
+ */
+ private List<Intent> createAnotherDomainIntents() {
+ FilteredConnectPoint ingress = new FilteredConnectPoint(CP1);
+ FilteredConnectPoint egress = new FilteredConnectPoint(CP3);
+ DomainPointToPointIntent intent = DomainPointToPointIntent.builder()
+ .appId(APP_ID)
+ .key(KEY1)
+ .priority(DEFAULT_PRIORITY)
+ .filteredIngressPoint(ingress)
+ .filteredEgressPoint(egress)
+ .links(ImmutableList.of())
+ .build();
+
+ return ImmutableList.of(intent);
+ }
+
+ /**
+ * Test domain Intent service; always success for all domain Intent operations.
+ */
+ class TestDomainIntentService implements DomainIntentService {
+ @Override
+ public void sumbit(DomainIntentOperations domainOperations) {
+ domainOperations.callback().onSuccess(domainOperations);
+ }
+ }
+
+ /**
+ * Test domain Intent service; always failed of any domain Intent operation.
+ */
+ class TestFailedDomainIntentService extends TestDomainIntentService {
+
+ @Override
+ public void sumbit(DomainIntentOperations domainOperations) {
+ domainOperations.callback().onError(domainOperations);
+ }
+ }
+
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowObjectiveIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowObjectiveIntentInstallerTest.java
new file mode 100644
index 0000000..99f5db9
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowObjectiveIntentInstallerTest.java
@@ -0,0 +1,521 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.intent.impl.installer;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flowobjective.DefaultFilteringObjective;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.DefaultNextObjective;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.onosproject.net.intent.FlowObjectiveIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentInstallationContext;
+import org.onosproject.net.intent.IntentOperationContext;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.store.service.WallClockTimestamp;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+import static org.onosproject.net.flowobjective.ObjectiveError.*;
+
+/**
+ * Tests for flow objective Intent installer.
+ */
+public class FlowObjectiveIntentInstallerTest extends AbstractIntentInstallerTest {
+ private static final int NEXT_ID_1 = 1;
+ protected FlowObjectiveIntentInstaller installer;
+ protected TestFlowObjectiveService flowObjectiveService;
+
+ @Before
+ public void setup() {
+ super.setup();
+ flowObjectiveService = new TestFlowObjectiveService();
+ installer = new FlowObjectiveIntentInstaller();
+ installer.flowObjectiveService = flowObjectiveService;
+ installer.trackerService = trackerService;
+ installer.intentExtensionService = intentExtensionService;
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+
+ installer.activate();
+ }
+
+ @After
+ public void tearDown() {
+ super.tearDown();
+ installer.deactivated();
+ }
+
+ /**
+ * Installs flow objective Intents.
+ */
+ @Test
+ public void testInstallIntent() {
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createFlowObjectiveIntents();
+
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+
+
+ IntentOperationContext<FlowObjectiveIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+ }
+
+ /**
+ * Uninstalls flow objective Intents.
+ */
+ @Test
+ public void testUninstallIntent() {
+ List<Intent> intentsToUninstall = createFlowObjectiveIntents();
+ List<Intent> intentsToInstall = Lists.newArrayList();
+
+
+ IntentData toInstall = null;
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.WITHDRAWING,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+ IntentOperationContext<FlowObjectiveIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+ }
+
+ /**
+ * Do both uninstall and install flow objective Intents.
+ */
+ @Test
+ public void testUninstallAndInstallIntent() {
+ List<Intent> intentsToUninstall = createFlowObjectiveIntents();
+ List<Intent> intentsToInstall = createAnotherFlowObjectiveIntents();
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+
+ IntentOperationContext<FlowObjectiveIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+ }
+
+ /**
+ * Nothing to uninstall or install.
+ */
+ @Test
+ public void testNoAnyIntentToApply() {
+ IntentData toInstall = null;
+ IntentData toUninstall = null;
+ IntentOperationContext<FlowObjectiveIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context);
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+ }
+
+ /*
+ * Error handling
+ */
+ IntentOperationContext context;
+ IntentOperationContext failedContext;
+ IntentOperationContext successContext;
+ List<ObjectiveError> errors;
+
+ /**
+ * Handles UNSUPPORTED error.
+ */
+ @Test
+ public void testUnsupportedError() {
+ // Unsupported, should just failed
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService();
+ context = createInstallContext();
+ installer.apply(context);
+ assertEquals(intentInstallCoordinator.failedContext, context);
+ }
+
+ /**
+ * Handles FLOWINSTALLATIONFAILED error with touch the threshold.
+ */
+ @Test
+ public void testFlowInstallationFailedError() {
+ // flow install failed, should retry until retry threshold
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
+ FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
+ FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
+ FLOWINSTALLATIONFAILED);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createInstallContext();
+ installer.apply(context);
+ failedContext = intentInstallCoordinator.failedContext;
+ assertEquals(failedContext, context);
+ }
+
+ /**
+ * Handles FLOWINSTALLATIONFAILED error without touch the threshold.
+ */
+ @Test
+ public void testFlowInstallationFailedErrorUnderThreshold() {
+ // And retry two times and success
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createInstallContext();
+ installer.apply(context);
+ successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, context);
+ }
+
+ /**
+ * Handles GROUPINSTALLATIONFAILED error with touch the threshold.
+ */
+ @Test
+ public void testGroupInstallationFailedError() {
+ // Group install failed, and retry threshold exceed
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
+ GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
+ GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
+ GROUPINSTALLATIONFAILED);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createInstallContext();
+ installer.apply(context);
+ failedContext = intentInstallCoordinator.failedContext;
+ assertEquals(failedContext, context);
+
+ }
+
+ /**
+ * Handles GROUPINSTALLATIONFAILED error without touch the threshold.
+ */
+ @Test
+ public void testGroupInstallationFailedErrorUnderThreshold() {
+ // group install failed, and retry two times.
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createInstallContext();
+ installer.apply(context);
+ successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, context);
+
+ }
+
+ /**
+ * Handles GROUPEXISTS error.
+ */
+ @Test
+ public void testGroupExistError() {
+ // group exists, retry by using add to exist
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(GROUPEXISTS);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createInstallContext();
+ installer.apply(context);
+ successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, context);
+ }
+
+ /**
+ * Handles GROUPMISSING error with ADD_TO_EXIST operation.
+ */
+ @Test
+ public void testGroupMissingError() {
+ // group exist -> group missing -> add group
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(GROUPEXISTS, GROUPMISSING);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createInstallContext();
+ installer.apply(context);
+ successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, context);
+ }
+
+ /**
+ * Handles GROUPMISSING error with ADD operation.
+ */
+ @Test
+ public void testGroupChainElementMissingError() {
+ // group chain element missing
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(GROUPMISSING);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createInstallContext();
+ installer.apply(context);
+ successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, context);
+ }
+
+ /**
+ * Handles GROUPMISSING error with REMOVE operation.
+ */
+ @Test
+ public void testGroupAlreadyRemoved() {
+ // group already removed
+ intentInstallCoordinator = new TestIntentInstallCoordinator();
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ errors = ImmutableList.of(GROUPMISSING);
+ installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
+ context = createUninstallContext();
+ installer.apply(context);
+ successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, context);
+ }
+
+ /**
+ * Creates Intent operation context for uninstall Intents.
+ *
+ * @return the context
+ */
+ private IntentOperationContext createUninstallContext() {
+ List<Intent> intentsToUninstall = createFlowObjectiveIntents();
+ List<Intent> intentsToInstall = Lists.newArrayList();
+ IntentData toInstall = null;
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ return new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ }
+
+ /**
+ * Creates Intent operation context for install Intents.
+ *
+ * @return the context
+ */
+ private IntentOperationContext createInstallContext() {
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createFlowObjectiveIntents();
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ return new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ }
+
+ /**
+ * Creates flow objective Intents.
+ *
+ * @return the flow objective intents
+ */
+ private List<Intent> createFlowObjectiveIntents() {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(CP1.port())
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP2.port())
+ .build();
+
+ FilteringObjective filt = DefaultFilteringObjective.builder()
+ .addCondition(selector.getCriterion(Criterion.Type.IN_PORT))
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(APP_ID)
+ .permit()
+ .add();
+
+ NextObjective next = DefaultNextObjective.builder()
+ .withMeta(selector)
+ .addTreatment(treatment)
+ .makePermanent()
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(APP_ID)
+ .withType(NextObjective.Type.SIMPLE)
+ .withId(NEXT_ID_1)
+ .add();
+
+ ForwardingObjective fwd = DefaultForwardingObjective.builder()
+ .withSelector(selector)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .nextStep(NEXT_ID_1)
+ .add();
+
+ List<Objective> objectives = ImmutableList.of(filt, next, fwd);
+ List<DeviceId> deviceIds = ImmutableList.of(CP1.deviceId(), CP1.deviceId(), CP1.deviceId());
+ List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
+
+ Intent intent = new FlowObjectiveIntent(APP_ID, KEY1, deviceIds, objectives, resources, RG1);
+ return ImmutableList.of(intent);
+ }
+
+ /**
+ * Creates flow objective Intents with different selector.
+ *
+ * @return the flow objective Intents
+ */
+ private List<Intent> createAnotherFlowObjectiveIntents() {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchVlanId(VlanId.vlanId("100"))
+ .matchInPort(CP1.port())
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP2.port())
+ .build();
+
+ FilteringObjective filt = DefaultFilteringObjective.builder()
+ .addCondition(selector.getCriterion(Criterion.Type.IN_PORT))
+ .addCondition(selector.getCriterion(Criterion.Type.VLAN_VID))
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(APP_ID)
+ .permit()
+ .add();
+
+ NextObjective next = DefaultNextObjective.builder()
+ .withMeta(selector)
+ .addTreatment(treatment)
+ .makePermanent()
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(APP_ID)
+ .withType(NextObjective.Type.SIMPLE)
+ .withId(NEXT_ID_1)
+ .add();
+
+ ForwardingObjective fwd = DefaultForwardingObjective.builder()
+ .withSelector(selector)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .nextStep(NEXT_ID_1)
+ .add();
+
+ List<Objective> objectives = ImmutableList.of(filt, next, fwd);
+ List<DeviceId> deviceIds = ImmutableList.of(CP1.deviceId(), CP1.deviceId(), CP1.deviceId());
+ List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
+
+ Intent intent = new FlowObjectiveIntent(APP_ID, KEY1, deviceIds, objectives, resources, RG1);
+ return ImmutableList.of(intent);
+ }
+
+ /**
+ * Flow objective service for test; always successful for every flow objectives.
+ */
+ class TestFlowObjectiveService extends FlowObjectiveServiceAdapter {
+ List<DeviceId> devices = Lists.newArrayList();
+ List<Objective> objectives = Lists.newArrayList();
+
+ @Override
+ public void apply(DeviceId deviceId, Objective objective) {
+ devices.add(deviceId);
+ objectives.add(objective);
+ objective.context().ifPresent(context -> context.onSuccess(objective));
+ }
+ }
+
+ /**
+ * Flow objective service for test; contains errors for every flow objective
+ * submission.
+ */
+ class TestFailedFlowObjectiveService extends TestFlowObjectiveService {
+ private final Set<ObjectiveError> groupErrors =
+ ImmutableSet.of(GROUPEXISTS, GROUPINSTALLATIONFAILED,
+ GROUPMISSING, GROUPREMOVALFAILED);
+
+ /**
+ * Error states to test error handler by given error queue
+ * e.g.
+ * FLOWINSTALLATIONFAILED -> FLOWINSTALLATIONFAILED -> null: should be success
+ * FLOWINSTALLATIONFAILED -> five same error -> .... : should be failed
+ */
+ List<ObjectiveError> errors;
+
+ public TestFailedFlowObjectiveService() {
+ errors = Lists.newArrayList();
+ errors.add(UNSUPPORTED);
+ }
+
+ public TestFailedFlowObjectiveService(List<ObjectiveError> errors) {
+ this.errors = Lists.newArrayList(errors);
+ }
+
+ @Override
+ public void apply(DeviceId deviceId, Objective objective) {
+ if (errors.size() != 0) {
+ if (groupErrors.contains(errors.get(0)) && objective instanceof NextObjective) {
+ ObjectiveError error = errors.remove(0);
+ objective.context().ifPresent(context -> context.onError(objective, error));
+ return;
+ }
+ if (!groupErrors.contains(errors.get(0)) && !(objective instanceof NextObjective)) {
+ ObjectiveError error = errors.remove(0);
+ objective.context().ifPresent(context -> context.onError(objective, error));
+ return;
+ }
+ }
+ objective.context().ifPresent(context -> context.onSuccess(objective));
+
+ }
+ }
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowRuleIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowRuleIntentInstallerTest.java
new file mode 100644
index 0000000..418392b
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/FlowRuleIntentInstallerTest.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.intent.impl.installer;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleServiceAdapter;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentInstallationContext;
+import org.onosproject.net.intent.IntentOperationContext;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.PathIntent;
+import org.onosproject.store.service.WallClockTimestamp;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for flow rule Intent installer.
+ */
+public class FlowRuleIntentInstallerTest extends AbstractIntentInstallerTest {
+
+ private TestFlowRuleService flowRuleService;
+ private FlowRuleIntentInstaller installer;
+
+ @Before
+ public void setup() {
+ super.setup();
+ flowRuleService = new TestFlowRuleService();
+ installer = new FlowRuleIntentInstaller();
+ installer.flowRuleService = flowRuleService;
+ installer.intentExtensionService = intentExtensionService;
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ installer.trackerService = trackerService;
+
+ installer.activate();
+ }
+
+ @After
+ public void tearDown() {
+ super.tearDown();
+ installer.deactivated();
+ }
+
+ /**
+ * Installs Intents only, no Intents to be uninstall.
+ */
+ @Test
+ public void testInstallOnly() {
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createFlowRuleIntents();
+
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+
+
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+
+ Set<FlowRule> expectedFlowRules = intentsToInstall.stream()
+ .map(intent -> (FlowRuleIntent) intent)
+ .map(FlowRuleIntent::flowRules)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet());
+
+ assertEquals(expectedFlowRules, flowRuleService.flowRulesAdd);
+ }
+
+ /**
+ * Uninstalls Intents only, no Intents to be install.
+ */
+ @Test
+ public void testUninstallOnly() {
+ List<Intent> intentsToInstall = Lists.newArrayList();
+ List<Intent> intentsToUninstall = createFlowRuleIntents();
+
+ IntentData toInstall = null;
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.WITHDRAWING,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+
+
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+
+ Set<FlowRule> expectedFlowRules = intentsToUninstall.stream()
+ .map(intent -> (FlowRuleIntent) intent)
+ .map(FlowRuleIntent::flowRules)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet());
+
+ assertEquals(expectedFlowRules, flowRuleService.flowRulesRemove);
+ }
+
+ /**
+ * Do both install and uninstall Intents with different flow rules.
+ */
+ @Test
+ public void testUninstallAndInstall() {
+ List<Intent> intentsToInstall = createAnotherFlowRuleIntents();
+ List<Intent> intentsToUninstall = createFlowRuleIntents();
+
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+
+ Set<FlowRule> expectedFlowRules = intentsToUninstall.stream()
+ .map(intent -> (FlowRuleIntent) intent)
+ .map(FlowRuleIntent::flowRules)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet());
+
+ assertEquals(expectedFlowRules, flowRuleService.flowRulesRemove);
+
+ expectedFlowRules = intentsToInstall.stream()
+ .map(intent -> (FlowRuleIntent) intent)
+ .map(FlowRuleIntent::flowRules)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet());
+
+ assertEquals(expectedFlowRules, flowRuleService.flowRulesAdd);
+ }
+
+ /**
+ * Do both install and uninstall Intents with same flow rules.
+ */
+ @Test
+ public void testUninstallAndInstallUnchanged() {
+ List<Intent> intentsToInstall = createFlowRuleIntents();
+ List<Intent> intentsToUninstall = createFlowRuleIntents();
+
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+
+ assertEquals(0, flowRuleService.flowRulesRemove.size());
+ assertEquals(0, flowRuleService.flowRulesAdd.size());
+ }
+
+ /**
+ * Do both install and uninstall Intents with same flow rule Intent.
+ */
+ @Test
+ public void testUninstallAndInstallSame() {
+ List<Intent> intentsToInstall = createFlowRuleIntents();
+ List<Intent> intentsToUninstall = intentsToInstall;
+
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToUninstall);
+
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+
+ assertEquals(0, flowRuleService.flowRulesRemove.size());
+ assertEquals(0, flowRuleService.flowRulesAdd.size());
+ }
+
+ /**
+ * Nothing to uninstall or install.
+ */
+ @Test
+ public void testNoAnyIntentToApply() {
+ IntentData toInstall = null;
+ IntentData toUninstall = null;
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context);
+ installer.apply(operationContext);
+
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+
+ assertEquals(0, flowRuleService.flowRulesRemove.size());
+ assertEquals(0, flowRuleService.flowRulesAdd.size());
+ }
+
+ /**
+ * Test if the flow installation failed.
+ */
+ @Test
+ public void testFailed() {
+ installer.flowRuleService = new TestFailedFlowRuleService();
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createFlowRuleIntents();
+
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+
+
+ IntentOperationContext<FlowRuleIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+
+ installer.apply(operationContext);
+
+ IntentOperationContext failedContext = intentInstallCoordinator.failedContext;
+ assertEquals(failedContext, operationContext);
+ }
+
+ /**
+ * Generates FlowRuleIntents for test.
+ *
+ * @return the FlowRuleIntents for test
+ */
+ public List<Intent> createFlowRuleIntents() {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPhyPort(CP1.port())
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP2.port())
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(CP1.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .build();
+
+ List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
+
+ FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
+ KEY1,
+ ImmutableList.of(flowRule),
+ resources,
+ PathIntent.ProtectionType.PRIMARY,
+ RG1);
+
+ List<Intent> flowRuleIntents = Lists.newArrayList();
+ flowRuleIntents.add(intent);
+
+ return flowRuleIntents;
+ }
+
+ /**
+ * Generates another different FlowRuleIntents for test.
+ *
+ * @return the FlowRuleIntents for test
+ */
+ public List<Intent> createAnotherFlowRuleIntents() {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchVlanId(VlanId.vlanId("100"))
+ .matchInPhyPort(CP1.port())
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(CP2.port())
+ .build();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(CP1.deviceId())
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .fromApp(APP_ID)
+ .withPriority(DEFAULT_PRIORITY)
+ .makePermanent()
+ .build();
+
+ List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
+
+ FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
+ KEY1,
+ ImmutableList.of(flowRule),
+ resources,
+ PathIntent.ProtectionType.PRIMARY,
+ RG1);
+
+ List<Intent> flowRuleIntents = Lists.newArrayList();
+ flowRuleIntents.add(intent);
+
+ return flowRuleIntents;
+ }
+
+ /**
+ * The FlowRuleService for test; always success for any flow rule operations.
+ */
+ class TestFlowRuleService extends FlowRuleServiceAdapter {
+
+ Set<FlowRule> flowRulesAdd = Sets.newHashSet();
+ Set<FlowRule> flowRulesRemove = Sets.newHashSet();
+
+ public void record(FlowRuleOperations ops) {
+ flowRulesAdd.clear();
+ flowRulesRemove.clear();
+ ops.stages().forEach(stage -> {
+ stage.forEach(op -> {
+ switch (op.type()) {
+ case ADD:
+ flowRulesAdd.add(op.rule());
+ break;
+ case REMOVE:
+ flowRulesRemove.add(op.rule());
+ break;
+ default:
+ break;
+ }
+ });
+ });
+ }
+
+ @Override
+ public void apply(FlowRuleOperations ops) {
+ record(ops);
+ ops.callback().onSuccess(ops);
+ }
+ }
+
+ /**
+ * The FlowRuleService for test; always failed for any flow rule operations.
+ */
+ class TestFailedFlowRuleService extends TestFlowRuleService {
+ @Override
+ public void apply(FlowRuleOperations ops) {
+ record(ops);
+ ops.callback().onError(ops);
+ }
+ }
+
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/ProtectionEndpointIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/ProtectionEndpointIntentInstallerTest.java
new file mode 100644
index 0000000..53851da
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/ProtectionEndpointIntentInstallerTest.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.intent.impl.installer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onlab.junit.TestUtils;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onosproject.codec.CodecService;
+import org.onosproject.codec.impl.CodecManager;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointDescription;
+import org.onosproject.net.behaviour.protection.TransportEndpointDescription;
+import org.onosproject.net.config.BaseConfig;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.NetworkConfigServiceAdapter;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentInstallationContext;
+import org.onosproject.net.intent.IntentOperationContext;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.ProtectionEndpointIntent;
+import org.onosproject.store.service.WallClockTimestamp;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for protection endpoint Intent installer.
+ */
+public class ProtectionEndpointIntentInstallerTest extends AbstractIntentInstallerTest {
+ private static final String FINGERPRINT = "Test fingerprint";
+ protected ProtectionEndpointIntentInstaller installer;
+ protected NetworkConfigService networkConfigService;
+ private static TestServiceDirectory directory;
+ private static ServiceDirectory original;
+
+ @BeforeClass
+ public static void setUpClass() throws TestUtils.TestUtilsException {
+ directory = new TestServiceDirectory();
+
+ CodecManager codecService = new CodecManager();
+ codecService.activate();
+ directory.add(CodecService.class, codecService);
+
+ // replace service directory used by BaseConfig
+ original = TestUtils.getField(BaseConfig.class, "services");
+ TestUtils.setField(BaseConfig.class, "services", directory);
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws TestUtils.TestUtilsException {
+ TestUtils.setField(BaseConfig.class, "services", original);
+ }
+
+ @Before
+ public void setup() {
+ super.setup();
+ networkConfigService = new TestNetworkConfigService();
+ installer = new ProtectionEndpointIntentInstaller();
+ installer.networkConfigService = networkConfigService;
+ installer.intentExtensionService = intentExtensionService;
+ installer.intentInstallCoordinator = intentInstallCoordinator;
+ installer.trackerService = trackerService;
+
+ installer.activate();
+ }
+
+ @After
+ public void tearDown() {
+ super.tearDown();
+ installer.deactivated();
+ }
+
+ /**
+ * Installs protection endpoint Intents.
+ * framework.
+ */
+ @Test
+ public void testInstallIntents() {
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createProtectionIntents(CP2);
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentOperationContext<ProtectionEndpointIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.successContext, operationContext);
+ }
+
+ /**
+ * Uninstalls protection endpoint Intents.
+ * framework.
+ */
+ @Test
+ public void testUninstallIntents() {
+ List<Intent> intentsToUninstall = createProtectionIntents(CP2);
+ List<Intent> intentsToInstall = Lists.newArrayList();
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ IntentData toInstall = null;
+ IntentOperationContext<ProtectionEndpointIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.successContext, operationContext);
+ }
+
+ /**
+ * Test both uninstall and install protection endpoint Intents.
+ * framework.
+ */
+ @Test
+ public void testUninstallAndInstallIntents() {
+ List<Intent> intentsToUninstall = createProtectionIntents(CP2);
+ List<Intent> intentsToInstall = createProtectionIntents(CP3);
+ IntentData toUninstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLED,
+ new WallClockTimestamp());
+ toUninstall = new IntentData(toUninstall, intentsToInstall);
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentOperationContext<ProtectionEndpointIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.successContext, operationContext);
+ }
+
+ /**
+ * Nothing to uninstall or install.
+ */
+ @Test
+ public void testNoAnyIntentToApply() {
+ IntentData toInstall = null;
+ IntentData toUninstall = null;
+ IntentOperationContext<ProtectionEndpointIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context);
+ installer.apply(operationContext);
+ IntentOperationContext successContext = intentInstallCoordinator.successContext;
+ assertEquals(successContext, operationContext);
+ }
+
+ /**
+ * Test if installation failed.
+ * framework.
+ */
+ @Test
+ public void testInstallFailed() {
+ networkConfigService = new TestFailedNetworkConfigService();
+ installer.networkConfigService = networkConfigService;
+ List<Intent> intentsToUninstall = Lists.newArrayList();
+ List<Intent> intentsToInstall = createProtectionIntents(CP2);
+ IntentData toUninstall = null;
+ IntentData toInstall = new IntentData(createP2PIntent(),
+ IntentState.INSTALLING,
+ new WallClockTimestamp());
+ toInstall = new IntentData(toInstall, intentsToInstall);
+ IntentOperationContext<ProtectionEndpointIntent> operationContext;
+ IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
+ operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
+ installer.apply(operationContext);
+ assertEquals(intentInstallCoordinator.failedContext, operationContext);
+ }
+
+ /**
+ * Creates protection endpoint Intents by givent output point.
+ *
+ * @param output the output point
+ * @return the protection endpoint Intents
+ */
+ private List<Intent> createProtectionIntents(ConnectPoint output) {
+ FilteredConnectPoint filteredOutput = new FilteredConnectPoint(output);
+ TransportEndpointDescription path = TransportEndpointDescription.builder()
+ .withOutput(filteredOutput)
+ .withEnabled(true).build();
+
+ List<TransportEndpointDescription> paths = ImmutableList.of(path);
+ ProtectedTransportEndpointDescription description =
+ ProtectedTransportEndpointDescription.of(paths, CP2.deviceId(), FINGERPRINT);
+ ProtectionEndpointIntent intent = ProtectionEndpointIntent.builder()
+ .appId(APP_ID)
+ .description(description)
+ .deviceId(CP1.deviceId())
+ .key(KEY1)
+ .resourceGroup(RG1)
+ .build();
+
+ return ImmutableList.of(intent);
+ }
+
+ class TestNetworkConfigService extends NetworkConfigServiceAdapter {
+ protected Set<NetworkConfigListener> listeners = Sets.newHashSet();
+
+ @Override
+ public void addListener(NetworkConfigListener listener) {
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(NetworkConfigListener listener) {
+ listeners.remove(listener);
+ }
+
+ @Override
+ public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
+ NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED,
+ subject,
+ configClass);
+ CompletableFuture.runAsync(() -> {
+ listeners.forEach(listener -> listener.event(event));
+ });
+ return null;
+ }
+
+ @Override
+ public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
+ NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_REMOVED,
+ subject,
+ configClass);
+ CompletableFuture.runAsync(() -> {
+ listeners.forEach(listener -> listener.event(event));
+ });
+ }
+ }
+
+ /**
+ * Test network config service; will send wrong events to listeners.
+ */
+ class TestFailedNetworkConfigService extends TestNetworkConfigService {
+
+ @Override
+ public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass, JsonNode json) {
+ NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_REMOVED,
+ subject,
+ configClass);
+ CompletableFuture.runAsync(() -> {
+ listeners.forEach(listener -> listener.event(event));
+ });
+ return null;
+ }
+
+ @Override
+ public <S, C extends Config<S>> void removeConfig(S subject, Class<C> configClass) {
+ NetworkConfigEvent event = new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED,
+ subject,
+ configClass);
+ CompletableFuture.runAsync(() -> {
+ listeners.forEach(listener -> listener.event(event));
+ });
+ }
+ }
+}