blob: 1bafca8c4bfd29bcd860717496e26135b175dc26 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.intent;
Brian O'Connorf3d06162014-10-02 15:54:12 -070017
Brian O'Connorcb900f42014-10-07 21:55:33 -070018import org.junit.After;
19import org.junit.Before;
20import org.junit.Test;
Brian O'Connorabafb502014-12-02 22:26:20 -080021import org.onosproject.core.IdGenerator;
Brian O'Connorf3d06162014-10-02 15:54:12 -070022
Brian O'Connor64a0369d2015-02-20 22:02:59 -080023import java.util.ArrayList;
24import java.util.Arrays;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080025import java.util.Collections;
26import java.util.Iterator;
27import java.util.List;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080028
29import static org.junit.Assert.*;
30import static org.onosproject.net.intent.IntentEvent.Type.*;
31
Brian O'Connorf3d06162014-10-02 15:54:12 -070032/**
33 * Suite of tests for the intent service contract.
34 */
35public class IntentServiceTest {
36
Brian O'Connor520c0522014-11-23 23:50:47 -080037 public static final int IID = 123;
38 public static final int INSTALLABLE_IID = 234;
Brian O'Connorf3d06162014-10-02 15:54:12 -070039
40 protected static final int GRACE_MS = 500; // millis
41
42 protected TestableIntentService service;
43 protected TestListener listener = new TestListener();
Brian O'Connor520c0522014-11-23 23:50:47 -080044 protected IdGenerator idGenerator = new MockIdGenerator();
Brian O'Connorf3d06162014-10-02 15:54:12 -070045
46 @Before
47 public void setUp() {
48 service = createIntentService();
49 service.addListener(listener);
Thomas Vachuska23235962017-02-03 11:44:15 -080050 Intent.unbindIdGenerator(idGenerator);
Brian O'Connor520c0522014-11-23 23:50:47 -080051 Intent.bindIdGenerator(idGenerator);
Brian O'Connorf3d06162014-10-02 15:54:12 -070052 }
53
54 @After
55 public void tearDown() {
56 service.removeListener(listener);
Brian O'Connor520c0522014-11-23 23:50:47 -080057 Intent.unbindIdGenerator(idGenerator);
Brian O'Connorf3d06162014-10-02 15:54:12 -070058 }
59
60 /**
61 * Creates a service instance appropriately instrumented for testing.
62 *
63 * @return testable intent service
64 */
65 protected TestableIntentService createIntentService() {
66 return new FakeIntentManager();
67 }
68
69 @Test
70 public void basics() {
71 // Make sure there are no intents
Brian O'Connor66630c82014-10-02 21:08:19 -070072 assertEquals("incorrect intent count", 0, service.getIntentCount());
Brian O'Connorf3d06162014-10-02 15:54:12 -070073
74 // Register a compiler and an installer both setup for success.
75 service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID)));
Brian O'Connorf3d06162014-10-02 15:54:12 -070076
77 final Intent intent = new TestIntent(IID);
78 service.submit(intent);
79
80 // Allow a small window of time until the intent is in the expected state
Sho SHIMIZU74626412015-09-11 11:46:27 -070081 TestTools.assertAfter(GRACE_MS, () ->
82 assertEquals("incorrect intent state", IntentState.INSTALLED, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -070083
84 // Make sure that all expected events have been emitted
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080085 validateEvents(intent, INSTALL_REQ, INSTALLED);
Brian O'Connorf3d06162014-10-02 15:54:12 -070086
87 // Make sure there is just one intent (and is ours)
Brian O'Connor66630c82014-10-02 21:08:19 -070088 assertEquals("incorrect intent count", 1, service.getIntentCount());
Brian O'Connorf3d06162014-10-02 15:54:12 -070089
90 // Reset the listener events
91 listener.events.clear();
92
93 // Now withdraw the intent
94 service.withdraw(intent);
95
96 // Allow a small window of time until the event is in the expected state
Sho SHIMIZU74626412015-09-11 11:46:27 -070097 TestTools.assertAfter(GRACE_MS, () ->
98 assertEquals("incorrect intent state", IntentState.WITHDRAWN, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -070099
100 // Make sure that all expected events have been emitted
tom85258ee2014-10-07 00:10:02 -0700101 validateEvents(intent, WITHDRAWN);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700102
103 // TODO: discuss what is the fate of intents after they have been withdrawn
104 // Make sure that the intent is no longer in the system
105// assertEquals("incorrect intent count", 0, service.getIntents().size());
tom85258ee2014-10-07 00:10:02 -0700106// assertNull("intent should not be found", service.getIntent(intent.id()));
107// assertNull("intent state should not be found", service.getIntentState(intent.id()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700108 }
109
110 @Test
111 public void failedCompilation() {
112 // Register a compiler programmed for success
113 service.registerCompiler(TestIntent.class, new TestCompiler(true));
114
115 // Submit an intent
116 final Intent intent = new TestIntent(IID);
117 service.submit(intent);
118
119 // Allow a small window of time until the intent is in the expected state
Sho SHIMIZU74626412015-09-11 11:46:27 -0700120 TestTools.assertAfter(GRACE_MS, () ->
121 assertEquals("incorrect intent state", IntentState.FAILED, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700122
123 // Make sure that all expected events have been emitted
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800124 validateEvents(intent, INSTALL_REQ, FAILED);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700125 }
126
Brian O'Connorf3d06162014-10-02 15:54:12 -0700127 /**
128 * Validates that the test event listener has received the following events
129 * for the specified intent. Events received for other intents will not be
130 * considered.
131 *
132 * @param intent intent subject
tom85258ee2014-10-07 00:10:02 -0700133 * @param types list of event types for which events are expected
Brian O'Connorf3d06162014-10-02 15:54:12 -0700134 */
tom85258ee2014-10-07 00:10:02 -0700135 protected void validateEvents(Intent intent, IntentEvent.Type... types) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700136 Iterator<IntentEvent> events = listener.events.iterator();
tom85258ee2014-10-07 00:10:02 -0700137 for (IntentEvent.Type type : types) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700138 IntentEvent event = events.hasNext() ? events.next() : null;
139 if (event == null) {
tom85258ee2014-10-07 00:10:02 -0700140 fail("expected event not found: " + type);
141 } else if (intent.equals(event.subject())) {
142 assertEquals("incorrect state", type, event.type());
Brian O'Connorf3d06162014-10-02 15:54:12 -0700143 }
144 }
145
146 // Remainder of events should not apply to this intent; make sure.
147 while (events.hasNext()) {
148 assertFalse("unexpected event for intent",
tom85258ee2014-10-07 00:10:02 -0700149 intent.equals(events.next().subject()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700150 }
151 }
152
153 @Test
154 public void compilerBasics() {
155 // Make sure there are no compilers
156 assertEquals("incorrect compiler count", 0, service.getCompilers().size());
157
158 // Add a compiler and make sure that it appears in the map
159 IntentCompiler<TestIntent> compiler = new TestCompiler(false);
160 service.registerCompiler(TestIntent.class, compiler);
161 assertEquals("incorrect compiler", compiler,
162 service.getCompilers().get(TestIntent.class));
163
164 // Remove the same and make sure that it no longer appears in the map
165 service.unregisterCompiler(TestIntent.class);
166 assertNull("compiler should not be registered",
167 service.getCompilers().get(TestIntent.class));
168 }
169
170 @Test
Brian O'Connorf3d06162014-10-02 15:54:12 -0700171 public void implicitRegistration() {
172 // Add a compiler and make sure that it appears in the map
173 IntentCompiler<TestIntent> compiler = new TestCompiler(new TestSubclassInstallableIntent(INSTALLABLE_IID));
174 service.registerCompiler(TestIntent.class, compiler);
175 assertEquals("incorrect compiler", compiler,
176 service.getCompilers().get(TestIntent.class));
177
Brian O'Connorf3d06162014-10-02 15:54:12 -0700178 // Submit an intent which is a subclass of the one we registered
179 final Intent intent = new TestSubclassIntent(IID);
180 service.submit(intent);
181
182 // Allow some time for the intent to be compiled and installed
Sho SHIMIZU74626412015-09-11 11:46:27 -0700183 TestTools.assertAfter(GRACE_MS, () ->
184 assertEquals("incorrect intent state", IntentState.INSTALLED, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700185
186 // Make sure that now we have an implicit registration of the compiler
187 // under the intent subclass
188 assertEquals("incorrect compiler", compiler,
189 service.getCompilers().get(TestSubclassIntent.class));
190
Brian O'Connorf3d06162014-10-02 15:54:12 -0700191 // TODO: discuss whether or if implicit registration should require implicit unregistration
192 // perhaps unregister by compiler or installer itself, rather than by class would be better
193 }
194
195
196 // Fixture to track emitted intent events
Brian O'Connor66630c82014-10-02 21:08:19 -0700197 protected class TestListener implements IntentListener {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700198 final List<IntentEvent> events = new ArrayList<>();
199
200 @Override
201 public void event(IntentEvent event) {
202 events.add(event);
203 }
204 }
205
206 // Controllable compiler
207 private class TestCompiler implements IntentCompiler<TestIntent> {
208 private final boolean fail;
209 private final List<Intent> result;
210
211 TestCompiler(boolean fail) {
212 this.fail = fail;
213 this.result = Collections.emptyList();
214 }
215
216 TestCompiler(Intent... result) {
217 this.fail = false;
218 this.result = Arrays.asList(result);
219 }
220
221 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800222 public List<Intent> compile(TestIntent intent, List<Intent> installable) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700223 if (fail) {
224 throw new IntentException("compile failed by design");
225 }
226 List<Intent> compiled = new ArrayList<>(result);
227 return compiled;
228 }
229 }
Brian O'Connorf3d06162014-10-02 15:54:12 -0700230}