Merge "[Ravenwood] Add "--strip-mockito" to Ravenizer" into main
diff --git a/ravenwood/tests/coretest/Android.bp b/ravenwood/tests/coretest/Android.bp
index d94475c..85f1baf 100644
--- a/ravenwood/tests/coretest/Android.bp
+++ b/ravenwood/tests/coretest/Android.bp
@@ -17,9 +17,15 @@
         "junit-params",
         "platform-parametric-runner-lib",
         "truth",
+
+        // This library should be removed by Ravenizer
+        "mockito-target-minus-junit4",
     ],
     srcs: [
         "test/**/*.java",
     ],
+    ravenizer: {
+        strip_mockito: true,
+    },
     auto_gen_config: true,
 }
diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java
new file mode 100644
index 0000000..dd6d259
--- /dev/null
+++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024 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.ravenwoodtest.coretest;
+
+import static org.junit.Assert.assertThrows;
+
+import org.junit.Test;
+
+public class RavenwoodMockitoTest {
+
+    @Test
+    public void checkMockitoClasses() {
+        // DexMaker should not exist
+        assertThrows(
+                ClassNotFoundException.class,
+                () -> Class.forName("com.android.dx.DexMaker"));
+        // Mockito 2 should not exist
+        assertThrows(
+                ClassNotFoundException.class,
+                () -> Class.forName("org.mockito.Matchers"));
+    }
+}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
index f7f9a85..49f0b59 100644
--- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
@@ -85,18 +85,17 @@
 /**
  * Main class.
  */
-class Ravenizer(val options: RavenizerOptions) {
-    fun run() {
+class Ravenizer {
+    fun run(options: RavenizerOptions) {
         val stats = RavenizerStats()
 
-        val fatalValidation = options.fatalValidation.get
-
         stats.totalTime = log.nTime {
             process(
                 options.inJar.get,
                 options.outJar.get,
                 options.enableValidation.get,
-                fatalValidation,
+                options.fatalValidation.get,
+                options.stripMockito.get,
                 stats,
             )
         }
@@ -108,6 +107,7 @@
         outJar: String,
         enableValidation: Boolean,
         fatalValidation: Boolean,
+        stripMockito: Boolean,
         stats: RavenizerStats,
     ) {
         var allClasses = ClassNodes.loadClassStructures(inJar) {
@@ -126,6 +126,9 @@
                 }
             }
         }
+        if (includeUnsupportedMockito(allClasses)) {
+            log.w("Unsupported Mockito detected in $inJar}!")
+        }
 
         stats.totalProcessTime = log.vTime("$executableName processing $inJar") {
             ZipFile(inJar).use { inZip ->
@@ -145,6 +148,11 @@
                             )
                         }
 
+                        if (stripMockito && entry.name.isMockitoFile()) {
+                            // Skip this entry
+                            continue
+                        }
+
                         val className = zipEntryNameToClassName(entry.name)
 
                         if (className != null) {
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt
index ff41818..aee4530 100644
--- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerMain.kt
@@ -36,6 +36,6 @@
         log.v("Options: $options")
 
         // Run.
-        Ravenizer(options).run()
+        Ravenizer().run(options)
     }
 }
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt
index 10fe0a3..32dcbe5 100644
--- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/RavenizerOptions.kt
@@ -47,6 +47,9 @@
 
     /** Whether the validation failure is fatal or not. */
     var fatalValidation: SetOnce<Boolean> = SetOnce(false),
+
+    /** Whether to remove mockito and dexmaker classes. */
+    var stripMockito: SetOnce<Boolean> = SetOnce(false),
 ) {
     companion object {
 
@@ -85,6 +88,9 @@
                         "--fatal-validation" -> ret.fatalValidation.set(true)
                         "--no-fatal-validation" -> ret.fatalValidation.set(false)
 
+                        "--strip-mockito" -> ret.stripMockito.set(true)
+                        "--no-strip-mockito" -> ret.stripMockito.set(false)
+
                         else -> throw ArgumentsException("Unknown option: $arg")
                     }
                 } catch (e: SetOnce.SetMoreThanOnceException) {
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt
index 1aa70c08..37a7975 100644
--- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Utils.kt
@@ -100,3 +100,19 @@
         // TODO -- anything else?
     )
 }
+
+/**
+ * Files that should be removed when "--strip-mockito" is set.
+ */
+fun String.isMockitoFile(): Boolean {
+    return this.startsWithAny(
+        "org/mockito/", // Mockito
+        "com/android/dx/", // DexMaker
+        "mockito-extensions/", // DexMaker overrides
+    )
+}
+
+fun includeUnsupportedMockito(classes: ClassNodes): Boolean {
+    return classes.findClass("com/android/dx/DexMaker") != null
+            || classes.findClass("org/mockito/Matchers") != null
+}