Unit tests for Objective Tracker
- Fixed a bug in ObjectiveTracker turned up by tests, it
could not handle an emptry list (it was checking for null only)
- Implemented tests for topology, resource and leadership
events
Change-Id: I1318a0e8655f5b44b30d2ecb527f665f13d54243
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java b/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java
index 4180827..0a36d1c 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/ObjectiveTracker.java
@@ -178,7 +178,7 @@
return;
}
- if (event.reasons() == null) {
+ if (event.reasons() == null || event.reasons().isEmpty()) {
delegate.triggerCompile(new HashSet<IntentId>(), true);
} else {
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java
new file mode 100644
index 0000000..cf89098
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/ObjectiveTrackerTest.java
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2014 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 java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.junit.TestUtils;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.event.Event;
+import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentBatchLeaderEvent;
+import org.onosproject.net.intent.IntentBatchListener;
+import org.onosproject.net.intent.IntentId;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.link.LinkEvent;
+import org.onosproject.net.resource.LinkResourceEvent;
+import org.onosproject.net.resource.LinkResourceListener;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.net.topology.TopologyEvent;
+import org.onosproject.net.topology.TopologyListener;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.SetMultimap;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.onosproject.net.NetTestTools.link;
+import org.onlab.junit.TestUtils.TestUtilsException;
+
+/**
+ * Tests for the objective tracker.
+ */
+public class ObjectiveTrackerTest {
+ private static final int WAIT_TIMEOUT_SECONDS = 2;
+ private Topology topology;
+ private ObjectiveTracker tracker;
+ private TestTopologyChangeDelegate delegate;
+ private List<Event> reasons;
+ private TopologyListener listener;
+ private LinkResourceListener linkResourceListener;
+ private IntentBatchListener leaderListener;
+ private IdGenerator mockGenerator;
+
+ /**
+ * Initialization shared by all test cases.
+ *
+ * @throws TestUtilsException if any filed look ups fail
+ */
+ @Before
+ public void setUp() throws TestUtilsException {
+ topology = createMock(Topology.class);
+ tracker = new ObjectiveTracker();
+ delegate = new TestTopologyChangeDelegate();
+ tracker.setDelegate(delegate);
+ reasons = new LinkedList<>();
+ listener = TestUtils.getField(tracker, "listener");
+ linkResourceListener = TestUtils.getField(tracker, "linkResourceListener");
+ leaderListener = TestUtils.getField(tracker, "leaderListener");
+ mockGenerator = new MockIdGenerator();
+ Intent.bindIdGenerator(mockGenerator);
+ }
+
+ /**
+ * Code to clean up shared by all test case.
+ */
+ @After
+ public void tearDown() {
+ tracker.unsetDelegate(delegate);
+ Intent.unbindIdGenerator(mockGenerator);
+ }
+
+ /**
+ * Topology change delegate mock that tracks the events coming into it
+ * and saves them. It provides a latch so that tests can wait for events
+ * to be generated.
+ */
+ static class TestTopologyChangeDelegate implements TopologyChangeDelegate {
+
+ CountDownLatch latch = new CountDownLatch(1);
+ List<IntentId> intentIdsFromEvent;
+ boolean compileAllFailedFromEvent;
+
+ @Override
+ public void triggerCompile(Iterable<IntentId> intentIds,
+ boolean compileAllFailed) {
+ intentIdsFromEvent = Lists.newArrayList(intentIds);
+ compileAllFailedFromEvent = compileAllFailed;
+ latch.countDown();
+ }
+ }
+
+ /**
+ * Mock compilable intent class.
+ */
+ private static class MockIntent extends Intent {
+
+ public MockIntent(Collection<NetworkResource> resources) {
+ super(NetTestTools.APP_ID, resources);
+ }
+
+ }
+
+ /**
+ * Mock installable intent class.
+ */
+ private static class MockInstallableIntent extends Intent {
+ public MockInstallableIntent(Collection<NetworkResource> resources) {
+ super(NetTestTools.APP_ID, resources);
+ }
+
+ @Override
+ public boolean isInstallable() {
+ return true;
+ }
+
+ }
+
+ /**
+ * Tests an event with no associated reasons.
+ *
+ * @throws InterruptedException if the latch wait fails.
+ */
+ @Test
+ public void testEventNoReasons() throws InterruptedException {
+ final TopologyEvent event = new TopologyEvent(
+ TopologyEvent.Type.TOPOLOGY_CHANGED,
+ topology,
+ null);
+
+ listener.event(event);
+ assertThat(
+ delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
+ is(true));
+
+ assertThat(delegate.intentIdsFromEvent, hasSize(0));
+ assertThat(delegate.compileAllFailedFromEvent, is(true));
+ }
+
+ /**
+ * Tests an event for a link down where none of the reasons match
+ * currently installed intents.
+ *
+ * @throws InterruptedException if the latch wait fails.
+ */
+ @Test
+ public void testEventLinkDownNoMatches() throws InterruptedException {
+ final Link link = link("src", 1, "dst", 2);
+ final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
+ reasons.add(linkEvent);
+
+ final TopologyEvent event = new TopologyEvent(
+ TopologyEvent.Type.TOPOLOGY_CHANGED,
+ topology,
+ reasons);
+
+ listener.event(event);
+ assertThat(
+ delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
+ is(true));
+
+ assertThat(delegate.intentIdsFromEvent, hasSize(0));
+ assertThat(delegate.compileAllFailedFromEvent, is(false));
+ }
+
+ /**
+ * Tests an event for a link being added.
+ *
+ * @throws InterruptedException if the latch wait fails.
+ */
+ @Test
+ public void testEventLinkAdded() throws InterruptedException {
+ final Link link = link("src", 1, "dst", 2);
+ final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_ADDED, link);
+ reasons.add(linkEvent);
+
+ final TopologyEvent event = new TopologyEvent(
+ TopologyEvent.Type.TOPOLOGY_CHANGED,
+ topology,
+ reasons);
+
+ listener.event(event);
+ assertThat(
+ delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
+ is(true));
+
+ assertThat(delegate.intentIdsFromEvent, hasSize(0));
+ assertThat(delegate.compileAllFailedFromEvent, is(true));
+ }
+
+ /**
+ * Tests an event for a link down where the link matches existing intents.
+ *
+ * @throws InterruptedException if the latch wait fails.
+ */
+ @Test
+ public void testEventLinkDownMatch() throws Exception {
+ final Link link = link("src", 1, "dst", 2);
+ final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
+ reasons.add(linkEvent);
+
+ final TopologyEvent event = new TopologyEvent(
+ TopologyEvent.Type.TOPOLOGY_CHANGED,
+ topology,
+ reasons);
+
+ final IntentId intentId = IntentId.valueOf(0x333L);
+ Collection<NetworkResource> resources = ImmutableSet.of(link);
+ tracker.addTrackedResources(intentId, resources);
+
+ listener.event(event);
+ assertThat(
+ delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
+ is(true));
+
+ assertThat(delegate.intentIdsFromEvent, hasSize(1));
+ assertThat(delegate.compileAllFailedFromEvent, is(false));
+ assertThat(delegate.intentIdsFromEvent.get(0).toString(),
+ equalTo("0x333"));
+ }
+
+ /**
+ * Tests a resource available event.
+ *
+ * @throws InterruptedException if the latch wait fails.
+ */
+ @Test
+ public void testResourceEvent() throws Exception {
+ LinkResourceEvent event = new LinkResourceEvent(
+ LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
+ new HashSet<>());
+ linkResourceListener.event(event);
+
+ assertThat(
+ delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
+ is(true));
+
+ assertThat(delegate.intentIdsFromEvent, hasSize(0));
+ assertThat(delegate.compileAllFailedFromEvent, is(true));
+ }
+
+ /**
+ * Tests leadership events.
+ *
+ * @throws InterruptedException if the latch wait fails.
+ */
+ @Test
+ public void testLeaderEvents() throws Exception {
+
+ final Link link = link("src", 1, "dst", 2);
+ final List<NetworkResource> resources = ImmutableList.of(link);
+
+ final List<Intent> intents = new LinkedList<>();
+ final List<Intent> installableIntents = new LinkedList<>();
+ installableIntents.add(new MockInstallableIntent(resources));
+ intents.add(new MockIntent(resources));
+
+ final SetMultimap<LinkKey, IntentId> intentsByLink =
+ TestUtils.getField(tracker, "intentsByLink");
+ assertThat(intentsByLink.size(), is(0));
+
+ final IntentService mockIntentManager = createMock(IntentService.class);
+ expect(mockIntentManager
+ .getIntents())
+ .andReturn(intents)
+ .anyTimes();
+ expect(mockIntentManager
+ .getIntent(IntentId.valueOf(0x0)))
+ .andReturn(intents.get(0))
+ .anyTimes();
+ expect(mockIntentManager
+ .getInstallableIntents(IntentId.valueOf(0x1)))
+ .andReturn(installableIntents)
+ .anyTimes();
+ replay(mockIntentManager);
+ tracker.bindIntentService(mockIntentManager);
+
+ final IntentBatchLeaderEvent electedEvent = new IntentBatchLeaderEvent(
+ IntentBatchLeaderEvent.Type.ELECTED, NetTestTools.APP_ID);
+ leaderListener.event(electedEvent);
+ assertThat(intentsByLink.size(), is(1));
+
+ final IntentBatchLeaderEvent bootedEvent = new IntentBatchLeaderEvent(
+ IntentBatchLeaderEvent.Type.BOOTED, NetTestTools.APP_ID);
+ leaderListener.event(bootedEvent);
+ assertThat(intentsByLink.size(), is(0));
+
+ tracker.unbindIntentService(mockIntentManager);
+ }
+}