blob: e4d906b2f2715b88fc171547d9e1df7a35310cab [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);
Brian O'Connor520c0522014-11-23 23:50:47 -080050 Intent.bindIdGenerator(idGenerator);
Brian O'Connorf3d06162014-10-02 15:54:12 -070051 }
52
53 @After
54 public void tearDown() {
55 service.removeListener(listener);
Brian O'Connor520c0522014-11-23 23:50:47 -080056 Intent.unbindIdGenerator(idGenerator);
Brian O'Connorf3d06162014-10-02 15:54:12 -070057 }
58
59 /**
60 * Creates a service instance appropriately instrumented for testing.
61 *
62 * @return testable intent service
63 */
64 protected TestableIntentService createIntentService() {
65 return new FakeIntentManager();
66 }
67
68 @Test
69 public void basics() {
70 // Make sure there are no intents
Brian O'Connor66630c82014-10-02 21:08:19 -070071 assertEquals("incorrect intent count", 0, service.getIntentCount());
Brian O'Connorf3d06162014-10-02 15:54:12 -070072
73 // Register a compiler and an installer both setup for success.
74 service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID)));
Brian O'Connorf3d06162014-10-02 15:54:12 -070075
76 final Intent intent = new TestIntent(IID);
77 service.submit(intent);
78
79 // Allow a small window of time until the intent is in the expected state
Sho SHIMIZU74626412015-09-11 11:46:27 -070080 TestTools.assertAfter(GRACE_MS, () ->
81 assertEquals("incorrect intent state", IntentState.INSTALLED, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -070082
83 // Make sure that all expected events have been emitted
Brian O'Connor7a71d5d2014-12-02 00:12:27 -080084 validateEvents(intent, INSTALL_REQ, INSTALLED);
Brian O'Connorf3d06162014-10-02 15:54:12 -070085
86 // Make sure there is just one intent (and is ours)
Brian O'Connor66630c82014-10-02 21:08:19 -070087 assertEquals("incorrect intent count", 1, service.getIntentCount());
Brian O'Connorf3d06162014-10-02 15:54:12 -070088
89 // Reset the listener events
90 listener.events.clear();
91
92 // Now withdraw the intent
93 service.withdraw(intent);
94
95 // Allow a small window of time until the event is in the expected state
Sho SHIMIZU74626412015-09-11 11:46:27 -070096 TestTools.assertAfter(GRACE_MS, () ->
97 assertEquals("incorrect intent state", IntentState.WITHDRAWN, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -070098
99 // Make sure that all expected events have been emitted
tom85258ee2014-10-07 00:10:02 -0700100 validateEvents(intent, WITHDRAWN);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700101
102 // TODO: discuss what is the fate of intents after they have been withdrawn
103 // Make sure that the intent is no longer in the system
104// assertEquals("incorrect intent count", 0, service.getIntents().size());
tom85258ee2014-10-07 00:10:02 -0700105// assertNull("intent should not be found", service.getIntent(intent.id()));
106// assertNull("intent state should not be found", service.getIntentState(intent.id()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700107 }
108
109 @Test
110 public void failedCompilation() {
111 // Register a compiler programmed for success
112 service.registerCompiler(TestIntent.class, new TestCompiler(true));
113
114 // Submit an intent
115 final Intent intent = new TestIntent(IID);
116 service.submit(intent);
117
118 // Allow a small window of time until the intent is in the expected state
Sho SHIMIZU74626412015-09-11 11:46:27 -0700119 TestTools.assertAfter(GRACE_MS, () ->
120 assertEquals("incorrect intent state", IntentState.FAILED, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700121
122 // Make sure that all expected events have been emitted
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800123 validateEvents(intent, INSTALL_REQ, FAILED);
Brian O'Connorf3d06162014-10-02 15:54:12 -0700124 }
125
Brian O'Connorf3d06162014-10-02 15:54:12 -0700126 /**
127 * Validates that the test event listener has received the following events
128 * for the specified intent. Events received for other intents will not be
129 * considered.
130 *
131 * @param intent intent subject
tom85258ee2014-10-07 00:10:02 -0700132 * @param types list of event types for which events are expected
Brian O'Connorf3d06162014-10-02 15:54:12 -0700133 */
tom85258ee2014-10-07 00:10:02 -0700134 protected void validateEvents(Intent intent, IntentEvent.Type... types) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700135 Iterator<IntentEvent> events = listener.events.iterator();
tom85258ee2014-10-07 00:10:02 -0700136 for (IntentEvent.Type type : types) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700137 IntentEvent event = events.hasNext() ? events.next() : null;
138 if (event == null) {
tom85258ee2014-10-07 00:10:02 -0700139 fail("expected event not found: " + type);
140 } else if (intent.equals(event.subject())) {
141 assertEquals("incorrect state", type, event.type());
Brian O'Connorf3d06162014-10-02 15:54:12 -0700142 }
143 }
144
145 // Remainder of events should not apply to this intent; make sure.
146 while (events.hasNext()) {
147 assertFalse("unexpected event for intent",
tom85258ee2014-10-07 00:10:02 -0700148 intent.equals(events.next().subject()));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700149 }
150 }
151
152 @Test
153 public void compilerBasics() {
154 // Make sure there are no compilers
155 assertEquals("incorrect compiler count", 0, service.getCompilers().size());
156
157 // Add a compiler and make sure that it appears in the map
158 IntentCompiler<TestIntent> compiler = new TestCompiler(false);
159 service.registerCompiler(TestIntent.class, compiler);
160 assertEquals("incorrect compiler", compiler,
161 service.getCompilers().get(TestIntent.class));
162
163 // Remove the same and make sure that it no longer appears in the map
164 service.unregisterCompiler(TestIntent.class);
165 assertNull("compiler should not be registered",
166 service.getCompilers().get(TestIntent.class));
167 }
168
169 @Test
Brian O'Connorf3d06162014-10-02 15:54:12 -0700170 public void implicitRegistration() {
171 // Add a compiler and make sure that it appears in the map
172 IntentCompiler<TestIntent> compiler = new TestCompiler(new TestSubclassInstallableIntent(INSTALLABLE_IID));
173 service.registerCompiler(TestIntent.class, compiler);
174 assertEquals("incorrect compiler", compiler,
175 service.getCompilers().get(TestIntent.class));
176
Brian O'Connorf3d06162014-10-02 15:54:12 -0700177 // Submit an intent which is a subclass of the one we registered
178 final Intent intent = new TestSubclassIntent(IID);
179 service.submit(intent);
180
181 // Allow some time for the intent to be compiled and installed
Sho SHIMIZU74626412015-09-11 11:46:27 -0700182 TestTools.assertAfter(GRACE_MS, () ->
183 assertEquals("incorrect intent state", IntentState.INSTALLED, service.getIntentState(intent.key())));
Brian O'Connorf3d06162014-10-02 15:54:12 -0700184
185 // Make sure that now we have an implicit registration of the compiler
186 // under the intent subclass
187 assertEquals("incorrect compiler", compiler,
188 service.getCompilers().get(TestSubclassIntent.class));
189
Brian O'Connorf3d06162014-10-02 15:54:12 -0700190 // TODO: discuss whether or if implicit registration should require implicit unregistration
191 // perhaps unregister by compiler or installer itself, rather than by class would be better
192 }
193
194
195 // Fixture to track emitted intent events
Brian O'Connor66630c82014-10-02 21:08:19 -0700196 protected class TestListener implements IntentListener {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700197 final List<IntentEvent> events = new ArrayList<>();
198
199 @Override
200 public void event(IntentEvent event) {
201 events.add(event);
202 }
203 }
204
205 // Controllable compiler
206 private class TestCompiler implements IntentCompiler<TestIntent> {
207 private final boolean fail;
208 private final List<Intent> result;
209
210 TestCompiler(boolean fail) {
211 this.fail = fail;
212 this.result = Collections.emptyList();
213 }
214
215 TestCompiler(Intent... result) {
216 this.fail = false;
217 this.result = Arrays.asList(result);
218 }
219
220 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800221 public List<Intent> compile(TestIntent intent, List<Intent> installable) {
Brian O'Connorf3d06162014-10-02 15:54:12 -0700222 if (fail) {
223 throw new IntentException("compile failed by design");
224 }
225 List<Intent> compiled = new ArrayList<>(result);
226 return compiled;
227 }
228 }
Brian O'Connorf3d06162014-10-02 15:54:12 -0700229}