Refactor to share test type checking logic

Ensures the same logic is used.

Bug: 292249899
Test: TH
Change-Id: Ic5e8eb819a146dcf75ce7abfe42e5a1f4b76e01d
diff --git a/javatests/com/android/tradefed/UnitTests.java b/javatests/com/android/tradefed/UnitTests.java
index 61136f1..6911a44 100644
--- a/javatests/com/android/tradefed/UnitTests.java
+++ b/javatests/com/android/tradefed/UnitTests.java
@@ -419,6 +419,7 @@
 import com.android.tradefed.util.LocalRunInstructionBuilderTest;
 import com.android.tradefed.util.LogcatEventParserTest;
 import com.android.tradefed.util.MetricUtilityTest;
+import com.android.tradefed.util.ModuleTestTypeUtilTest;
 import com.android.tradefed.util.MultiMapTest;
 import com.android.tradefed.util.NativeCodeCoverageFlusherTest;
 import com.android.tradefed.util.PairTest;
@@ -1007,6 +1008,7 @@
     ListInstrumentationParserTest.class,
     LogcatEventParserTest.class,
     MetricUtilityTest.class,
+    ModuleTestTypeUtilTest.class,
     MultiMapTest.class,
     MergedZipEntryCollectionTest.class,
     NativeCodeCoverageFlusherTest.class,
diff --git a/javatests/com/android/tradefed/presubmit/GeneralTestsConfigValidation.java b/javatests/com/android/tradefed/presubmit/GeneralTestsConfigValidation.java
index 200e671..82847b9 100644
--- a/javatests/com/android/tradefed/presubmit/GeneralTestsConfigValidation.java
+++ b/javatests/com/android/tradefed/presubmit/GeneralTestsConfigValidation.java
@@ -37,10 +37,10 @@
 import com.android.tradefed.testtype.suite.ValidateSuiteConfigHelper;
 import com.android.tradefed.testtype.suite.params.ModuleParameters;
 import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.ModuleTestTypeUtil;
 
 import com.google.common.base.Joiner;
 
-import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,8 +71,6 @@
             description = "The disallowed test type for configs in general-tests.zip")
     private List<String> mDisallowedTestTypes = new ArrayList<>();
 
-    private static final String TEST_TYPE_KEY = "test-type";
-
     private IBuildInfo mBuild;
 
     /**
@@ -501,26 +499,27 @@
         }
     }
 
+    /**
+     * Check the {@link config} to ensure it's not declared as one of the {#link
+     * disallowedTestTypes}.
+     *
+     * @param config The config to check.
+     * @param ConfigurationException The disallowed test types to check against.
+     * @throws ConfigurationException if the config is of disallowed test types.
+     */
     public static void checkDisallowedTestType(
             IConfiguration config, List<String> disallowedTestTypes) throws ConfigurationException {
         if (disallowedTestTypes == null || disallowedTestTypes.isEmpty()) {
             return;
         }
 
-        ConfigurationDescriptor cd = config.getConfigurationDescription();
-        Assert.assertNotNull(config + ": configuration descriptor is null", cd);
-        List<String> testTypes = cd.getMetaData(TEST_TYPE_KEY);
-        if (testTypes == null || testTypes.isEmpty()) {
-            return;
-        }
-
-        for (String testType : testTypes) {
-            if (disallowedTestTypes.contains(testType)) {
-                throw new ConfigurationException(
-                        String.format(
-                                "Config %s of test type '%s' is not allowed.",
-                                config.getName(), testType));
-            }
+        List<String> matched =
+                ModuleTestTypeUtil.getMatchedConfigTestTypes(config, disallowedTestTypes);
+        if (!matched.isEmpty()) {
+            throw new ConfigurationException(
+                    String.format(
+                            "Config %s of test type '%s' is not allowed.",
+                            config.getName(), Joiner.on(", ").join(matched)));
         }
     }
 }
