Bug 521246: [JUnit 5] Add provision to use @Tag filtering

Change-Id: I570e5b8e9a4479c3f0ec37869dc7bb3f7fbb728c
diff --git a/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/ITestLoader.java b/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/ITestLoader.java
index c84f5ef..0c59823 100644
--- a/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/ITestLoader.java
+++ b/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/ITestLoader.java
@@ -19,10 +19,11 @@
 	 * @param testName individual method to be run
 	 * @param failureNames may want to run these first, since they failed
 	 * @param packages packages containing tests to run
+	 * @param includeExcludeTags tags to be included and excluded in the test run
 	 * @param uniqueId unique ID of the test to run
 	 * @param listener to be notified if tests could not be loaded
 	 * @return the loaded test references
 	 */
-	public abstract ITestReference[] loadTests(Class[] testClasses, String testName, String[] failureNames, String[] packages, String uniqueId, RemoteTestRunner listener);
+	public abstract ITestReference[] loadTests(Class[] testClasses, String testName, String[] failureNames, String[] packages, String[][] includeExcludeTags, String uniqueId, RemoteTestRunner listener);
 }
 
diff --git a/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/RemoteTestRunner.java b/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/RemoteTestRunner.java
index 26b3767..05085fa 100644
--- a/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/RemoteTestRunner.java
+++ b/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/RemoteTestRunner.java
@@ -69,6 +69,10 @@
 	 * The unique ID of test to run or "" if not available
 	 */
 	private String fUniqueId;
