From 3587fc64a40ef7a88a25cb35c86956dabe919ada Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 16:46:14 +0200 Subject: [PATCH 01/10] Scaffold org.osgi:org.osgi.compendium:5.0.0 --- .../org.osgi/org.osgi.compendium/index.json | 14 +++++++++++++ .../org.osgi.compendium/5.0.0/.gitignore | 4 ++++ .../org.osgi.compendium/5.0.0/build.gradle | 16 +++++++++++++++ .../5.0.0/gradle.properties | 6 ++++++ .../org.osgi.compendium/5.0.0/settings.gradle | 20 +++++++++++++++++++ .../Org_osgi_compendiumTest.java | 16 +++++++++++++++ 6 files changed, 76 insertions(+) create mode 100644 metadata/org.osgi/org.osgi.compendium/index.json create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/.gitignore create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/gradle.properties create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/settings.gradle create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java diff --git a/metadata/org.osgi/org.osgi.compendium/index.json b/metadata/org.osgi/org.osgi.compendium/index.json new file mode 100644 index 00000000000..e0df60c7393 --- /dev/null +++ b/metadata/org.osgi/org.osgi.compendium/index.json @@ -0,0 +1,14 @@ +[ + { + "latest": true, + "allowed-packages": [ "org.osgi" ], + "metadata-version": "5.0.0", + "source-code-url": "https://repo.maven.apache.org/maven2/org/osgi/org.osgi.compendium/5.0.0/org.osgi.compendium-5.0.0-sources.jar", + "repository-url": "https://github.com/osgi/osgi", + "test-code-url": "https://github.com/osgi/osgi/tree/r5-cmpn-ri-ct-final", + "documentation-url": "https://repo.maven.apache.org/maven2/org/osgi/org.osgi.compendium/5.0.0/org.osgi.compendium-5.0.0-javadoc.jar", + "tested-versions": [ + "5.0.0" + ] + } +] diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/.gitignore b/tests/src/org.osgi/org.osgi.compendium/5.0.0/.gitignore new file mode 100644 index 00000000000..c98c7875b0e --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/.gitignore @@ -0,0 +1,4 @@ +gradlew.bat +gradlew +gradle/ +build/ diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle b/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle new file mode 100644 index 00000000000..da18bc8e9ca --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle @@ -0,0 +1,16 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +plugins { + id "org.graalvm.internal.tck" +} + +String libraryVersion = tck.testedLibraryVersion.get() + +dependencies { + testImplementation "org.osgi:org.osgi.compendium:$libraryVersion" + testImplementation 'org.assertj:assertj-core:3.22.0' +} diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/gradle.properties b/tests/src/org.osgi/org.osgi.compendium/5.0.0/gradle.properties new file mode 100644 index 00000000000..ab0b263358e --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/gradle.properties @@ -0,0 +1,6 @@ +# Optional explicit tested library coordinates (format: group:artifact:version). +# If omitted, fallback resolution in org.graalvm.internal.tck.gradle still uses +# environment variable GVM_TCK_LC and then this property. +library.coordinates = org.osgi:org.osgi.compendium:5.0.0 +library.version = 5.0.0 +metadata.dir = org.osgi/org.osgi.compendium/5.0.0/ diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/settings.gradle b/tests/src/org.osgi/org.osgi.compendium/5.0.0/settings.gradle new file mode 100644 index 00000000000..a874aaf2505 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/settings.gradle @@ -0,0 +1,20 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +pluginManagement { + def tckPath = Objects.requireNonNullElse( + System.getenv("GVM_TCK_TCKDIR"), + "../../../../tck-build-logic" + ) + includeBuild(tckPath) + repositories { mavenLocal(); gradlePluginPortal() } +} + +plugins { + id "org.graalvm.internal.tck-settings" version "1.0.0-SNAPSHOT" +} + +rootProject.name = 'org.osgi.org.osgi.compendium_tests' diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java new file mode 100644 index 00000000000..a3f218c0bd3 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java @@ -0,0 +1,16 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium; + +import org.junit.jupiter.api.Test; + +class Org_osgi_compendiumTest { + @Test + void test() throws Exception { + System.out.println("This is just a placeholder, implement your test"); + } +} From e328a1b79eb143ceac9a74c16516191cd2c87ae4 Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 16:49:01 +0200 Subject: [PATCH 02/10] Add ApplicationDescriptor delegate coverage test --- .../ApplicationDescriptorDelegate1Test.java | 118 ++++++++++++++++++ .../Org_osgi_compendiumTest.java | 16 --- 2 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java delete mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java new file mode 100644 index 00000000000..e3c7fbb124d --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java @@ -0,0 +1,118 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.osgi.service.application.ApplicationDescriptor; +import org.osgi.service.application.ApplicationHandle; +import org.osgi.service.application.ApplicationException; +import org.osgi.service.application.ScheduledApplication; + +public class ApplicationDescriptorDelegate1Test { + private static final String IMPLEMENTATION_PROPERTY = + "org.osgi.vendor.application.ApplicationDescriptor"; + + @Test + void constructorLoadsVendorDelegateImplementationFromSystemProperty() { + String previousImplementation = System.getProperty(IMPLEMENTATION_PROPERTY); + System.setProperty(IMPLEMENTATION_PROPERTY, VendorApplicationDescriptor.class.getName()); + + try { + VendorApplicationDescriptor.reset(); + + TestApplicationDescriptor descriptor = new TestApplicationDescriptor("example.application"); + + assertThat(descriptor.getApplicationId()).isEqualTo("example.application"); + assertThat(VendorApplicationDescriptor.boundApplicationId).isEqualTo("example.application"); + assertThat(VendorApplicationDescriptor.boundDescriptor).isSameAs(descriptor); + } finally { + if (previousImplementation == null) { + System.clearProperty(IMPLEMENTATION_PROPERTY); + } else { + System.setProperty(IMPLEMENTATION_PROPERTY, previousImplementation); + } + } + } + + public static final class VendorApplicationDescriptor { + private static ApplicationDescriptor boundDescriptor; + private static String boundApplicationId; + + public static void reset() { + boundDescriptor = null; + boundApplicationId = null; + } + + public void setApplicationDescriptor(ApplicationDescriptor descriptor, String applicationId) { + boundDescriptor = descriptor; + boundApplicationId = applicationId; + } + + public boolean isLocked() { + return false; + } + + public void lock() { + } + + public void unlock() { + } + + public ScheduledApplication schedule( + String scheduleId, + Map arguments, + String topic, + String eventFilter, + boolean recurring) { + return null; + } + + public ApplicationHandle launch(Map arguments) { + return null; + } + } + + private static final class TestApplicationDescriptor extends ApplicationDescriptor { + private TestApplicationDescriptor(String applicationId) { + super(applicationId); + } + + @Override + public boolean matchDNChain(String pattern) { + return false; + } + + @Override + protected Map getPropertiesSpecific(String locale) { + return Collections.emptyMap(); + } + + @Override + protected ApplicationHandle launchSpecific(Map arguments) throws Exception { + throw new ApplicationException( + ApplicationException.APPLICATION_INTERNAL_ERROR, + "launchSpecific should not be invoked by this coverage test"); + } + + @Override + protected boolean isLaunchableSpecific() { + return true; + } + + @Override + protected void lockSpecific() { + } + + @Override + protected void unlockSpecific() { + } + } +} diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java deleted file mode 100644 index a3f218c0bd3..00000000000 --- a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/Org_osgi_compendiumTest.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright and related rights waived via CC0 - * - * You should have received a copy of the CC0 legalcode along with this - * work. If not, see . - */ -package org_osgi.org_osgi_compendium; - -import org.junit.jupiter.api.Test; - -class Org_osgi_compendiumTest { - @Test - void test() throws Exception { - System.out.println("This is just a placeholder, implement your test"); - } -} From bb1bb216d7bf308dc777c1e9e5cb6090e712bb27 Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 16:49:51 +0200 Subject: [PATCH 03/10] Add OSGi core test dependency --- tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle b/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle index da18bc8e9ca..3f06e54ade2 100644 --- a/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle @@ -11,6 +11,7 @@ plugins { String libraryVersion = tck.testedLibraryVersion.get() dependencies { + testImplementation "org.osgi:org.osgi.core:$libraryVersion" testImplementation "org.osgi:org.osgi.compendium:$libraryVersion" testImplementation 'org.assertj:assertj-core:3.22.0' } From 6e4c3dc09330eb47a79b3e33aa3f7419ffa1f1e3 Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 16:54:07 +0200 Subject: [PATCH 04/10] Add ApplicationDescriptor delegate coverage tests --- .../ApplicationDescriptorDelegate1Test.java | 245 ++++++++++++++++-- 1 file changed, 222 insertions(+), 23 deletions(-) diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java index e3c7fbb124d..2a3d5ac3730 100644 --- a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationDescriptorDelegate1Test.java @@ -8,47 +8,164 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.util.Collections; +import java.util.HashMap; import java.util.Map; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.osgi.service.application.ApplicationDescriptor; import org.osgi.service.application.ApplicationHandle; import org.osgi.service.application.ApplicationException; import org.osgi.service.application.ScheduledApplication; +import org.osgi.framework.InvalidSyntaxException; public class ApplicationDescriptorDelegate1Test { private static final String IMPLEMENTATION_PROPERTY = "org.osgi.vendor.application.ApplicationDescriptor"; + private static String previousImplementation; + + @BeforeAll + static void setUpVendorImplementation() { + previousImplementation = System.getProperty(IMPLEMENTATION_PROPERTY); + System.setProperty(IMPLEMENTATION_PROPERTY, VendorApplicationDescriptor.class.getName()); + } + + @AfterAll + static void restoreVendorImplementation() { + if (previousImplementation == null) { + System.clearProperty(IMPLEMENTATION_PROPERTY); + } else { + System.setProperty(IMPLEMENTATION_PROPERTY, previousImplementation); + } + } + + @BeforeEach + void resetVendorState() { + VendorApplicationDescriptor.reset(); + } @Test void constructorLoadsVendorDelegateImplementationFromSystemProperty() { - String previousImplementation = System.getProperty(IMPLEMENTATION_PROPERTY); - System.setProperty(IMPLEMENTATION_PROPERTY, VendorApplicationDescriptor.class.getName()); + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application", false, true); - try { - VendorApplicationDescriptor.reset(); + assertThat(descriptor.getApplicationId()).isEqualTo("example.application"); + assertThat(VendorApplicationDescriptor.boundApplicationId).isEqualTo("example.application"); + assertThat(VendorApplicationDescriptor.boundDescriptor).isSameAs(descriptor); + } + + @Test + void getPropertiesUsesVendorIsLockedState() { + VendorApplicationDescriptor.locked = true; + + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application", false, true); + + Map properties = descriptor.getProperties(null); + + assertThat(properties).containsEntry(ApplicationDescriptor.APPLICATION_LOCKED, Boolean.TRUE); + assertThat(VendorApplicationDescriptor.isLockedCalls).isEqualTo(1); + assertThat(descriptor.lockSpecificCalls).isEqualTo(1); + assertThat(descriptor.unlockSpecificCalls).isZero(); + } - TestApplicationDescriptor descriptor = new TestApplicationDescriptor("example.application"); + @Test + void lockDelegatesToVendorImplementation() { + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application", false, true); + + descriptor.lock(); + + assertThat(VendorApplicationDescriptor.lockCalls).isEqualTo(1); + assertThat(descriptor.lockSpecificCalls).isEqualTo(1); + } + + @Test + void unlockDelegatesToVendorImplementation() { + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application", false, true); + + descriptor.unlock(); + + assertThat(VendorApplicationDescriptor.unlockCalls).isEqualTo(1); + assertThat(descriptor.unlockSpecificCalls).isEqualTo(1); + } + + @Test + void scheduleDelegatesToVendorImplementation() throws ApplicationException, InvalidSyntaxException { + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application", false, true); + Map arguments = new HashMap(); + arguments.put("mode", "full"); + + ScheduledApplication scheduledApplication = + descriptor.schedule("nightly", arguments, "app/topic", "(mode=full)", true); + + assertThat(VendorApplicationDescriptor.scheduleCalls).isEqualTo(1); + assertThat(VendorApplicationDescriptor.lastScheduleId).isEqualTo("nightly"); + assertThat(VendorApplicationDescriptor.lastArguments).isSameAs(arguments); + assertThat(VendorApplicationDescriptor.lastTopic).isEqualTo("app/topic"); + assertThat(VendorApplicationDescriptor.lastEventFilter).isEqualTo("(mode=full)"); + assertThat(VendorApplicationDescriptor.lastRecurring).isTrue(); + assertThat(scheduledApplication).isSameAs(VendorApplicationDescriptor.lastScheduledApplication); + } + + @Test + void launchInvokesVendorDelegateBeforeLaunchabilityCheck() { + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application", false, false); + Map arguments = new HashMap(); + arguments.put("mode", "dry-run"); - assertThat(descriptor.getApplicationId()).isEqualTo("example.application"); - assertThat(VendorApplicationDescriptor.boundApplicationId).isEqualTo("example.application"); - assertThat(VendorApplicationDescriptor.boundDescriptor).isSameAs(descriptor); - } finally { - if (previousImplementation == null) { - System.clearProperty(IMPLEMENTATION_PROPERTY); - } else { - System.setProperty(IMPLEMENTATION_PROPERTY, previousImplementation); - } + ApplicationException applicationException = null; + try { + descriptor.launch(arguments); + } catch (ApplicationException ex) { + applicationException = ex; } + + assertThat(applicationException).isNotNull(); + assertThat(applicationException.getErrorCode()) + .isEqualTo(ApplicationException.APPLICATION_NOT_LAUNCHABLE); + assertThat(applicationException).hasMessage("Cannot launch the application!"); + assertThat(VendorApplicationDescriptor.launchCalls).isEqualTo(1); + assertThat(VendorApplicationDescriptor.lastLaunchArguments).isSameAs(arguments); } public static final class VendorApplicationDescriptor { private static ApplicationDescriptor boundDescriptor; private static String boundApplicationId; + private static boolean locked; + private static int isLockedCalls; + private static int lockCalls; + private static int unlockCalls; + private static int scheduleCalls; + private static int launchCalls; + private static String lastScheduleId; + private static Map lastArguments; + private static String lastTopic; + private static String lastEventFilter; + private static boolean lastRecurring; + private static ScheduledApplication lastScheduledApplication; + private static Map lastLaunchArguments; public static void reset() { boundDescriptor = null; boundApplicationId = null; + locked = false; + isLockedCalls = 0; + lockCalls = 0; + unlockCalls = 0; + scheduleCalls = 0; + launchCalls = 0; + lastScheduleId = null; + lastArguments = null; + lastTopic = null; + lastEventFilter = null; + lastRecurring = false; + lastScheduledApplication = null; + lastLaunchArguments = null; } public void setApplicationDescriptor(ApplicationDescriptor descriptor, String applicationId) { @@ -57,13 +174,16 @@ public void setApplicationDescriptor(ApplicationDescriptor descriptor, String ap } public boolean isLocked() { - return false; + isLockedCalls++; + return locked; } public void lock() { + lockCalls++; } public void unlock() { + unlockCalls++; } public ScheduledApplication schedule( @@ -72,17 +192,36 @@ public ScheduledApplication schedule( String topic, String eventFilter, boolean recurring) { - return null; + scheduleCalls++; + lastScheduleId = scheduleId; + lastArguments = arguments; + lastTopic = topic; + lastEventFilter = eventFilter; + lastRecurring = recurring; + lastScheduledApplication = + new TestScheduledApplication( + scheduleId, topic, eventFilter, recurring, boundDescriptor, arguments); + return lastScheduledApplication; } public ApplicationHandle launch(Map arguments) { + launchCalls++; + lastLaunchArguments = arguments; return null; } } private static final class TestApplicationDescriptor extends ApplicationDescriptor { - private TestApplicationDescriptor(String applicationId) { + private final boolean launchable; + private final boolean containerLocked; + private int lockSpecificCalls; + private int unlockSpecificCalls; + + private TestApplicationDescriptor( + String applicationId, boolean containerLocked, boolean launchable) { super(applicationId); + this.containerLocked = containerLocked; + this.launchable = launchable; } @Override @@ -92,27 +231,87 @@ public boolean matchDNChain(String pattern) { @Override protected Map getPropertiesSpecific(String locale) { - return Collections.emptyMap(); + Map properties = new HashMap(); + properties.put(APPLICATION_LOCKED, Boolean.valueOf(containerLocked)); + return properties; } @Override protected ApplicationHandle launchSpecific(Map arguments) throws Exception { - throw new ApplicationException( - ApplicationException.APPLICATION_INTERNAL_ERROR, - "launchSpecific should not be invoked by this coverage test"); + throw new AssertionError("launchSpecific should not be invoked by this coverage test"); } @Override protected boolean isLaunchableSpecific() { - return true; + return launchable; } @Override protected void lockSpecific() { + lockSpecificCalls++; } @Override protected void unlockSpecific() { + unlockSpecificCalls++; + } + } + + private static final class TestScheduledApplication implements ScheduledApplication { + private final String scheduleId; + private final String topic; + private final String eventFilter; + private final boolean recurring; + private final ApplicationDescriptor descriptor; + private final Map arguments; + + private TestScheduledApplication( + String scheduleId, + String topic, + String eventFilter, + boolean recurring, + ApplicationDescriptor descriptor, + Map arguments) { + this.scheduleId = scheduleId; + this.topic = topic; + this.eventFilter = eventFilter; + this.recurring = recurring; + this.descriptor = descriptor; + this.arguments = arguments; + } + + @Override + public String getScheduleId() { + return scheduleId; + } + + @Override + public String getTopic() { + return topic; + } + + @Override + public String getEventFilter() { + return eventFilter; + } + + @Override + public boolean isRecurring() { + return recurring; + } + + @Override + public ApplicationDescriptor getApplicationDescriptor() { + return descriptor; + } + + @Override + public Map getArguments() { + return arguments; + } + + @Override + public void remove() { } } } From e38a7c11ec67aa69094cd934947bc605d2f66249 Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 16:58:02 +0200 Subject: [PATCH 05/10] Add ApplicationHandle delegate coverage test --- .../ApplicationHandleDelegate1Test.java | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationHandleDelegate1Test.java diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationHandleDelegate1Test.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationHandleDelegate1Test.java new file mode 100644 index 00000000000..88ea7719a67 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/ApplicationHandleDelegate1Test.java @@ -0,0 +1,159 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.osgi.service.application.ApplicationDescriptor; +import org.osgi.service.application.ApplicationHandle; + +public class ApplicationHandleDelegate1Test { + private static final String DESCRIPTOR_IMPLEMENTATION_PROPERTY = + "org.osgi.vendor.application.ApplicationDescriptor"; + private static final String HANDLE_IMPLEMENTATION_PROPERTY = + "org.osgi.vendor.application.ApplicationHandle"; + + private static String previousDescriptorImplementation; + private static String previousHandleImplementation; + + @BeforeAll + static void setUpVendorImplementations() { + previousDescriptorImplementation = System.getProperty(DESCRIPTOR_IMPLEMENTATION_PROPERTY); + previousHandleImplementation = System.getProperty(HANDLE_IMPLEMENTATION_PROPERTY); + System.setProperty( + DESCRIPTOR_IMPLEMENTATION_PROPERTY, + ApplicationDescriptorDelegate1Test.VendorApplicationDescriptor.class.getName()); + System.setProperty(HANDLE_IMPLEMENTATION_PROPERTY, VendorApplicationHandle.class.getName()); + } + + @AfterAll + static void restoreVendorImplementations() { + if (previousDescriptorImplementation == null) { + System.clearProperty(DESCRIPTOR_IMPLEMENTATION_PROPERTY); + } else { + System.setProperty(DESCRIPTOR_IMPLEMENTATION_PROPERTY, previousDescriptorImplementation); + } + + if (previousHandleImplementation == null) { + System.clearProperty(HANDLE_IMPLEMENTATION_PROPERTY); + } else { + System.setProperty(HANDLE_IMPLEMENTATION_PROPERTY, previousHandleImplementation); + } + } + + @BeforeEach + void resetVendorState() { + ApplicationDescriptorDelegate1Test.VendorApplicationDescriptor.reset(); + VendorApplicationHandle.reset(); + } + + @Test + void constructorLoadsVendorDelegateImplementationFromSystemProperty() { + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application"); + + TestApplicationHandle handle = + new TestApplicationHandle("example.application.1", descriptor); + + assertThat(handle.getInstanceId()).isEqualTo("example.application.1"); + assertThat(handle.getApplicationDescriptor()).isSameAs(descriptor); + assertThat(VendorApplicationHandle.boundHandle).isSameAs(handle); + assertThat(VendorApplicationHandle.boundDescriptorDelegate).isNotNull(); + } + + @Test + void destroyDelegatesToVendorImplementation() { + TestApplicationDescriptor descriptor = + new TestApplicationDescriptor("example.application"); + TestApplicationHandle handle = + new TestApplicationHandle("example.application.1", descriptor); + + handle.destroy(); + + assertThat(VendorApplicationHandle.destroyCalls).isEqualTo(1); + assertThat(handle.destroySpecificCalls).isEqualTo(1); + } + + public static final class VendorApplicationHandle { + private static ApplicationHandle boundHandle; + private static Object boundDescriptorDelegate; + private static int destroyCalls; + + public static void reset() { + boundHandle = null; + boundDescriptorDelegate = null; + destroyCalls = 0; + } + + public void setApplicationHandle(ApplicationHandle handle, Object descriptorDelegate) { + boundHandle = handle; + boundDescriptorDelegate = descriptorDelegate; + } + + public void destroy() { + destroyCalls++; + } + } + + private static final class TestApplicationDescriptor extends ApplicationDescriptor { + private TestApplicationDescriptor(String applicationId) { + super(applicationId); + } + + @Override + public boolean matchDNChain(String pattern) { + return false; + } + + @Override + protected Map getPropertiesSpecific(String locale) { + return new HashMap(); + } + + @Override + protected ApplicationHandle launchSpecific(Map arguments) { + throw new AssertionError("launchSpecific should not be invoked by this coverage test"); + } + + @Override + protected boolean isLaunchableSpecific() { + return true; + } + + @Override + protected void lockSpecific() { + } + + @Override + protected void unlockSpecific() { + } + } + + private static final class TestApplicationHandle extends ApplicationHandle { + private int destroySpecificCalls; + + private TestApplicationHandle(String instanceId, ApplicationDescriptor descriptor) { + super(instanceId, descriptor); + } + + @Override + public String getState() { + return RUNNING; + } + + @Override + protected void destroySpecific() { + destroySpecificCalls++; + } + } +} From 890e595af04da13f371601d9e915af48b1a0f362 Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 17:10:30 +0200 Subject: [PATCH 06/10] Add DeploymentAdminPermission initializer coverage test --- .../DeploymentAdminPermission1Test.java | 79 ++++++++++++++++ .../DeploymentAdminPermission.java | 90 +++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentAdminPermission1Test.java create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentAdminPermission.java diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentAdminPermission1Test.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentAdminPermission1Test.java new file mode 100644 index 00000000000..7602f58aea9 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentAdminPermission1Test.java @@ -0,0 +1,79 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.osgi.service.deploymentadmin.DeploymentAdminPermission; + +public class DeploymentAdminPermission1Test { + private static final String IMPLEMENTATION_PROPERTY = "org.osgi.vendor.deploymentadmin"; + private static final String IMPLEMENTATION_PACKAGE = + "org_osgi.org_osgi_compendium.vendor.deploymentadmin"; + + private static String previousImplementationPackage; + + @BeforeAll + static void setUpVendorImplementation() { + previousImplementationPackage = System.getProperty(IMPLEMENTATION_PROPERTY); + System.setProperty(IMPLEMENTATION_PROPERTY, IMPLEMENTATION_PACKAGE); + } + + @AfterAll + static void restoreVendorImplementation() { + if (previousImplementationPackage == null) { + System.clearProperty(IMPLEMENTATION_PROPERTY); + } else { + System.setProperty(IMPLEMENTATION_PROPERTY, previousImplementationPackage); + } + } + + @BeforeEach + void resetVendorState() { + org_osgi.org_osgi_compendium.vendor.deploymentadmin.DeploymentAdminPermission.reset(); + } + + @Test + void constructorLoadsVendorPermissionClassFromConfiguredPackage() { + DeploymentAdminPermission permission = + new DeploymentAdminPermission("(name=example.bundle)", "list"); + + assertThat(permission.getActions()).isEqualTo("list"); + assertThat( + org_osgi.org_osgi_compendium.vendor.deploymentadmin + .DeploymentAdminPermission.constructorCalls) + .isEqualTo(1); + assertThat( + org_osgi.org_osgi_compendium.vendor.deploymentadmin + .DeploymentAdminPermission.lastCreatedName) + .isEqualTo("(name=example.bundle)"); + assertThat( + org_osgi.org_osgi_compendium.vendor.deploymentadmin + .DeploymentAdminPermission.lastCreatedActions) + .isEqualTo("list"); + } + + @Test + void impliesDelegatesToVendorPermissionInstance() { + DeploymentAdminPermission authorizingPermission = + new DeploymentAdminPermission("(name=example.bundle)", "list,metadata"); + DeploymentAdminPermission requestedPermission = + new DeploymentAdminPermission("(name=example.bundle)", "list"); + + boolean implied = authorizingPermission.implies(requestedPermission); + + assertThat(implied).isTrue(); + assertThat( + org_osgi.org_osgi_compendium.vendor.deploymentadmin + .DeploymentAdminPermission.impliesCalls) + .isEqualTo(1); + } +} diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentAdminPermission.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentAdminPermission.java new file mode 100644 index 00000000000..3847e89ae54 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentAdminPermission.java @@ -0,0 +1,90 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium.vendor.deploymentadmin; + +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + +public final class DeploymentAdminPermission extends Permission { + public static int constructorCalls; + public static int impliesCalls; + public static String lastCreatedName; + public static String lastCreatedActions; + + private final Set actionSet; + private final String actions; + + public static void reset() { + constructorCalls = 0; + impliesCalls = 0; + lastCreatedName = null; + lastCreatedActions = null; + } + + public DeploymentAdminPermission(String name, String actions) { + super(name); + constructorCalls++; + lastCreatedName = name; + lastCreatedActions = normalizeActions(actions); + this.actionSet = parseActions(actions); + this.actions = String.join(",", this.actionSet); + } + + @Override + public boolean implies(Permission permission) { + impliesCalls++; + if (!(permission instanceof DeploymentAdminPermission other)) { + return false; + } + return Objects.equals(getName(), other.getName()) && actionSet.containsAll(other.actionSet); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof DeploymentAdminPermission other)) { + return false; + } + return Objects.equals(getName(), other.getName()) + && Objects.equals(actionSet, other.actionSet); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), actionSet); + } + + @Override + public String getActions() { + return actions; + } + + @Override + public PermissionCollection newPermissionCollection() { + return new Permissions(); + } + + private static Set parseActions(String actions) { + LinkedHashSet normalizedActions = new LinkedHashSet(); + for (String action : normalizeActions(actions).split(",")) { + if (!action.isEmpty()) { + normalizedActions.add(action); + } + } + return normalizedActions; + } + + private static String normalizeActions(String actions) { + return actions.replace(" ", ""); + } +} From e3f6849d6aa6e05fcb96a2cefa99662af6a5620e Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 17:13:47 +0200 Subject: [PATCH 07/10] Add DeploymentCustomizerPermission coverage test --- .../DeploymentCustomizerPermission1Test.java | 63 ++++++++++++++++ .../DeploymentCustomizerPermission.java | 75 +++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentCustomizerPermission1Test.java create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentCustomizerPermission.java diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentCustomizerPermission1Test.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentCustomizerPermission1Test.java new file mode 100644 index 00000000000..6be26cd7df8 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DeploymentCustomizerPermission1Test.java @@ -0,0 +1,63 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.osgi.service.deploymentadmin.spi.DeploymentCustomizerPermission; + +public class DeploymentCustomizerPermission1Test { + private static final String IMPLEMENTATION_PROPERTY = "org.osgi.vendor.deploymentadmin"; + private static final String IMPLEMENTATION_PACKAGE = + "org_osgi.org_osgi_compendium.vendor.deploymentadmin"; + + private static String previousImplementationPackage; + + @BeforeAll + static void setUpVendorImplementation() { + previousImplementationPackage = System.getProperty(IMPLEMENTATION_PROPERTY); + System.setProperty(IMPLEMENTATION_PROPERTY, IMPLEMENTATION_PACKAGE); + } + + @AfterAll + static void restoreVendorImplementation() { + if (previousImplementationPackage == null) { + System.clearProperty(IMPLEMENTATION_PROPERTY); + } else { + System.setProperty(IMPLEMENTATION_PROPERTY, previousImplementationPackage); + } + } + + @BeforeEach + void resetVendorState() { + org_osgi.org_osgi_compendium.vendor.deploymentadmin.DeploymentCustomizerPermission.reset(); + } + + @Test + void constructorLoadsVendorPermissionClassFromConfiguredPackage() { + DeploymentCustomizerPermission permission = + new DeploymentCustomizerPermission("(name=example.bundle)", "privatearea"); + + assertThat(permission.getActions()).isEqualTo("privatearea"); + assertThat( + org_osgi.org_osgi_compendium.vendor.deploymentadmin + .DeploymentCustomizerPermission.constructorCalls) + .isEqualTo(1); + assertThat( + org_osgi.org_osgi_compendium.vendor.deploymentadmin + .DeploymentCustomizerPermission.lastCreatedName) + .isEqualTo("(name=example.bundle)"); + assertThat( + org_osgi.org_osgi_compendium.vendor.deploymentadmin + .DeploymentCustomizerPermission.lastCreatedActions) + .isEqualTo("privatearea"); + } +} diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentCustomizerPermission.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentCustomizerPermission.java new file mode 100644 index 00000000000..2613ecfbda4 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/vendor/deploymentadmin/DeploymentCustomizerPermission.java @@ -0,0 +1,75 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium.vendor.deploymentadmin; + +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.Permissions; +import java.util.Locale; +import java.util.Objects; + +public final class DeploymentCustomizerPermission extends Permission { + public static int constructorCalls; + public static String lastCreatedName; + public static String lastCreatedActions; + + private final String actions; + + public static void reset() { + constructorCalls = 0; + lastCreatedName = null; + lastCreatedActions = null; + } + + public DeploymentCustomizerPermission(String name, String actions) { + super(name); + constructorCalls++; + lastCreatedName = name; + this.actions = normalizeActions(actions); + lastCreatedActions = this.actions; + } + + @Override + public boolean implies(Permission permission) { + if (!(permission instanceof DeploymentCustomizerPermission other)) { + return false; + } + return Objects.equals(getName(), other.getName()) + && Objects.equals(actions, other.actions); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof DeploymentCustomizerPermission other)) { + return false; + } + return Objects.equals(getName(), other.getName()) + && Objects.equals(actions, other.actions); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), actions); + } + + @Override + public String getActions() { + return actions; + } + + @Override + public PermissionCollection newPermissionCollection() { + return new Permissions(); + } + + private static String normalizeActions(String actions) { + return actions.toLowerCase(Locale.ROOT).replace(" ", ""); + } +} From 54626006c874c0f329a8051cf2804d528ec48304 Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 17:17:26 +0200 Subject: [PATCH 08/10] Add DmtData integer coverage test --- .../org_osgi_compendium/DmtData1Test.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DmtData1Test.java diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DmtData1Test.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DmtData1Test.java new file mode 100644 index 00000000000..f7421a30fec --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/DmtData1Test.java @@ -0,0 +1,24 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.osgi.service.dmt.DmtData; + +public class DmtData1Test { + @Test + void intConstructorCreatesIntegerDataAndExposesIntegerMetadata() { + DmtData data = new DmtData(42); + + assertThat(data.getFormat()).isEqualTo(DmtData.FORMAT_INTEGER); + assertThat(data.getInt()).isEqualTo(42); + assertThat(data.getFormatName()).isEqualTo("integer"); + assertThat(data.getSize()).isEqualTo(Integer.BYTES); + } +} From 7eebf421345faeecedc4ddd2c0de4ebd91cef94f Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 17:22:04 +0200 Subject: [PATCH 09/10] Add XMLParserActivator coverage test --- .../XMLParserActivator1Test.java | 502 ++++++++++++++++++ 1 file changed, 502 insertions(+) create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/XMLParserActivator1Test.java diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/XMLParserActivator1Test.java b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/XMLParserActivator1Test.java new file mode 100644 index 00000000000..e7ad67279e2 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/src/test/java/org_osgi/org_osgi_compendium/XMLParserActivator1Test.java @@ -0,0 +1,502 @@ +/* + * Copyright and related rights waived via CC0 + * + * You should have received a copy of the CC0 legalcode along with this + * work. If not, see . + */ +package org_osgi.org_osgi_compendium; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.BundleListener; +import org.osgi.framework.Constants; +import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkListener; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceListener; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.Version; +import org.osgi.util.xml.XMLParserActivator; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.xml.sax.EntityResolver; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class XMLParserActivator1Test { + @TempDir + Path tempDir; + + @BeforeEach + void resetFactoryState() { + TestDocumentBuilderFactory.reset(); + } + + @Test + void startInstantiatesConfiguredDocumentBuilderFactoryClass() throws Exception { + Path servicesDirectory = tempDir.resolve("META-INF/services"); + Files.createDirectories(servicesDirectory); + Path domFactoryServiceFile = servicesDirectory.resolve(XMLParserActivator.DOMFACTORYNAME); + Files.writeString( + domFactoryServiceFile, + TestDocumentBuilderFactory.class.getName() + System.lineSeparator()); + + TestBundle bundle = new TestBundle(17L); + bundle.addResource(XMLParserActivator.DOMCLASSFILE, domFactoryServiceFile.toUri().toURL()); + TestBundleContext context = new TestBundleContext(bundle); + XMLParserActivator activator = new XMLParserActivator(); + + activator.start(context); + + assertThat(TestDocumentBuilderFactory.constructorCalls).isEqualTo(1); + assertThat(context.registrationClasses).containsExactly(XMLParserActivator.DOMFACTORYNAME); + assertThat(context.registrationProperties).hasSize(1); + Hashtable properties = context.registrationProperties.get(0); + assertThat(properties.get(Constants.SERVICE_DESCRIPTION)) + .isEqualTo("A JAXP Compliant DOM Parser"); + assertThat(properties.get(Constants.SERVICE_PID)) + .isEqualTo("javax.xml.parsers.DocumentBuilderFactory.17.0"); + assertThat(properties.get(XMLParserActivator.PARSER_VALIDATING)).isEqualTo(Boolean.TRUE); + assertThat(properties.get(XMLParserActivator.PARSER_NAMESPACEAWARE)).isEqualTo(Boolean.TRUE); + assertThat(properties.get("parser.factoryname")) + .isEqualTo(TestDocumentBuilderFactory.class.getName()); + } + + public static final class TestDocumentBuilderFactory extends DocumentBuilderFactory { + private static int constructorCalls; + + public TestDocumentBuilderFactory() { + constructorCalls++; + } + + static void reset() { + constructorCalls = 0; + } + + @Override + public DocumentBuilder newDocumentBuilder() { + return new TestDocumentBuilder(isNamespaceAware(), isValidating()); + } + + @Override + public void setAttribute(String name, Object value) { + } + + @Override + public Object getAttribute(String name) { + return null; + } + + @Override + public void setFeature(String name, boolean value) { + } + + @Override + public boolean getFeature(String name) { + return false; + } + } + + private static final class TestDocumentBuilder extends DocumentBuilder { + private final boolean namespaceAware; + private final boolean validating; + + private TestDocumentBuilder(boolean namespaceAware, boolean validating) { + this.namespaceAware = namespaceAware; + this.validating = validating; + } + + @Override + public Document parse(InputSource is) throws SAXException, IOException { + throw new UnsupportedOperationException("parse is not used by this coverage test"); + } + + @Override + public boolean isNamespaceAware() { + return namespaceAware; + } + + @Override + public boolean isValidating() { + return validating; + } + + @Override + public void setEntityResolver(EntityResolver er) { + } + + @Override + public void setErrorHandler(ErrorHandler eh) { + } + + @Override + public Document newDocument() { + return null; + } + + @Override + public DOMImplementation getDOMImplementation() { + return null; + } + } + + private static final class TestBundleContext implements BundleContext { + private final TestBundle bundle; + private final List registrationClasses = new ArrayList<>(); + private final List> registrationProperties = + new ArrayList<>(); + + private TestBundleContext(TestBundle bundle) { + this.bundle = bundle; + } + + @Override + public String getProperty(String key) { + throw new UnsupportedOperationException(); + } + + @Override + public Bundle getBundle() { + return bundle; + } + + @Override + public Bundle installBundle(String location, InputStream input) throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public Bundle installBundle(String location) throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public Bundle getBundle(long id) { + throw new UnsupportedOperationException(); + } + + @Override + public Bundle[] getBundles() { + throw new UnsupportedOperationException(); + } + + @Override + public void addServiceListener(ServiceListener listener, String filter) + throws InvalidSyntaxException { + throw new UnsupportedOperationException(); + } + + @Override + public void addServiceListener(ServiceListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeServiceListener(ServiceListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void addBundleListener(BundleListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeBundleListener(BundleListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void addFrameworkListener(FrameworkListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeFrameworkListener(FrameworkListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceRegistration registerService( + String[] clazzes, Object service, Dictionary properties) { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceRegistration registerService( + String clazz, Object service, Dictionary properties) { + registrationClasses.add(clazz); + registrationProperties.add(copyDictionary(properties)); + return new TestServiceRegistration(); + } + + @Override + public ServiceRegistration registerService( + Class clazz, S service, Dictionary properties) { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceReference[] getServiceReferences(String clazz, String filter) + throws InvalidSyntaxException { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceReference[] getAllServiceReferences(String clazz, String filter) + throws InvalidSyntaxException { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceReference getServiceReference(String clazz) { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceReference getServiceReference(Class clazz) { + throw new UnsupportedOperationException(); + } + + @Override + public Collection> getServiceReferences(Class clazz, String filter) + throws InvalidSyntaxException { + throw new UnsupportedOperationException(); + } + + @Override + public S getService(ServiceReference reference) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean ungetService(ServiceReference reference) { + throw new UnsupportedOperationException(); + } + + @Override + public File getDataFile(String filename) { + throw new UnsupportedOperationException(); + } + + @Override + public Filter createFilter(String filter) throws InvalidSyntaxException { + throw new UnsupportedOperationException(); + } + + @Override + public Bundle getBundle(String location) { + throw new UnsupportedOperationException(); + } + + private static Hashtable copyDictionary(Dictionary properties) { + Hashtable copiedProperties = new Hashtable<>(); + Enumeration keys = properties.keys(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + copiedProperties.put(key, properties.get(key)); + } + return copiedProperties; + } + } + + private static final class TestServiceRegistration implements ServiceRegistration { + @Override + public ServiceReference getReference() { + throw new UnsupportedOperationException(); + } + + @Override + public void setProperties(Dictionary properties) { + throw new UnsupportedOperationException(); + } + + @Override + public void unregister() { + throw new UnsupportedOperationException(); + } + } + + private static final class TestBundle implements Bundle { + private final long bundleId; + private final Map resources = new HashMap<>(); + + private TestBundle(long bundleId) { + this.bundleId = bundleId; + } + + private void addResource(String path, URL resource) { + resources.put(path, resource); + } + + @Override + public int getState() { + throw new UnsupportedOperationException(); + } + + @Override + public void start(int options) throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public void start() throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public void stop(int options) throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public void stop() throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public void update(InputStream input) throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public void update() throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public void uninstall() throws BundleException { + throw new UnsupportedOperationException(); + } + + @Override + public Dictionary getHeaders() { + throw new UnsupportedOperationException(); + } + + @Override + public long getBundleId() { + return bundleId; + } + + @Override + public String getLocation() { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceReference[] getRegisteredServices() { + throw new UnsupportedOperationException(); + } + + @Override + public ServiceReference[] getServicesInUse() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasPermission(Object permission) { + throw new UnsupportedOperationException(); + } + + @Override + public URL getResource(String name) { + return resources.get(name); + } + + @Override + public Dictionary getHeaders(String locale) { + throw new UnsupportedOperationException(); + } + + @Override + public String getSymbolicName() { + throw new UnsupportedOperationException(); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + return Class.forName(name); + } + + @Override + public Enumeration getResources(String name) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration getEntryPaths(String path) { + throw new UnsupportedOperationException(); + } + + @Override + public URL getEntry(String path) { + throw new UnsupportedOperationException(); + } + + @Override + public long getLastModified() { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration findEntries(String path, String filePattern, boolean recurse) { + throw new UnsupportedOperationException(); + } + + @Override + public BundleContext getBundleContext() { + throw new UnsupportedOperationException(); + } + + @Override + public Map> getSignerCertificates(int signersType) { + throw new UnsupportedOperationException(); + } + + @Override + public Version getVersion() { + throw new UnsupportedOperationException(); + } + + @Override + public A adapt(Class type) { + throw new UnsupportedOperationException(); + } + + @Override + public File getDataFile(String filename) { + throw new UnsupportedOperationException(); + } + + @Override + public int compareTo(Bundle other) { + return Long.compare(bundleId, other.getBundleId()); + } + } +} From 5f41e0c9c4b05ff9f2ca1e781d3edd8fe6de29f8 Mon Sep 17 00:00:00 2001 From: Mihailo Markovic Date: Wed, 8 Apr 2026 17:27:31 +0200 Subject: [PATCH 10/10] Update generated library support for org.osgi:org.osgi.compendium:5.0.0 --- .../5.0.0/reachability-metadata.json | 210 ++++++++++++++++++ stats/stats.json | 41 ++++ .../org.osgi.compendium/5.0.0/build.gradle | 11 + .../5.0.0/user-code-filter.json | 10 + 4 files changed, 272 insertions(+) create mode 100644 metadata/org.osgi/org.osgi.compendium/5.0.0/reachability-metadata.json create mode 100644 tests/src/org.osgi/org.osgi.compendium/5.0.0/user-code-filter.json diff --git a/metadata/org.osgi/org.osgi.compendium/5.0.0/reachability-metadata.json b/metadata/org.osgi/org.osgi.compendium/5.0.0/reachability-metadata.json new file mode 100644 index 00000000000..bde90aa14d1 --- /dev/null +++ b/metadata/org.osgi/org.osgi.compendium/5.0.0/reachability-metadata.json @@ -0,0 +1,210 @@ +{ + "reflection": [ + { + "condition": { + "typeReached": "org.osgi.service.dmt.DmtData" + }, + "type": "java.lang.Boolean" + }, + { + "condition": { + "typeReached": "org.osgi.service.dmt.DmtData" + }, + "type": "java.lang.Integer" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationHandle" + }, + "type": "java.lang.Object" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationDescriptor" + }, + "type": "java.lang.String" + }, + { + "condition": { + "typeReached": "org.osgi.service.deploymentadmin.DeploymentAdminPermission" + }, + "type": "java.lang.String" + }, + { + "condition": { + "typeReached": "org.osgi.service.deploymentadmin.spi.DeploymentCustomizerPermission" + }, + "type": "java.lang.String" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationDescriptor" + }, + "type": "java.util.Map" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationDescriptor" + }, + "type": "org.osgi.service.application.ApplicationDescriptor" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationHandle" + }, + "type": "org.osgi.service.application.ApplicationHandle" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationDescriptor$Delegate" + }, + "type": "org_osgi.org_osgi_compendium.ApplicationDescriptorDelegate1Test$VendorApplicationDescriptor", + "methods": [ + { + "name": "isLocked", + "parameterTypes": [] + }, + { + "name": "launch", + "parameterTypes": [ + "java.util.Map" + ] + }, + { + "name": "lock", + "parameterTypes": [] + }, + { + "name": "schedule", + "parameterTypes": [ + "java.lang.String", + "java.util.Map", + "java.lang.String", + "java.lang.String", + "boolean" + ] + }, + { + "name": "setApplicationDescriptor", + "parameterTypes": [ + "org.osgi.service.application.ApplicationDescriptor", + "java.lang.String" + ] + }, + { + "name": "unlock", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationDescriptor$Delegate$1" + }, + "type": "org_osgi.org_osgi_compendium.ApplicationDescriptorDelegate1Test$VendorApplicationDescriptor" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationDescriptor$Delegate$2" + }, + "type": "org_osgi.org_osgi_compendium.ApplicationDescriptorDelegate1Test$VendorApplicationDescriptor", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationHandle$Delegate" + }, + "type": "org_osgi.org_osgi_compendium.ApplicationHandleDelegate1Test$VendorApplicationHandle", + "methods": [ + { + "name": "destroy", + "parameterTypes": [] + }, + { + "name": "setApplicationHandle", + "parameterTypes": [ + "org.osgi.service.application.ApplicationHandle", + "java.lang.Object" + ] + } + ] + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationHandle$Delegate$1" + }, + "type": "org_osgi.org_osgi_compendium.ApplicationHandleDelegate1Test$VendorApplicationHandle" + }, + { + "condition": { + "typeReached": "org.osgi.service.application.ApplicationHandle$Delegate$2" + }, + "type": "org_osgi.org_osgi_compendium.ApplicationHandleDelegate1Test$VendorApplicationHandle", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReached": "org.osgi.util.xml.XMLParserActivator" + }, + "type": "org_osgi.org_osgi_compendium.XMLParserActivator1Test$TestDocumentBuilderFactory", + "methods": [ + { + "name": "", + "parameterTypes": [] + } + ] + }, + { + "condition": { + "typeReached": "org.osgi.service.deploymentadmin.DeploymentAdminPermission" + }, + "type": "org_osgi.org_osgi_compendium.vendor.deploymentadmin.DeploymentAdminPermission", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.String", + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReached": "org.osgi.service.deploymentadmin.DeploymentAdminPermission$1" + }, + "type": "org_osgi.org_osgi_compendium.vendor.deploymentadmin.DeploymentAdminPermission" + }, + { + "condition": { + "typeReached": "org.osgi.service.deploymentadmin.spi.DeploymentCustomizerPermission" + }, + "type": "org_osgi.org_osgi_compendium.vendor.deploymentadmin.DeploymentCustomizerPermission", + "methods": [ + { + "name": "", + "parameterTypes": [ + "java.lang.String", + "java.lang.String" + ] + } + ] + }, + { + "condition": { + "typeReached": "org.osgi.service.deploymentadmin.spi.DeploymentCustomizerPermission$1" + }, + "type": "org_osgi.org_osgi_compendium.vendor.deploymentadmin.DeploymentCustomizerPermission" + } + ] +} \ No newline at end of file diff --git a/stats/stats.json b/stats/stats.json index 5afa1d2b637..fd3c3d9bd0e 100644 --- a/stats/stats.json +++ b/stats/stats.json @@ -5912,6 +5912,47 @@ } } }, + "org.osgi:org.osgi.compendium" : { + "metadataVersions" : { + "5.0.0" : { + "versions" : [ { + "version" : "5.0.0", + "dynamicAccess" : { + "breakdown" : { + "reflection" : { + "coverageRatio" : 1.0, + "coveredCalls" : 32, + "totalCalls" : 32 + } + }, + "coverageRatio" : 1.0, + "coveredCalls" : 32, + "totalCalls" : 32 + }, + "libraryCoverage" : { + "instruction" : { + "covered" : 1065, + "missed" : 17528, + "ratio" : 0.05728, + "total" : 18593 + }, + "line" : { + "covered" : 240, + "missed" : 3477, + "ratio" : 0.064568, + "total" : 3717 + }, + "method" : { + "covered" : 63, + "missed" : 600, + "ratio" : 0.095023, + "total" : 663 + } + } + } ] + } + } + }, "org.postgresql:postgresql" : { "metadataVersions" : { "42.3.4" : { diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle b/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle index 3f06e54ade2..66301702ad8 100644 --- a/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/build.gradle @@ -15,3 +15,14 @@ dependencies { testImplementation "org.osgi:org.osgi.compendium:$libraryVersion" testImplementation 'org.assertj:assertj-core:3.22.0' } + +graalvmNative { + agent { + defaultMode = "conditional" + modes { + conditional { + userCodeFilterPath = "user-code-filter.json" + } + } + } +} diff --git a/tests/src/org.osgi/org.osgi.compendium/5.0.0/user-code-filter.json b/tests/src/org.osgi/org.osgi.compendium/5.0.0/user-code-filter.json new file mode 100644 index 00000000000..493e888eb28 --- /dev/null +++ b/tests/src/org.osgi/org.osgi.compendium/5.0.0/user-code-filter.json @@ -0,0 +1,10 @@ +{ + "rules" : [ + { + "excludeClasses" : "**" + }, + { + "includeClasses" : "org.osgi.**" + } + ] +}