Merge "Added an option to fail the empty invocation."
diff --git a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
index 0c8bc66..550ac65 100644
--- a/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
+++ b/src/com/android/tradefed/testtype/suite/BaseTestSuite.java
@@ -180,6 +180,13 @@
     )
     private Set<ModuleParameters> mExcludedModuleParameters = new HashSet<>();
 
+    @Option(
+            name = "fail-on-everything-filtered",
+            description =
+                    "Whether or not to fail the invocation in case test filter returns"
+                            + " an empty result.")
+    private boolean mFailOnEverythingFiltered = false;
+
     private SuiteModuleLoader mModuleRepo;
     private Map<String, List<SuiteTestFilter>> mIncludeFiltersParsed = new HashMap<>();
     private Map<String, List<SuiteTestFilter>> mExcludeFiltersParsed = new HashMap<>();
@@ -285,7 +292,19 @@
             // Finally add the full test cases directory in case there is no special sub-dir.
             testsDirectories.add(testsDir);
             // Actual loading of the configurations.
-            return loadingStrategy(abis, testsDirectories, mSuitePrefix, mSuiteTag);
+            LinkedHashMap<String, IConfiguration> loadedTests =
+                    loadingStrategy(abis, testsDirectories, mSuitePrefix, mSuiteTag);
+
+            if (mFailOnEverythingFiltered
+                    && loadedTests.isEmpty()
+                    && !mIncludeFiltersParsed.isEmpty()) {
+                throw new IllegalStateException(
+                        String.format(
+                                "Include filter '%s' was specified"
+                                        + " but resulted in an empty test set.",
+                                includeFilter));
+            }
+            return loadedTests;
         } catch (DeviceNotAvailableException | FileNotFoundException e) {
             throw new RuntimeException(e);
         }
diff --git a/tests/src/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java b/tests/src/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java
index a32553a..0e56621 100644
--- a/tests/src/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java
+++ b/tests/src/com/android/tradefed/testtype/suite/BaseTestSuiteTest.java
@@ -309,6 +309,43 @@
         assertTrue(configMap.containsKey("armeabi-v7a suite/stub1"));
     }
 
+    /**
+     * Test for {@link BaseTestSuite#loadTests()} implementation, for configuration with include
+     * filter set to a non-existent test.
+     */
+    @Test
+    public void testLoadTests_emptyFilter() throws Exception {
+        OptionSetter setter = new OptionSetter(mRunner);
+        setter.setOptionValue("include-filter", "Doesntexist");
+        setter.setOptionValue("suite-config-prefix", "suite");
+        setter.setOptionValue("run-suite-tag", "example-suite");
+        LinkedHashMap<String, IConfiguration> configMap = mRunner.loadTests();
+        assertEquals(0, configMap.size());
+    }
+
+    /**
+     * Test for {@link BaseTestSuite#loadTests()} implementation, for configuration with include
+     * filter set to a non-existent test and enabled failure on empty test set.
+     */
+    @Test
+    public void testLoadTests_emptyFilterWithFailOnEmpty() throws Exception {
+        OptionSetter setter = new OptionSetter(mRunner);
+        setter.setOptionValue("include-filter", "Doesntexist");
+        setter.setOptionValue("fail-on-everything-filtered", "true");
+        setter.setOptionValue("suite-config-prefix", "suite");
+        setter.setOptionValue("run-suite-tag", "example-suite");
+        try {
+            mRunner.loadTests();
+            fail("Should have thrown exception");
+        } catch (IllegalStateException ex) {
+            assertEquals(
+                    "Include filter '{arm64-v8a Doesntexist=[Doesntexist], armeabi-v7a "
+                            + "Doesntexist=[Doesntexist]}' was specified but resulted in "
+                            + "an empty test set.",
+                    ex.getMessage());
+        }
+    }
+
     /** Test that when splitting, the instance of the implementation is used. */
     @Test
     public void testSplit() throws Exception {