Bug 544423 - getBundles(): versionRange was not honored

Fixes regression detected via Bug#545878: Argument versionRange was not
used and thus getBundles did not filter bundles by versions.
Also make sure that bundles are sorted and highest version comes first
to match the contract of getBundle().

Added test cases for methods isFragment(), getBundle() & getBundles().

Add org.eclipse.jdt.annotation & org.eclipse.core.filesystem as optional
dependency for testing
purpose. Without the test methods does not find the bundles in the
platform.

Change-Id: Ied640949fc23e2c260b265797320c8dd5475150a
Signed-off-by: Karsten Thoms <karsten.thoms@itemis.de>
diff --git a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/runtime/InternalPlatform.java b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/runtime/InternalPlatform.java
index de79541..eeda2b8 100644
--- a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/runtime/InternalPlatform.java
+++ b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/runtime/InternalPlatform.java
@@ -228,7 +228,7 @@
 
 	public Bundle[] getBundles(String symbolicName, String versionRange) {
 		Map<String, String> directives = Collections.singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE,
-				getRequirementFilter(symbolicName, null));
+				getRequirementFilter(symbolicName, versionRange));
 		Collection<BundleCapability> matchingBundleCapabilities = fwkWiring.findProviders(ModuleContainer
 				.createRequirement(IdentityNamespace.IDENTITY_NAMESPACE, directives, Collections.emptyMap()));
 
@@ -239,9 +239,10 @@
 		Bundle[] results = matchingBundleCapabilities.stream().map(c -> c.getRevision().getBundle())
 				// Remove all the bundles that are installed or uninstalled
 				.filter(bundle -> (bundle.getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0)
+				.sorted((b1, b2) -> b2.getVersion().compareTo(b1.getVersion())) // highest version first
 				.toArray(Bundle[]::new);
 
-		return results;
+		return results.length > 0 ? results : null;
 	}
 
 	private String getRequirementFilter(String symbolicName, String versionRange) {
diff --git a/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF b/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF
index 4707958..4acc0f0 100644
--- a/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.core.tests.runtime/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Eclipse Core Tests Runtime
 Bundle-SymbolicName: org.eclipse.core.tests.runtime; singleton:=true
-Bundle-Version: 3.11.600.qualifier
+Bundle-Version: 3.11.700.qualifier
 Bundle-Activator: org.eclipse.core.tests.runtime.RuntimeTestsPlugin
 Bundle-Vendor: Eclipse.org
 Export-Package: org.eclipse.core.tests.internal.preferences,
@@ -19,3 +19,5 @@
 Plugin-Class: org.eclipse.core.tests.runtime.RuntimeTestsPlugin
 Eclipse-BundleShape: dir
 Automatic-Module-Name: org.eclipse.core.tests.runtime
+Import-Package: org.eclipse.core.filesystem;resolution:=optional,
+ org.eclipse.jdt.annotation;resolution:=optional
diff --git a/tests/org.eclipse.core.tests.runtime/pom.xml b/tests/org.eclipse.core.tests.runtime/pom.xml
index 014ece2..1f74bc2 100644
--- a/tests/org.eclipse.core.tests.runtime/pom.xml
+++ b/tests/org.eclipse.core.tests.runtime/pom.xml
@@ -20,7 +20,7 @@
   </parent>
   <groupId>org.eclipse.core</groupId>
   <artifactId>org.eclipse.core.tests.runtime</artifactId>
-  <version>3.11.600-SNAPSHOT</version>
+  <version>3.11.700-SNAPSHOT</version>
   <packaging>eclipse-test-plugin</packaging>
   <properties>
     <defaultSigning-excludeInnerJars>true</defaultSigning-excludeInnerJars>
diff --git a/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/PlatformTest.java b/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/PlatformTest.java
index 2422b5c..f0fccfd 100644
--- a/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/PlatformTest.java
+++ b/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/PlatformTest.java
@@ -17,13 +17,15 @@
 import java.util.*;
 import org.eclipse.core.runtime.*;
 import org.eclipse.osgi.framework.log.FrameworkLog;
-import org.osgi.framework.ServiceReference;
+import org.osgi.framework.*;
 
 /**
  * Test cases for the Platform API
  */
 public class PlatformTest extends RuntimeTest {
 
+	private static final String PI_JDT_ANNOTATION = "org.eclipse.jdt.annotation";
+	private static final String PI_FILESYSTEM = "org.eclipse.core.filesystem";
 	private FrameworkLog logService;
 	private ServiceReference<FrameworkLog> logRef;
 	private java.io.File originalLocation;
@@ -148,4 +150,48 @@
 		assertEquals("2.1", RuntimeTest.PI_RUNTIME_TESTS, collected.get(0).getPlugin());
 	}
 
+	public void testIsFragment() {
+		String bundleId = PI_FILESYSTEM;
+		Bundle bundle = Platform.getBundle(bundleId);
+		assertNotNull(bundleId + ": bundle not found", bundle);
+		assertFalse(Platform.isFragment(bundle));
+
+		bundleId = PI_FILESYSTEM + "." + System.getProperty("osgi.os");
+		if (!Platform.OS_MACOSX.equals(System.getProperty("osgi.os"))) {
+			bundleId += "." + System.getProperty("osgi.arch");
+		}
+		bundle = Platform.getBundle(bundleId);
+		if (bundle != null) {
+			// bundle not available on Gerrit build
+			assertTrue(Platform.isFragment(bundle));
+		}
+	}
+
+	public void testGetBundle() throws BundleException {
+		Bundle bundle = Platform.getBundle(PI_JDT_ANNOTATION);
+		assertNotNull("org.eclipse.jdt.annotation bundle not available", bundle);
+		assertEquals(2, bundle.getVersion().getMajor()); // new 2.x version
+
+		bundle.uninstall();
+		bundle = Platform.getBundle(PI_JDT_ANNOTATION);
+		assertNull(PI_JDT_ANNOTATION + " bundle => expect null result", bundle);
+	}
+
+	public void testGetBundles() {
+		Bundle[] bundles = Platform.getBundles(PI_JDT_ANNOTATION, null);
+		assertNotNull(PI_JDT_ANNOTATION + " bundle not available", bundles);
+		// there may be only one version available, and then it will be the new version
+		assertEquals(1, bundles.length);
+		assertEquals(2, bundles[0].getVersion().getMajor()); // new 2.x version
+
+		bundles = Platform.getBundles(PI_JDT_ANNOTATION, "2.0.0");
+		assertNotNull(PI_JDT_ANNOTATION + " bundle not available", bundles);
+		assertEquals(1, bundles.length);
+		assertEquals(2, bundles[0].getVersion().getMajor()); // new 2.x version
+
+		// version out of range
+		bundles = Platform.getBundles(PI_JDT_ANNOTATION, "[1.1.0,2.0.0)");
+		assertNull("No bundle should match => expect null result", bundles);
+	}
+
 }