+	/**
+	 * Tags to be included and excluded in the test run
+	 */
+	private String[][] fIncludeExcludeTags= new String[2][];
 
 	/**
 	 * The current test result
@@ -305,6 +309,32 @@
 			} else if(args[i].toLowerCase().equals("-uniqueid")) { //$NON-NLS-1$
 				fUniqueId= args[i+1];
 				i++;
+			} else if (args[i].toLowerCase().equals("--include-tag")) { //$NON-NLS-1$
+				String[] includeTags= fIncludeExcludeTags[0];
+				if (includeTags == null) {
+					includeTags= new String[1];
+					includeTags[0]= args[i + 1];
+				} else {
+					String[] tags= new String[includeTags.length + 1];
+					System.arraycopy(includeTags, 0, tags, 0, includeTags.length);
+					tags[includeTags.length]= args[i + 1];
+					includeTags= tags;
+				}
+				fIncludeExcludeTags[0]= includeTags;
+				i++;
+			} else if (args[i].toLowerCase().equals("--exclude-tag")) { //$NON-NLS-1$
+				String[] excludeTags= fIncludeExcludeTags[1];
+				if (excludeTags == null) {
+					excludeTags= new String[1];
+					excludeTags[0]= args[i + 1];
+				} else {
+					String[] tags= new String[excludeTags.length + 1];
+					System.arraycopy(excludeTags, 0, tags, 0, excludeTags.length);
+					tags[excludeTags.length]= args[i + 1];
+					excludeTags= tags;
+				}
+				fIncludeExcludeTags[1]= excludeTags;
+				i++;
 			}
 		}
 
@@ -490,7 +520,7 @@
 	 * @param execution executor
 	 */
 	public void runTests(String[] testClassNames, String testName, TestExecution execution) {
-		ITestReference[] suites= fLoader.loadTests(loadClasses(testClassNames), testName, fFailureNames, fPackageNames, fUniqueId, this);
+		ITestReference[] suites= fLoader.loadTests(loadClasses(testClassNames), testName, fFailureNames, fPackageNames, fIncludeExcludeTags, fUniqueId, this);
 
 		// count all testMethods and inform ITestRunListeners
 		int count= countTests(suites);
@@ -538,7 +568,7 @@
 	 */
 	public void rerunTest(RerunRequest r) {
 		final Class[] classes= loadClasses(new String[] { r.fRerunClassName });
-		ITestReference rerunTest1= fLoader.loadTests(classes, r.fRerunTestName, null, null, fUniqueId, this)[0];
+		ITestReference rerunTest1= fLoader.loadTests(classes, r.fRerunTestName, null, null, fIncludeExcludeTags, fUniqueId, this)[0];
 		RerunExecutionListener service= rerunExecutionListener();
 
 		TestExecution execution= new TestExecution(service, getClassifier());
diff --git a/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/junit3/JUnit3TestLoader.java b/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/junit3/JUnit3TestLoader.java
index 965db39..dcb975a 100644
--- a/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/junit3/JUnit3TestLoader.java
+++ b/org.eclipse.jdt.junit.runtime/src/org/eclipse/jdt/internal/junit/runner/junit3/JUnit3TestLoader.java
@@ -36,7 +36,7 @@
 
 	// WANT: give test loaders a schema
 
-	public ITestReference[] loadTests(Class[] testClasses, String testName, String[] failureNames, String[] packages, String uniqueId, RemoteTestRunner listener) {
+	public ITestReference[] loadTests(Class[] testClasses, String testName, String[] failureNames, String[] packages, String[][] includeExcludeTags, String uniqueId, RemoteTestRunner listener) {
 		// instantiate all tests
 		ITestReference[] suites= new ITestReference[testClasses.length];
 		ITestPrioritizer prioritizer;
diff --git a/org.eclipse.jdt.junit4.runtime/src/org/eclipse/jdt/internal/junit4/runner/JUnit4TestLoader.java b/org.eclipse.jdt.junit4.runtime/src/org/eclipse/jdt/internal/junit4/runner/JUnit4TestLoader.java
index e776983..811f7ad 100644
--- a/org.eclipse.jdt.junit4.runtime/src/org/eclipse/jdt/internal/junit4/runner/JUnit4TestLoader.java
+++ b/org.eclipse.jdt.junit4.runtime/src/org/eclipse/jdt/internal/junit4/runner/JUnit4TestLoader.java
@@ -36,6 +36,7 @@
 			String testName,
 			String[] failureNames,
 			String[] packages,
+			String[][] includeExcludeTags,
 			String uniqueId,
 			RemoteTestRunner listener) {
 
diff --git a/org.eclipse.jdt.junit5.runtime/src/org/eclipse/jdt/internal/junit5/runner/JUnit5TestLoader.java b/org.eclipse.jdt.junit5.runtime/src/org/eclipse/jdt/internal/junit5/runner/JUnit5TestLoader.java
index a8d8ecd..1ac0e05 100644
--- a/org.eclipse.jdt.junit5.runtime/src/org/eclipse/jdt/internal/junit5/runner/JUnit5TestLoader.java
+++ b/org.eclipse.jdt.junit5.runtime/src/org/eclipse/jdt/internal/junit5/runner/JUnit5TestLoader.java
@@ -10,10 +10,15 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.junit5.runner;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.platform.engine.Filter;
 import org.junit.platform.engine.discovery.ClassNameFilter;
 import org.junit.platform.engine.discovery.DiscoverySelectors;
 import org.junit.platform.launcher.Launcher;
 import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TagFilter;
 import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
 import org.junit.platform.launcher.core.LauncherFactory;
 
@@ -26,46 +31,46 @@
 	private Launcher fLauncher= LauncherFactory.create();
 
 	@Override
-	public ITestReference[] loadTests(Class[] testClasses, String testName, String[] failureNames, String[] packages, String uniqueId, RemoteTestRunner listener) {
+	public ITestReference[] loadTests(Class[] testClasses, String testName, String[] failureNames, String[] packages, String[][] includeExcludeTags, String uniqueId, RemoteTestRunner listener) {
 		ITestReference[] refs= new ITestReference[0];
 		if (uniqueId != null && !uniqueId.trim().isEmpty()) {
 			refs= new ITestReference[1];
-			refs[0]= createUniqueIdTest(uniqueId);
+			refs[0]= createUniqueIdTest(uniqueId, includeExcludeTags);
 		} else if (packages != null) {
 			refs= new ITestReference[packages.length];
 			for (int i= 0; i < packages.length; i++) {
-				refs[i]= createTest(packages[i]);
+				refs[i]= createTest(packages[i], includeExcludeTags);
 			}
 		} else {
 			refs= new ITestReference[testClasses.length];
 			for (int i= 0; i < testClasses.length; i++) {
-				refs[i]= createTest(testClasses[i], testName);
+				refs[i]= createTest(testClasses[i], testName, includeExcludeTags);
 			}
 		}
 		return refs;
 	}
 
-	private ITestReference createTest(Class<?> clazz, String testName) {
+	private ITestReference createTest(Class<?> clazz, String testName, String[][] includeExcludeTags) {
 		if (clazz == null) {
 			return null;
 		}
 		if (testName != null) {
-			return createFilteredTest(clazz, testName);
+			return createFilteredTest(clazz, testName, includeExcludeTags);
 		}
-		return createUnfilteredTest(clazz);
+		return createUnfilteredTest(clazz, includeExcludeTags);
 	}
 
-	private ITestReference createFilteredTest(Class<?> clazz, String testName) {
-		LauncherDiscoveryRequest request= LauncherDiscoveryRequestBuilder.request().selectors(DiscoverySelectors.selectMethod(clazz.getName() + "#" + testName)).build(); //$NON-NLS-1$
+	private ITestReference createFilteredTest(Class<?> clazz, String testName, String[][] includeExcludeTags) {
+		LauncherDiscoveryRequest request= LauncherDiscoveryRequestBuilder.request().selectors(DiscoverySelectors.selectMethod(clazz.getName() + "#" + testName)).filters(getTagFilters(includeExcludeTags)).build(); //$NON-NLS-1$
 		return new JUnit5TestReference(request, fLauncher);
 	}
 
-	private ITestReference createUnfilteredTest(Class<?> clazz) {
-		LauncherDiscoveryRequest request= LauncherDiscoveryRequestBuilder.request().selectors(DiscoverySelectors.selectClass(clazz)).build();
+	private ITestReference createUnfilteredTest(Class<?> clazz, String[][] includeExcludeTags) {
+		LauncherDiscoveryRequest request= LauncherDiscoveryRequestBuilder.request().selectors(DiscoverySelectors.selectClass(clazz)).filters(getTagFilters(includeExcludeTags)).build();
 		return new JUnit5TestReference(request, fLauncher);
 	}
 
-	private ITestReference createTest(String pkg) {
+	private ITestReference createTest(String pkg, String[][] includeExcludeTags) {
 		if (pkg == null) {
 			return null;
 		}
@@ -79,13 +84,27 @@
 		LauncherDiscoveryRequest request= LauncherDiscoveryRequestBuilder.request()
 				.selectors(DiscoverySelectors.selectPackage(pkg))
 				.filters(ClassNameFilter.includeClassNamePatterns(pattern))
+				.filters(getTagFilters(includeExcludeTags))
 				.build();
 
 		return new JUnit5TestReference(request, fLauncher);
 	}
 
-	private ITestReference createUniqueIdTest(String uniqueId) {
-		LauncherDiscoveryRequest request= LauncherDiscoveryRequestBuilder.request().selectors(DiscoverySelectors.selectUniqueId(uniqueId)).build();
+	private ITestReference createUniqueIdTest(String uniqueId, String[][] includeExcludeTags) {
+		LauncherDiscoveryRequest request= LauncherDiscoveryRequestBuilder.request().selectors(DiscoverySelectors.selectUniqueId(uniqueId)).filters(getTagFilters(includeExcludeTags)).build();
 		return new JUnit5TestReference(request, fLauncher);
 	}
+
+	private Filter<?>[] getTagFilters(String[][] includeExcludeTags) {
+		String[] includeTags= includeExcludeTags[0];
+		String[] excludeTags= includeExcludeTags[1];
+		List<Filter<?>> tagFilters= new ArrayList<>();
+		if (includeTags != null) {
+			tagFilters.add(TagFilter.includeTags(includeTags));
+		}
+		if (excludeTags != null) {
+			tagFilters.add(TagFilter.excludeTags(excludeTags));
+		}
+		return tagFilters.toArray(new Filter[tagFilters.size()]);
+	}
 }