Skip to content

Commit

Permalink
Add LazyServiceComponentActivationDeadLockTest
Browse files Browse the repository at this point in the history
  • Loading branch information
HannesWell committed Jun 16, 2022
1 parent 48152cb commit 331931a
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 3 deletions.
1 change: 1 addition & 0 deletions bundles/org.eclipse.osgi.tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/bundle_tests/
/inner/
.DS_Store
/OSGI-INF/org.eclipse.osgi.*.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
classpath=true
dsVersion=V1_3
eclipse.preferences.version=1
enabled=true
generateBundleActivationPolicyLazy=true
path=OSGI-INF
validationErrorLevel=error
validationErrorLevel.missingImplicitUnbindMethod=error
7 changes: 7 additions & 0 deletions bundles/org.eclipse.osgi.tests/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,10 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
DynamicImport-Package: ext.framework.b
Eclipse-BundleShape: dir
Automatic-Module-Name: org.eclipse.osgi.tests
Service-Component: OSGI-INF/org.eclipse.osgi.tests.services.resolver.LazyServiceComponentActivationDeadLockTest$MavenImpl.xml,
OSGI-INF/org.eclipse.osgi.tests.services.resolver.LazyServiceComponentActivationDeadLockTest$MavenModelManager$HeavyComponent.xml,
OSGI-INF/org.eclipse.osgi.tests.services.resolver.LazyServiceComponentActivationDeadLockTest$MavenModelManager.xml,
OSGI-INF/org.eclipse.osgi.tests.services.resolver.LazyServiceComponentActivationDeadLockTest$MavenProjectManager$HeavyComponent.xml,
OSGI-INF/org.eclipse.osgi.tests.services.resolver.LazyServiceComponentActivationDeadLockTest$MavenProjectManager.xml,
OSGI-INF/org.eclipse.osgi.tests.services.resolver.LazyServiceComponentActivationDeadLockTest$ProjectConfigurationManager.xml,
OSGI-INF/org.eclipse.osgi.tests.services.resolver.LazyServiceComponentActivationDeadLockTest$RepositoryRegistry.xml
5 changes: 3 additions & 2 deletions bundles/org.eclipse.osgi.tests/build.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ bin.includes = .,\
test.xml,\
bundle_tests/*.jar,\
plugin.xml,\
profile.list
profile.list,\
OSGI-INF/

source.bundle_tests/test.jar = bundles_src/test/
manifest.bundle_tests/test.jar = META-INF/MANIFEST.MF
Expand Down Expand Up @@ -416,4 +417,4 @@ jars.compile.order = bundle_tests/ext.framework.b.jar,\
bundle_tests/test.dynamic.privateimport.jar,\
bundle_tests/test.bug490902.b.jar,\
bundle_tests/test.bug490902.a.jar,\
bundle_tests/mrBundleInputBase.jar
bundle_tests/mrBundleInputBase.jar
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
XFriendsInternalResolverTest.class, //
GenericCapabilityTest.class, //
OSGiCapabilityTest.class, //
DevModeTest.class })
DevModeTest.class, //
LazyServiceComponentActivationDeadLockTest.class })
public class AllTests {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*******************************************************************************
* Copyright (c) 2022, 2022 Hannes Wellmann and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Hannes Wellmann - initial API and implementation
*******************************************************************************/

package org.eclipse.osgi.tests.services.resolver;

import static org.junit.Assert.assertNotNull;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;

public class LazyServiceComponentActivationDeadLockTest {

// TODO: add test cases for dead-lock due to lazy activation in different
// bundles?!

@Test
public void testLateBindingInSameBundleDeadLock() throws Exception {
BundleContext ctx = FrameworkUtil.getBundle(LazyServiceComponentActivationDeadLockTest.class)
.getBundleContext();
ServiceReference<ProjectConfigurationManager> reference = ctx
.getServiceReference(ProjectConfigurationManager.class);

ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Future<ProjectConfigurationManager> service = executor.submit(() -> ctx.getService(reference));
assertNotNull(service.get(5, TimeUnit.SECONDS)); // times out in case of dead-lock
} finally {
executor.shutdown();
// ctx.ungetService(reference);
}
}

@Component(service = ProjectConfigurationManager.class)
public static class ProjectConfigurationManager {

@Reference
MavenImpl maven;

@Reference
MavenModelManager mavenModelManager;

}

@Component(service = MavenModelManager.class)
public static class MavenModelManager {

@Reference
private MavenProjectManager projectManager;

// The nested component below ensures that the activation of this component
// starts after the activation of MavenProjectManager has started in the SCR
// Actor thread.

@Reference
HeavyComponent AAA; // Capital letters are important to ensure this reference is handled first

@Component(service = HeavyComponent.class)
public static class HeavyComponent {

@Activate
public void activated() throws InterruptedException {
MavenProjectManager.HeavyComponent.ACTIVATED.await();
}
}
}

@Component(service = MavenProjectManager.class)
public static class MavenProjectManager {

private final List<ProjectConfigurationManager> listenerManager = new ArrayList<>();

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
public void addMavenProjectChangedListener(ProjectConfigurationManager listener) {
listenerManager.add(listener);
}

public void removeMavenProjectChangedListener(ProjectConfigurationManager listener) {
listenerManager.remove(listener);
}

// The nested component below ensures that the activation of this component
// starts after the activation of MavenModelManager has started in the main
// thread.

@Reference
HeavyComponent AAA; // Capital letters are important to ensure this reference is handled first

@Component(service = HeavyComponent.class)
public static class HeavyComponent {
public static final CountDownLatch ACTIVATED = new CountDownLatch(1);

@Activate
public void activated() {
ACTIVATED.countDown();
}
}
}

@Component(service = MavenImpl.class)
public static class MavenImpl {

@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
private final List<RepositoryRegistry> settingsListeners = new CopyOnWriteArrayList<>();
}

@Component(service = RepositoryRegistry.class)
public static class RepositoryRegistry {

@Reference
private MavenImpl maven;

@Reference
MavenProjectManager projectManager;
}

}

0 comments on commit 331931a

Please sign in to comment.