diff --git a/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java b/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java
index 7c8a8b4..04abe49 100644
--- a/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java
+++ b/javatests/com/android/tradefed/presubmit/TestMappingsValidation.java
@@ -21,7 +21,6 @@
 
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.build.IDeviceBuildInfo;
-import com.android.tradefed.config.ConfigurationDescriptor;
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.ConfigurationFactory;
 import com.android.tradefed.config.ConfigurationUtil;
@@ -36,6 +35,7 @@
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.suite.ITestSuite;
 import com.android.tradefed.util.FileUtil;
+import com.android.tradefed.util.ModuleTestTypeUtil;
 import com.android.tradefed.util.ZipUtil2;
 import com.android.tradefed.util.testmapping.TestInfo;
 import com.android.tradefed.util.testmapping.TestMapping;
@@ -50,7 +50,6 @@
 
 import org.junit.After;
 import org.junit.Assume;
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -105,8 +104,6 @@
             "https://source.android.com/compatibility/tests/development/test-mapping#packaging_build_script_rules";
     private static final String MODULE_NAME = "module_name";
     private static final String MAINLINE = "mainline";
-    private static final String TEST_TYPE_KEY = "test-type";
-    private static final String TEST_TYPE_VALUE_PERFORMANCE = "performance";
 
     // Pair that shouldn't be overlapping. Test can only exists in one or the other.
     private static final Set<String> INCOMPATIBLE_PAIRS =
@@ -450,7 +447,9 @@
                 if (!modules.contains(module)) {
                     continue;
                 }
-                if (isPerformanceModule(configName)) {
+                IConfiguration config =
+                        mConfigFactory.createConfigurationFromArgs(new String[] {configName});
+                if (ModuleTestTypeUtil.isPerformanceModule(config)) {
                     performanceModules.add(module);
                 }
             }
@@ -468,14 +467,6 @@
         }
     }
 
