blob: 58b21ef71ba8ba7014b07572117e681631d86c46 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
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'Connorabafb502014-12-02 22:26:20 -080022import org.onosproject.net.resource.LinkResourceAllocations;
Brian O'Connorf3d06162014-10-02 15:54:12 -070023
Brian O'Connor64a0369d2015-02-20 22:02:59 -080024import java.util.ArrayList;
25import java.util.Arrays;
Brian O'Connor64a0369d2015-02-20 22:02:59 -080026import java.util.Collections;
27import java.util.Iterator;
28import java.util.List;
29import java.util.Set;
30
31import static org.junit.Assert.*;
32import static org.onosproject.net.intent.IntentEvent.Type.*;
33
Brian O'Connorf3d06162014-10-02 15:54:12 -070034/**
35 * Suite of tests for the intent service contract.
36 */
37public class IntentServiceTest {
38
Brian O'Connor520c0522014-11-23 23:50:47 -080039 public static final int IID = 123;
40 public static final int INSTALLABLE_IID = 234;
Brian O'Connorf3d06162014-10-02 15:54:12 -070041
42 protected static final int GRACE_MS = 500; // millis
43
44 protected TestableIntentService service;
45 protected TestListener listener = new TestListener();
Brian O'Connor520c0522014-11-23 23:50:47 -080046 protected IdGenerator idGenerator = new MockIdGenerator();
Brian O'Connorf3d06162014-10-02 15:54:12 -070047
48 @Before
49 public void setUp() {
50 service = createIntentService();
51 service.addListener(listener);
Brian O'Connor520c0522014-11-23 23:50:47 -080052 Intent.bindIdGenerator(idGenerator);
Brian O'Connorf3d06162014-10-02 15:54:12 -070053 }
54
55 @After
56 public void tearDown() {
57 service.removeListener(listener);
Brian O'Connor520c0522014-11-23 23:50:47 -080058 Intent.unbindIdGenerator(idGenerator);
Brian O'Connorf3d06162014-10-02 15:54:12 -070059 }
60
61 /**
62 * Creates a service instance appropriately instrumented for testing.
63 *
64 * @return testable intent service
65 */
66 protected TestableIntentService createIntentService() {
67 return new FakeIntentManager();
68 }
69
70 @Test
71 public void basics() {
72 // Make sure there are no intents
Brian O'Connor66630c82014-10-02 21:08:19 -070073 assertEquals("incorrect intent count", 0, service.getIntentCount());
Brian O'Connorf3d06162014-10-02 15:54:12 -070074
75 // Register a compiler and an installer both setup for success.
76 service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID)));
Brian O'Connorf3d06162014-10-02 15:54:12 -070077
78 final Intent intent = new TestIntent(IID);
79 service.submit(intent);
80
81 // Allow a small window of time until the intent is in the expected state
82 TestTools.assertAfter(GRACE_MS, new Runnable() {
83 @Override
84 public void run() {
tom85258ee2014-10-07 00:10:02 -070085 assertEquals("incorrect intent state", IntentState.INSTALLED,
Ray Milkeyf9af43c2015-02-09 16:45:48 -080086 service.getIntentState(intent.key()));
Brian O'Connorf3d06162014-10-02 15:54:12 -070087 }
88 });
89
90 // Make sure that all expected events have been emitted
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080091 validateEvents(intent, INSTALL_REQ, INSTALLED);
Brian O'Connorf3d06162014-10-02 15:54:12 -070092
93 // Make sure there is just one intent (and is ours)
Brian O'Connor66630c82014-10-02 21:08:19 -070094 assertEquals("incorrect intent count", 1, service.getIntentCount());
Brian O'Connorf3d06162014-10-02 15:54:12 -070095
96 // Reset the listener events
97 listener.events.clear();
98
99 // Now withdraw the intent
100 service.withdraw(intent);
101
102 // Allow a small window of time until the event is in the expected state
103 TestTools.assertAfter(GRACE_MS, new Runnable() {
104 @Override
105 public void run() {
tom85258ee2014-10-07 00:10:02 -0700106 assertEquals("incorrect intent state", IntentState.WITHDRAWN,
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800107 service.getIntentState(intent.key()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700108 }
109 });
110
111 // Make sure that all expected events have been emitted
tom85258ee2014-10-07 00:10:02 -0700112 validateEvents(intent, WITHDRAWN);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700113
114 // TODO: discuss what is the fate of intents after they have been withdrawn
115 // Make sure that the intent is no longer in the system
116// assertEquals("incorrect intent count", 0, service.getIntents().size());
tom85258ee2014-10-07 00:10:02 -0700117// assertNull("intent should not be found", service.getIntent(intent.id()));
118// assertNull("intent state should not be found", service.getIntentState(intent.id()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700119 }
120
121 @Test
122 public void failedCompilation() {
123 // Register a compiler programmed for success
124 service.registerCompiler(TestIntent.class, new TestCompiler(true));
125
126 // Submit an intent
127 final Intent intent = new TestIntent(IID);
128 service.submit(intent);
129
130 // Allow a small window of time until the intent is in the expected state
131 TestTools.assertAfter(GRACE_MS, new Runnable() {
132 @Override
133 public void run() {
tom85258ee2014-10-07 00:10:02 -0700134 assertEquals("incorrect intent state", IntentState.FAILED,
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800135 service.getIntentState(intent.key()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700136 }
137 });
138
139 // Make sure that all expected events have been emitted
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800140 validateEvents(intent, INSTALL_REQ, FAILED);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700141 }
142
Brian O'Connorf3d06162014-10-02 15:54:12 -0700143 /**
144 * Validates that the test event listener has received the following events
145 * for the specified intent. Events received for other intents will not be
146 * considered.
147 *
148 * @param intent intent subject
tom85258ee2014-10-07 00:10:02 -0700149 * @param types list of event types for which events are expected
Brian O'Connorf3d06162014-10-02 15:54:12 -0700150 */
tom85258ee2014-10-07 00:10:02 -0700151 protected void validateEvents(Intent intent, IntentEvent.Type... types) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700152 Iterator<IntentEvent> events = listener.events.iterator();
tom85258ee2014-10-07 00:10:02 -0700153 for (IntentEvent.Type type : types) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700154 IntentEvent event = events.hasNext() ? events.next() : null;
155 if (event == null) {
tom85258ee2014-10-07 00:10:02 -0700156 fail("expected event not found: " + type);
157 } else if (intent.equals(event.subject())) {
158 assertEquals("incorrect state", type, event.type());
Brian O'Connorf3d06162014-10-02 15:54:12 -0700159 }
160 }
161
162 // Remainder of events should not apply to this intent; make sure.
163 while (events.hasNext()) {
164 assertFalse("unexpected event for intent",
tom85258ee2014-10-07 00:10:02 -0700165 intent.equals(events.next().subject()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700166 }
167 }
168
169 @Test
170 public void compilerBasics() {
171 // Make sure there are no compilers
172 assertEquals("incorrect compiler count", 0, service.getCompilers().size());
173
174 // Add a compiler and make sure that it appears in the map
175 IntentCompiler<TestIntent> compiler = new TestCompiler(false);
176 service.registerCompiler(TestIntent.class, compiler);
177 assertEquals("incorrect compiler", compiler,
178 service.getCompilers().get(TestIntent.class));
179
180 // Remove the same and make sure that it no longer appears in the map
181 service.unregisterCompiler(TestIntent.class);
182 assertNull("compiler should not be registered",
183 service.getCompilers().get(TestIntent.class));
184 }
185
186 @Test
Brian O'Connorf3d06162014-10-02 15:54:12 -0700187 public void implicitRegistration() {
188 // Add a compiler and make sure that it appears in the map
189 IntentCompiler<TestIntent> compiler = new TestCompiler(new TestSubclassInstallableIntent(INSTALLABLE_IID));
190 service.registerCompiler(TestIntent.class, compiler);
191 assertEquals("incorrect compiler", compiler,
192 service.getCompilers().get(TestIntent.class));
193
Brian O'Connorf3d06162014-10-02 15:54:12 -0700194 // Submit an intent which is a subclass of the one we registered
195 final Intent intent = new TestSubclassIntent(IID);
196 service.submit(intent);
197
198 // Allow some time for the intent to be compiled and installed
199 TestTools.assertAfter(GRACE_MS, new Runnable() {
200 @Override
201 public void run() {
tom85258ee2014-10-07 00:10:02 -0700202 assertEquals("incorrect intent state", IntentState.INSTALLED,
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800203 service.getIntentState(intent.key()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700204 }
205 });
206
207 // Make sure that now we have an implicit registration of the compiler
208 // under the intent subclass
209 assertEquals("incorrect compiler", compiler,
210 service.getCompilers().get(TestSubclassIntent.class));
211
Brian O'Connorf3d06162014-10-02 15:54:12 -0700212 // TODO: discuss whether or if implicit registration should require implicit unregistration
213 // perhaps unregister by compiler or installer itself, rather than by class would be better
214 }
215
216
217 // Fixture to track emitted intent events
Brian O'Connor66630c82014-10-02 21:08:19 -0700218 protected class TestListener implements IntentListener {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700219 final List<IntentEvent> events = new ArrayList<>();
220
221 @Override
222 public void event(IntentEvent event) {
223 events.add(event);
224 }
225 }
226
227 // Controllable compiler
228 private class TestCompiler implements IntentCompiler<TestIntent> {
229 private final boolean fail;
230 private final List<Intent> result;
231
232 TestCompiler(boolean fail) {
233 this.fail = fail;
234 this.result = Collections.emptyList();
235 }
236
237 TestCompiler(Intent... result) {
238 this.fail = false;
239 this.result = Arrays.asList(result);
240 }
241
242 @Override
Brian O'Connorfa81eae2014-10-30 13:20:05 -0700243 public List<Intent> compile(TestIntent intent, List<Intent> installable,
244 Set<LinkResourceAllocations> resources) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700245 if (fail) {
246 throw new IntentException("compile failed by design");
247 }
248 List<Intent> compiled = new ArrayList<>(result);
249 return compiled;
250 }
251 }
Brian O'Connorf3d06162014-10-02 15:54:12 -0700252}