blob: 987743a3cbe58b67eb62e0352d8339146b5fa2ac [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.felix.dm.itest.api;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentState;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.itest.util.Ensure;
import org.apache.felix.dm.itest.util.Ensure.Steps;
import org.apache.felix.dm.itest.util.TestBase;
import org.junit.Assert;
/**
* This test case verifies the following (corner case) scenario:
*
* - Component A depends on Required (required=true)
* - Component A depends on BService (required=false)
* - There is an aspect for the B service.
* - A ComponentStateListener on A removes the aspect if it detects that A is stopping.
*
* Now the test verifies the following: if the "Required" service is removed, then
* A must be :
*
* 1) swapped with the original B service (since the component state listener removes the B aspect while A is stopping),
* 2) called in A.remove(original B)
* 3) and called in A.stop()
*/
public class FELIX5429_AspectSwapCallbackNotCalledForOptionalDepenency extends TestBase {
final Ensure m_ensure = new Ensure();
public void testOptionalAspectRemovedWhenComponentIsStopped() {
DependencyManager m = getDM();
Component requiredComp = m.createComponent()
.setImplementation(new Required())
.setInterface(Required.class.getName(), null);
Component aComp = m.createComponent()
.setImplementation(new A())
.add(m.createServiceDependency().setService(BService.class).setRequired(false).setCallbacks("add", null, "remove", "swap"))
.add(m.createServiceDependency().setService(Required.class).setRequired(true).setCallbacks("add", "remove"));
Component bComp = m.createComponent()
.setImplementation(new B())
.setInterface(BService.class.getName(), null);
Component bAspectComp = m.createAspectService(BService.class, null, 1)
.setImplementation(new BAspect());
aComp.add((comp, state) -> {
if (state == ComponentState.STOPPING) {
System.out.println("removing B aspect");
m.remove(bAspectComp);
}
});
m.add(requiredComp);
m.add(aComp);
m.add(bComp);
m.add(bAspectComp);
System.out.println("removing Required");
m.remove(requiredComp);
System.out.println("---");
m_ensure.waitForStep(7, 5000);
}
class Required {
}
class A {
private BService m_b;
private final Ensure.Steps m_swapSteps = new Steps(4, 5);
void add(Required required) {
System.out.println("A.add(" + required.getClass().getSimpleName() + ")");
m_ensure.step(1);
}
void remove(Required required) {
System.out.println("A.remove(" + required.getClass().getSimpleName() + ")");
}
void start() {
System.out.println("A.start");
m_ensure.step(2);
}
void stop() {
System.out.println("A.stop");
m_ensure.step(7);
}
void add(BService b) {
m_b = b;
System.out.println("A.add(" + b.getClass().getSimpleName() + ")");
m_ensure.step(3);
}
void swap(BService oldB, BService newB) {
Assert.assertEquals(m_b, oldB);
m_b = newB;
System.out.println("A.swap(" + oldB.getClass().getSimpleName() + "," + newB.getClass().getSimpleName() + ")");
m_ensure.steps(m_swapSteps); // 4, 5
}
void remove(BService b) {
System.out.println("A.remove(" + b.getClass().getSimpleName() + ")");
m_ensure.step(6);
}
}
interface BService {
}
class B implements BService {
}
class BAspect implements BService {
}
}