blob: d652eb77991ebcf738617e2aa499332f167bfd15 [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
44 ServiceProvider p = new ServiceProvider(e, "a");
45 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
79 ServiceProvider p = new ServiceProvider(e, "a");
80 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
109 @SuppressWarnings("serial")
110 public void testSingleAspectThatAlreadyExisted() {
111 DependencyManager m = new DependencyManager(context);
112 // helper class that ensures certain steps get executed in sequence
113 Ensure e = new Ensure();
114
115 // create a service provider and consumer
116 ServiceProvider p = new ServiceProvider(e, "a");
117 ServiceConsumer c = new ServiceConsumer(e);
118 Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000119 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 +0000120 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
121
122 // we first add the aspect
123 m.add(sa);
124 // then the service provider
125 m.add(sp);
126 // finally the consumer
127 m.add(sc);
128
129 Assert.assertEquals("aa", c.invoke());
130
131 // now the consumer's added should be invoked once, as the aspect is already available and should
132 // directly hide the original service
133 e.waitForStep(1, 2000);
134 e.step(2);
135
136 m.remove(sa);
137 // after removing the aspect, the consumer should get the original service back, so
138 // remove and add will be invoked
139 e.waitForStep(4, 2000);
140
141 Assert.assertEquals("a", c.invoke());
142
143 m.remove(sp);
144 // after removing the original service, the consumer's remove should be called once
145 e.waitForStep(5, 2000);
146
147 m.remove(sc);
148 e.step(6);
149 }
150
151 public void testSingleAspectThatAlreadyExistedRef() {
152 DependencyManager m = new DependencyManager(context);
153 // helper class that ensures certain steps get executed in sequence
154 Ensure e = new Ensure();
155
156 // create a service provider and consumer
157 ServiceProvider p = new ServiceProvider(e, "a");
158 ServiceConsumer c = new ServiceConsumer(e);
159
160 Component sp = component(m).impl(p).provides(ServiceInterface.class).properties(name -> "a").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000161 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 +0000162 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
163
164 // we first add the aspect
165 m.add(sa);
166 // then the service provider
167 m.add(sp);
168 // finally the consumer
169 m.add(sc);
170
171 Assert.assertEquals("aa", c.invoke());
172
173 // now the consumer's added should be invoked once, as the aspect is already available and should
174 // directly hide the original service
175 e.waitForStep(1, 2000);
176 e.step(2);
177
178 m.remove(sa);
179 // after removing the aspect, the consumer should get the original service back, so
180 // remove and add will be invoked
181 e.waitForStep(4, 2000);
182
183 Assert.assertEquals("a", c.invoke());
184
185 m.remove(sp);
186 // after removing the original service, the consumer's remove should be called once
187 e.waitForStep(5, 2000);
188
189 m.remove(sc);
190 e.step(6);
191 }
192
193 public void testMultipleAspects() {
194 DependencyManager m = new DependencyManager(context);
195 // helper class that ensures certain steps get executed in sequence
196 Ensure e = new Ensure();
197
198 // create service providers and consumers
199 ServiceConsumer c = new ServiceConsumer(e);
200 Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build();
201 Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000202 Component sc = component(m).impl(c).withSvc(ServiceInterface.class, srv -> srv.add("add").remove("remove")).build();
Pierre De Ropfaca2892016-01-31 23:27:05 +0000203
204 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
205 Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
206
207 m.add(sp);
208 m.add(sp2);
209 m.add(sa);
210 m.add(sa2);
211 m.add(sc);
212 // the consumer will monitor progress, it should get it's add invoked twice, once for every
213 // (highest) aspect
214 e.waitForStep(2, 2000);
215 e.step(3);
216
217 // now invoke all services the consumer collected
218 List<String> list = c.invokeAll();
219 // and make sure both of them are correctly invoked
220 Assert.assertTrue(list.size() == 2);
221 Assert.assertTrue(list.contains("aaa"));
222 Assert.assertTrue(list.contains("bbb"));
223
224 m.remove(sc);
225 // removing the consumer now should get its removed method invoked twice
226 e.waitForStep(5, 2000);
227 e.step(6);
228 m.remove(sa2);
229 m.remove(sa);
230 m.remove(sp2);
231 m.remove(sp);
232 e.step(7);
233 }
234
235 public void testMultipleAspectsRef() {
236 DependencyManager m = new DependencyManager(context);
237 // helper class that ensures certain steps get executed in sequence
238 Ensure e = new Ensure();
239
240 // create service providers and consumers
241 ServiceConsumer c = new ServiceConsumer(e);
242 Component sp = component(m).impl(new ServiceProvider(e, "a")).provides(ServiceInterface.class).properties(name -> "a").build();
243 Component sp2 = component(m).impl(new ServiceProvider(e, "b")).provides(ServiceInterface.class).properties(name -> "b").build();
Pierre De Rop11527502016-02-18 21:07:16 +0000244 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 +0000245
246 Component sa = aspect(m, ServiceInterface.class).rank(20).impl(ServiceAspect.class).build();
247 Component sa2 = aspect(m, ServiceInterface.class).rank(10).impl(ServiceAspect.class).build();
248
249 m.add(sp);
250 m.add(sp2);
251 m.add(sa);
252 m.add(sa2);
253 m.add(sc);
254 // the consumer will monitor progress, it should get it's add invoked twice, once for every
255 // (highest) aspect
256 e.waitForStep(2, 2000);
257 e.step(3);
258
259 // now invoke all services the consumer collected
260 List<String> list = c.invokeAll();
261 // and make sure both of them are correctly invoked
262 Assert.assertTrue(list.size() == 2);
263 Assert.assertTrue(list.contains("aaa"));
264 Assert.assertTrue(list.contains("bbb"));
265
266 m.remove(sc);
267 // removing the consumer now should get its removed method invoked twice
268 e.waitForStep(5, 2000);
269 e.step(6);
270 m.remove(sa2);
271 m.remove(sa);
272 m.remove(sp2);
273 m.remove(sp);
274 e.step(7);
275 }
276
277 public static interface ServiceInterface {
278 public String invoke(String input);
279 }
280
281 public static class ServiceProvider implements ServiceInterface {
282 private final Ensure m_ensure;
283 private final String m_name;
284 public ServiceProvider(Ensure e, String name) {
285 m_ensure = e;
286 m_name = name;
287 }
288 public String invoke(String input) {
289 return input + m_name;
290 }
291 }
292
293 public static class ServiceAspect implements ServiceInterface {
294 private volatile ServiceInterface m_originalService;
295 private volatile ServiceRegistration m_registration;
296
297 public String invoke(String input) {
298 String result = m_originalService.invoke(input);
299 String property = (String) m_registration.getReference().getProperty("name");
300 return result + property;
301 }
302 }
303
304 public static class ServiceConsumer {
305 private final Ensure m_ensure;
306 private volatile ServiceInterface m_service;
307 private List<ServiceInterface> m_services = new ArrayList<ServiceInterface>();
308
309 public ServiceConsumer(Ensure e) {
310 m_ensure = e;
311 }
312
Pierre De Rop11527502016-02-18 21:07:16 +0000313 public void addRef(ServiceInterface si, ServiceReference<ServiceInterface> ref) { // method ref callback
314 add(ref, si);
315 }
316
317 public void add(ServiceReference<ServiceInterface> ref, ServiceInterface si) { // reflection callback
Pierre De Ropfaca2892016-01-31 23:27:05 +0000318 System.out.println("add: " + ServiceUtil.toString(ref));
319 m_services.add(si);
320 m_ensure.step();
321 }
322
Pierre De Rop11527502016-02-18 21:07:16 +0000323 public void removeRef(ServiceInterface si, ServiceReference<ServiceInterface> ref) { // method ref callback
324 remove(ref, si);
325 }
326
327 public void remove(ServiceReference<ServiceInterface> ref, ServiceInterface si) { // reflection callback
Pierre De Ropfaca2892016-01-31 23:27:05 +0000328 System.out.println("rem: " + ServiceUtil.toString(ref));
329 m_services.remove(si);
330 m_ensure.step();
331 }
332
333 public String invoke() {
334 return m_service.invoke("");
335 }
336
337 public List<String> invokeAll() {
338 List<String> results = new ArrayList<String>();
339 for (ServiceInterface si : m_services) {
340 results.add(si.invoke(""));
341 }
342 return results;
343 }
344 }
345}