blob: f629235387d77722cdc69378c8f9083b89ea7cdf [file] [log] [blame]
Pierre De Ropfaca2892016-01-31 23:27:05 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.dm.lambda.itest;
20
21import static org.apache.felix.dm.lambda.DependencyManagerActivator.aspect;
22import static org.apache.felix.dm.lambda.DependencyManagerActivator.component;
23
24import java.util.ArrayList;
25import java.util.List;
26
27import org.apache.felix.dm.Component;
28import org.apache.felix.dm.DependencyManager;
29import org.junit.Assert;
30import org.osgi.framework.ServiceReference;
31import org.osgi.framework.ServiceRegistration;
32
33/**
34 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
35 */
36public class AspectBaseTest extends TestBase {
37
38 public void testSingleAspect() {
39 DependencyManager m = getDM();
40 // helper class that ensures certain steps get executed in sequence
41 Ensure e = new Ensure();
42
43 // create a service provider and consumer
Pierre De Rop6e8f9212016-02-20 21:44:59 +000044 ServiceProvider p = new ServiceProvider("a");
Pierre De Ropfaca2892016-01-31 23:27:05 +000045 ServiceConsumer c = new ServiceConsumer(e);
46
47 Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
Pierre De Rop11527502016-02-18 21:07:16 +000048 Component sc = component(m).impl(c).withSvc(ServiceInterface.class, srv -> srv.add("add").remove("remove").autoConfig("m_service")).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +000049 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
50
51 m.add(sc);
52 m.add(sp);
53 // after the provider was added, the consumer's add should have been invoked once
54 e.waitForStep(1, 2000);
55 Assert.assertEquals("a", c.invoke());
56 m.add(sa);
57 // after the aspect was added, the consumer should get and add for the aspect and a remove
58 // for the original service
59 e.waitForStep(3, 2000);
60 Assert.assertEquals("aa", c.invoke());
61 m.remove(sa);
62 // removing the aspect again should give a remove and add
63 e.waitForStep(5, 2000);
64 Assert.assertEquals("a", c.invoke());
65 m.remove(sp);
66 // finally removing the original service should give a remove
67 e.waitForStep(6, 2000);
68 m.remove(sc);
69 e.step(7);
70 clearComponents();
71 }
72
73 public void testSingleAspectRef() {
74 DependencyManager m = getDM();
75 // helper class that ensures certain steps get executed in sequence
76 Ensure e = new Ensure();
77
78 // create a service provider and consumer
Pierre De Rop6e8f9212016-02-20 21:44:59 +000079 ServiceProvider p = new ServiceProvider("a");
Pierre De Ropfaca2892016-01-31 23:27:05 +000080 ServiceConsumer c = new ServiceConsumer(e);
81
82 Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
83 Component sc = component(m)
Pierre De Rop11527502016-02-18 21:07:16 +000084 .impl(c).withSvc(ServiceInterface.class, srv -> srv.add(c::addRef).remove(c::removeRef).autoConfig("m_service")).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +000085 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
86
87 m.add(sc);
88 m.add(sp);
89 // after the provider was added, the consumer's add should have been invoked once
90 e.waitForStep(1, 2000);
91 Assert.assertEquals("a", c.invoke());
92 m.add(sa);
93 // after the aspect was added, the consumer should get and add for the aspect and a remove
94 // for the original service
95 e.waitForStep(3, 2000);
96 Assert.assertEquals("aa", c.invoke());
97 m.remove(sa);
98 // removing the aspect again should give a remove and add
99 e.waitForStep(5, 2000);
100 Assert.assertEquals("a", c.invoke());
101 m.remove(sp);
102 // finally removing the original service should give a remove
103 e.waitForStep(6, 2000);
104 m.remove(sc);
105 e.step(7);
106 clearComponents();
107 }
108
Pierre De Ropfaca2892016-01-31 23:27:05 +0000109 public void testSingleAspectThatAlreadyExisted() {
110 DependencyManager m = new DependencyManager(context);
111 // helper class that ensures certain steps get executed in sequence
112 Ensure e = new Ensure();
113
114 // create a service provider and consumer
Pierre De Rop6e8f9212016-02-20 21:44:59 +0000115 ServiceProvider p = new ServiceProvider("a");
Pierre De Ropfaca2892016-01-31 23:27:05 +0000116 ServiceConsumer c = new ServiceConsumer(e);
117 Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000118 Component sc = component(m).impl(c).withSvc(ServiceInterface.class, srv -> srv.add("add").remove("remove").autoConfig("m_service")).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +0000119 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
120
121 // we first add the aspect
122 m.add(sa);
123 // then the service provider
124 m.add(sp);
125 // finally the consumer
126 m.add(sc);
127
128 Assert.assertEquals("aa", c.invoke());
129
130 // now the consumer's added should be invoked once, as the aspect is already available and should
131 // directly hide the original service
132 e.waitForStep(1, 2000);
133 e.step(2);
134
135 m.remove(sa);
136 // after removing the aspect, the consumer should get the original service back, so
137 // remove and add will be invoked
138 e.waitForStep(4, 2000);
139
140 Assert.assertEquals("a", c.invoke());
141
142 m.remove(sp);
143 // after removing the original service, the consumer's remove should be called once
144 e.waitForStep(5, 2000);
145
146 m.remove(sc);
147 e.step(6);
148 }
149
150 public void testSingleAspectThatAlreadyExistedRef() {
151 DependencyManager m = new DependencyManager(context);
152 // helper class that ensures certain steps get executed in sequence
153 Ensure e = new Ensure();
154
155 // create a service provider and consumer
Pierre De Rop6e8f9212016-02-20 21:44:59 +0000156 ServiceProvider p = new ServiceProvider("a");
Pierre De Ropfaca2892016-01-31 23:27:05 +0000157 ServiceConsumer c = new ServiceConsumer(e);
158
159 Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000160 Component sc = component(m).impl(c).withSvc(ServiceInterface.class, srv -> srv.add(c::addRef).remove(c::removeRef).autoConfig("m_service")).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +0000161 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
162
163 // we first add the aspect
164 m.add(sa);
165 // then the service provider
166 m.add(sp);
167 // finally the consumer
168 m.add(sc);
169
170 Assert.assertEquals("aa", c.invoke());
171
172 // now the consumer's added should be invoked once, as the aspect is already available and should
173 // directly hide the original service
174 e.waitForStep(1, 2000);
175 e.step(2);
176
177 m.remove(sa);
178 // after removing the aspect, the consumer should get the original service back, so
179 // remove and add will be invoked
180 e.waitForStep(4, 2000);
181
182 Assert.assertEquals("a", c.invoke());
183
184 m.remove(sp);
185 // after removing the original service, the consumer's remove should be called once
186 e.waitForStep(5, 2000);
187
188 m.remove(sc);
189 e.step(6);
190 }
191
192 public void testMultipleAspects() {
193 DependencyManager m = new DependencyManager(context);
194 // helper class that ensures certain steps get executed in sequence
195 Ensure e = new Ensure();
196
197 // create service providers and consumers
198 ServiceConsumer c = new ServiceConsumer(e);
Pierre De Rop6e8f9212016-02-20 21:44:59 +0000199 Component sp = component(m).impl(new ServiceProvider("a")).provides(ServiceInterface.class).properties(name -> "a").build();
200 Component sp2 = component(m).impl(new ServiceProvider("b")).provides(ServiceInterface.class).properties(name -> "b").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000201 Component sc = component(m).impl(c).withSvc(ServiceInterface.class, srv -> srv.add("add").remove("remove")).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +0000202
203 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
204 Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
205
206 m.add(sp);
207 m.add(sp2);
208 m.add(sa);
209 m.add(sa2);
210 m.add(sc);
211 // the consumer will monitor progress, it should get it's add invoked twice, once for every
212 // (highest) aspect
213 e.waitForStep(2, 2000);
214 e.step(3);
215
216 // now invoke all services the consumer collected
217 List<String> list = c.invokeAll();
218 // and make sure both of them are correctly invoked
219 Assert.assertTrue(list.size() == 2);
220 Assert.assertTrue(list.contains("aaa"));
221 Assert.assertTrue(list.contains("bbb"));
222
223 m.remove(sc);
224 // removing the consumer now should get its removed method invoked twice
225 e.waitForStep(5, 2000);
226 e.step(6);
227 m.remove(sa2);
228 m.remove(sa);
229 m.remove(sp2);
230 m.remove(sp);
231 e.step(7);
232 }
233
234 public void testMultipleAspectsRef() {
235 DependencyManager m = new DependencyManager(context);
236 // helper class that ensures certain steps get executed in sequence
237 Ensure e = new Ensure();
238
239 // create service providers and consumers
240 ServiceConsumer c = new ServiceConsumer(e);
Pierre De Rop6e8f9212016-02-20 21:44:59 +0000241 Component sp = component(m).impl(new ServiceProvider("a")).provides(ServiceInterface.class).properties(name -> "a").build();
242 Component sp2 = component(m).impl(new ServiceProvider("b")).provides(ServiceInterface.class).properties(name -> "b").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000243 Component sc = component(m).impl(c).withSvc(ServiceInterface.class, srv -> srv.add(c::addRef).remove(c::removeRef)).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +0000244
245 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
246 Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
247
248 m.add(sp);
249 m.add(sp2);
250 m.add(sa);
251 m.add(sa2);
252 m.add(sc);
253 // the consumer will monitor progress, it should get it's add invoked twice, once for every
254 // (highest) aspect
255 e.waitForStep(2, 2000);
256 e.step(3);
257
258 // now invoke all services the consumer collected
259 List<String> list = c.invokeAll();
260 // and make sure both of them are correctly invoked
261 Assert.assertTrue(list.size() == 2);
262 Assert.assertTrue(list.contains("aaa"));
263 Assert.assertTrue(list.contains("bbb"));
264
265 m.remove(sc);
266 // removing the consumer now should get its removed method invoked twice
267 e.waitForStep(5, 2000);
268 e.step(6);
269 m.remove(sa2);
270 m.remove(sa);
271 m.remove(sp2);
272 m.remove(sp);
273 e.step(7);
274 }
275
276 public static interface ServiceInterface {
277 public String invoke(String input);
278 }
279
280 public static class ServiceProvider implements ServiceInterface {
Pierre De Ropfaca2892016-01-31 23:27:05 +0000281 private final String m_name;
Pierre De Rop6e8f9212016-02-20 21:44:59 +0000282 public ServiceProvider(String name) {
Pierre De Ropfaca2892016-01-31 23:27:05 +0000283 m_name = name;
284 }
285 public String invoke(String input) {
286 return input + m_name;
287 }
288 }
289
290 public static class ServiceAspect implements ServiceInterface {
291 private volatile ServiceInterface m_originalService;
Pierre De Rop6e8f9212016-02-20 21:44:59 +0000292 private volatile ServiceRegistration<?> m_registration;
Pierre De Ropfaca2892016-01-31 23:27:05 +0000293
294 public String invoke(String input) {
295 String result = m_originalService.invoke(input);
296 String property = (String) m_registration.getReference().getProperty("name");
297 return result + property;
298 }
299 }
300
301 public static class ServiceConsumer {
302 private final Ensure m_ensure;
303 private volatile ServiceInterface m_service;
304 private List<ServiceInterface> m_services = new ArrayList<ServiceInterface>();
305
306 public ServiceConsumer(Ensure e) {
307 m_ensure = e;
308 }
309
Pierre De Rop11527502016-02-18 21:07:16 +0000310 public void addRef(ServiceInterface si, ServiceReference<ServiceInterface> ref) { // method ref callback
311 add(ref, si);
312 }
313
314 public void add(ServiceReference<ServiceInterface> ref, ServiceInterface si) { // reflection callback
Pierre De Ropfaca2892016-01-31 23:27:05 +0000315 System.out.println("add: " + ServiceUtil.toString(ref));
316 m_services.add(si);
317 m_ensure.step();
318 }
319
Pierre De Rop11527502016-02-18 21:07:16 +0000320 public void removeRef(ServiceInterface si, ServiceReference<ServiceInterface> ref) { // method ref callback
321 remove(ref, si);
322 }
323
324 public void remove(ServiceReference<ServiceInterface> ref, ServiceInterface si) { // reflection callback
Pierre De Ropfaca2892016-01-31 23:27:05 +0000325 System.out.println("rem: " + ServiceUtil.toString(ref));
326 m_services.remove(si);
327 m_ensure.step();
328 }
329
330 public String invoke() {
331 return m_service.invoke("");
332 }
333
334 public List<String> invokeAll() {
335 List<String> results = new ArrayList<String>();
336 for (ServiceInterface si : m_services) {
337 results.add(si.invoke(""));
338 }
339 return results;
340 }
341 }
342}