-    private boolean isPerformanceModule(String fileName) throws ConfigurationException {
-        IConfiguration config = mConfigFactory.createConfigurationFromArgs(new String[] {fileName});
-        ConfigurationDescriptor cd = config.getConfigurationDescription();
-        Assert.assertNotNull(config + ": configuration descriptor is null", cd);
-        List<String> testTypes = cd.getMetaData(TEST_TYPE_KEY);
-        return (testTypes != null && testTypes.contains(TEST_TYPE_VALUE_PERFORMANCE));
-    }
-
     /**
      * Validate if the filter option of a test contains both class/method and package. options.
      *
diff --git a/javatests/com/android/tradefed/util/ModuleTestTypeUtilTest.java b/javatests/com/android/tradefed/util/ModuleTestTypeUtilTest.java
new file mode 100644
index 0000000..a34675d
--- /dev/null
+++ b/javatests/com/android/tradefed/util/ModuleTestTypeUtilTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tradefed.util;
+
+import static org.junit.Assert.assertEquals;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import static org.mockito.Mockito.when;
+
+import com.android.tradefed.config.ConfigurationDescriptor;
+import com.android.tradefed.config.IConfiguration;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.Test;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+
+/** Unit tests for {@link ModuleTestTypeUtil}. */
+@RunWith(JUnit4.class)
+public class ModuleTestTypeUtilTest {
+
+    public static final String TEST_TYPE_KEY = "test-type";
+    public static final String TEST_TYPE_VALUE_PERFORMANCE = "performance";
+
+    @Mock IConfiguration mMockPerformanceModule;
+    @Mock IConfiguration mMockUnspecifiedModule;
+    @Mock ConfigurationDescriptor mMockPerformanceConfigDescriptor;
+    @Mock ConfigurationDescriptor mMockUnspecifiedConfigDescriptor;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(mMockPerformanceModule.getConfigurationDescription())
+                .thenReturn(mMockPerformanceConfigDescriptor);
+        when(mMockUnspecifiedModule.getConfigurationDescription())
+                .thenReturn(mMockUnspecifiedConfigDescriptor);
+        when(mMockPerformanceConfigDescriptor.getMetaData(ModuleTestTypeUtil.TEST_TYPE_KEY))
+                .thenReturn(Arrays.asList(ModuleTestTypeUtil.TEST_TYPE_VALUE_PERFORMANCE));
+        when(mMockUnspecifiedConfigDescriptor.getMetaData(ModuleTestTypeUtil.TEST_TYPE_KEY))
+                .thenReturn(new ArrayList<String>());
+    }
+
+    @Test
+    public void testPositiveTestTypeMatching() {
+        List<String> matched =
+                ModuleTestTypeUtil.getMatchedConfigTestTypes(
+                        mMockPerformanceModule,
+                        Arrays.asList(ModuleTestTypeUtil.TEST_TYPE_VALUE_PERFORMANCE));
+
+        assertEquals(matched, Arrays.asList(ModuleTestTypeUtil.TEST_TYPE_VALUE_PERFORMANCE));
+    }
+
+    @Test
+    public void testNegativeTestTypeMatching() {
+        List<String> matched =
+                ModuleTestTypeUtil.getMatchedConfigTestTypes(
+                        mMockUnspecifiedModule,
+                        Arrays.asList(ModuleTestTypeUtil.TEST_TYPE_VALUE_PERFORMANCE));
+
+        assertTrue(matched.isEmpty());
+    }
+
+    @Test
+    public void testPositivePerformanceTestTypeMatching() {
+        boolean isPerformanceModule =
+                ModuleTestTypeUtil.isPerformanceModule(mMockPerformanceModule);
+
+        assertTrue(isPerformanceModule);
+    }
+
+    @Test
+    public void testNegativePerformanceTestTypeMatching() {
+        boolean isPerformanceModule =
+                ModuleTestTypeUtil.isPerformanceModule(mMockUnspecifiedModule);
+
+        assertFalse(isPerformanceModule);
+    }
+}
diff --git a/src/com/android/tradefed/util/ModuleTestTypeUtil.java b/src/com/android/tradefed/util/ModuleTestTypeUtil.java
new file mode 100644
index 0000000..6f1957c
--- /dev/null
+++ b/src/com/android/tradefed/util/ModuleTestTypeUtil.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tradefed.util;
+
+import com.android.tradefed.config.ConfigurationDescriptor;
+import com.android.tradefed.config.IConfiguration;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.junit.Assert;
+
+/** Contains common utility methods for checking module. */
+public class ModuleTestTypeUtil {
+
+    public static final String TEST_TYPE_KEY = "test-type";
+    public static final String TEST_TYPE_VALUE_PERFORMANCE = "performance";
+
+    /**
+     * Check whether the {@link config} is a performance module.
+     *
+     * @param config The config to check.
+     * @return true if the config is a performance module.
+     */
+    public static boolean isPerformanceModule(IConfiguration config) {
+        List<String> matched =
+                getMatchedConfigTestTypes(config, Arrays.asList(TEST_TYPE_VALUE_PERFORMANCE));
+        return !matched.isEmpty();
+    }
+
+    /**
+     * Get the declared test types of the {@link config} with a match in the {#link
+     * testTypesToMatch}.
+     *
+     * @param config The config to check.
+     * @param testTypesToMatch The test types to match.
+     * @return matched test types of the config or an empty list if none matches.
+     */
+    public static List<String> getMatchedConfigTestTypes(
+            IConfiguration config, List<String> testTypesToMatch) {
+        List<String> matchedTypes = new ArrayList<>();
+        ConfigurationDescriptor cd = config.getConfigurationDescription();
+        Assert.assertNotNull(config + ": configuration descriptor is null", cd);
+        List<String> testTypes = cd.getMetaData(TEST_TYPE_KEY);
+        if (testTypes != null) {
+            for (String testType : testTypes) {
+                if (testTypesToMatch.contains(testType)) {
+                    matchedTypes.add(testType);
+                }
+            }
+        }
+        return matchedTypes;
+    }
+}