Add Script to collect ravenwood stats *.csv files

Also re-organize the f/b/ravenwood directory.

Test: ./ravenwood/scripts/run-ravenwood-tests.sh
Bug: 292141694
Change-Id: Icf6677c8ab8ead76148ae5278cb54d38fa0b34f2
diff --git a/ravenwood/scripts/bulk_enable.py b/ravenwood/scripts/bulk_enable.py
new file mode 100644
index 0000000..aafaaff
--- /dev/null
+++ b/ravenwood/scripts/bulk_enable.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+"""
+Tool to bulk-enable tests that are now passing on Ravenwood.
+
+Currently only offers to include classes which are fully passing; ignores
+classes that have partial success.
+
+Typical usage:
+$ RAVENWOOD_RUN_DISABLED_TESTS=1 atest MyTestsRavenwood
+$ cd /path/to/tests/root
+$ python bulk_enable.py /path/to/atest/output/host_log.txt
+"""
+
+import collections
+import os
+import re
+import subprocess
+import sys
+
+re_result = re.compile("I/ModuleListener.+?null-device-0 (.+?)#(.+?) ([A-Z_]+)(.*)$")
+
+DRY_RUN = "-n" in sys.argv
+
+ANNOTATION = "@android.platform.test.annotations.EnabledOnRavenwood"
+SED_ARG = "s/^((public )?class )/%s\\n\\1/g" % (ANNOTATION)
+
+STATE_PASSED = "PASSED"
+STATE_FAILURE = "FAILURE"
+STATE_ASSUMPTION_FAILURE = "ASSUMPTION_FAILURE"
+STATE_CANDIDATE = "CANDIDATE"
+
+stats_total = collections.defaultdict(int)
+stats_class = collections.defaultdict(lambda: collections.defaultdict(int))
+stats_method = collections.defaultdict()
+
+with open(sys.argv[-1]) as f:
+    for line in f.readlines():
+        result = re_result.search(line)
+        if result:
+            clazz, method, state, msg = result.groups()
+            if state == STATE_FAILURE and "actually passed under Ravenwood" in msg:
+                state = STATE_CANDIDATE
+            stats_total[state] += 1
+            stats_class[clazz][state] += 1
+            stats_method[(clazz, method)] = state
+
+# Find classes who are fully "candidates" (would be entirely green if enabled)
+num_enabled = 0
+for clazz in stats_class.keys():
+    stats = stats_class[clazz]
+    if STATE_CANDIDATE in stats and len(stats) == 1:
+        num_enabled += stats[STATE_CANDIDATE]
+        print("Enabling fully-passing class", clazz)
+        clazz_match = re.compile("%s\.(kt|java)" % (clazz.split(".")[-1]))
+        for root, dirs, files in os.walk("."):
+            for f in files:
+                if clazz_match.match(f) and not DRY_RUN:
+                    path = os.path.join(root, f)
+                    subprocess.run(["sed", "-i", "-E", SED_ARG, path])
+
+print("Overall stats", stats_total)
+print("Candidates actually enabled", num_enabled)
diff --git a/ravenwood/scripts/fix_test_runner.py b/ravenwood/scripts/fix_test_runner.py
new file mode 100755
index 0000000..99b7a1f
--- /dev/null
+++ b/ravenwood/scripts/fix_test_runner.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+"""
+Tool switch the deprecated jetpack test runner to the correct one.
+
+Typical usage:
+$ RAVENWOOD_OPTIONAL_VALIDATION=1 atest MyTestsRavenwood # Prepend RAVENWOOD_RUN_DISABLED_TESTS=1 as needed
+$ cd /path/to/tests/root
+$ python bulk_enable.py /path/to/atest/output/host_log.txt
+"""
+
+import collections
+import os
+import re
+import subprocess
+import sys
+
+re_result = re.compile("I/ModuleListener.+?null-device-0 (.+?)#(.+?) ([A-Z_]+)(.*)$")
+
+OLD_RUNNER = "androidx.test.runner.AndroidJUnit4"
+NEW_RUNNER = "androidx.test.ext.junit.runners.AndroidJUnit4"
+SED_ARG = r"s/%s/%s/g" % (OLD_RUNNER, NEW_RUNNER)
+
+target = collections.defaultdict()
+
+with open(sys.argv[1]) as f:
+    for line in f.readlines():
+        result = re_result.search(line)
+        if result:
+            clazz, method, state, msg = result.groups()
+            if NEW_RUNNER in msg:
+                target[clazz] = 1
+
+if len(target) == 0:
+    print("No tests need updating.")
+    sys.exit(0)
+
+num_fixed = 0
+for clazz in target.keys():
+    print("Fixing test runner", clazz)
+    clazz_match = re.compile("%s\.(kt|java)" % (clazz.split(".")[-1]))
+    found = False
+    for root, dirs, files in os.walk("."):
+        for f in files:
+            if clazz_match.match(f):
+                found = True
+                num_fixed += 1
+                path = os.path.join(root, f)
+                subprocess.run(["sed", "-i", "-E", SED_ARG, path])
+    if not found:
+        print(f"  Warining: tests {clazz} not found")
+
+
+print("Tests fixed", num_fixed)
diff --git a/ravenwood/scripts/list-ravenwood-tests.sh b/ravenwood/scripts/list-ravenwood-tests.sh
new file mode 100755
index 0000000..fb9b823
--- /dev/null
+++ b/ravenwood/scripts/list-ravenwood-tests.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# 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.
+
+# List all the ravenwood test modules.
+
+jq -r 'to_entries[] | select( .value.compatibility_suites | index("ravenwood-tests") ) | .key' "$OUT/module-info.json"
diff --git a/ravenwood/scripts/ravenwood-stats-checker.sh b/ravenwood/scripts/ravenwood-stats-checker.sh
new file mode 100755
index 0000000..93f4a3f
--- /dev/null
+++ b/ravenwood/scripts/ravenwood-stats-checker.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# 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.
+
+# Just print the available *.csv filenames.
+echo '#Stats files:'
+ls *.csv
\ No newline at end of file
diff --git a/ravenwood/scripts/ravenwood-stats-collector.sh b/ravenwood/scripts/ravenwood-stats-collector.sh
new file mode 100755
index 0000000..4dcaa2b
--- /dev/null
+++ b/ravenwood/scripts/ravenwood-stats-collector.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# 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.
+
+# Script to collect the ravenwood "stats" CVS files and create a single file.
+
+set -e
+
+# Output file
+out=/tmp/ravenwood-stats-all.csv
+
+# Where the input files are.
+path=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/ravenwood-stats-checker/x86_64/
+
+m() {
+    ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode "$@"
+}
+
+# Building this will generate the files we need.
+m ravenwood-stats-checker
+
+# Start...
+
+cd $path
+
+dump() {
+    local jar=$1
+    local file=$2
+
+    sed -e '1d' -e "s/^/$jar,/"  $file
+}
+
+collect() {
+    echo 'Jar,PackageName,ClassName,SupportedMethods,TotalMethods'
+    dump "framework-minus-apex"  hoststubgen_framework-minus-apex_stats.csv
+    dump "service.core"  hoststubgen_services.core_stats.csv
+}
+
+collect >$out
+
+echo "Full dump CVS created at $out"
diff --git a/ravenwood/scripts/run-ravenwood-tests.sh b/ravenwood/scripts/run-ravenwood-tests.sh
new file mode 100755
index 0000000..926c08f
--- /dev/null
+++ b/ravenwood/scripts/run-ravenwood-tests.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+# 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.
+
+# Run all the ravenwood tests + hoststubgen unit tests.
+
+all_tests="hoststubgentest tiny-framework-dump-test hoststubgen-invoke-test ravenwood-stats-checker"
+
+# "echo" is to remove the newlines
+all_tests="$all_tests $(echo $(${0%/*}/list-ravenwood-tests.sh) )"
+
+run() {
+    echo "Running: $*"
+    "${@}"
+}
+
+run ${ATEST:-atest} $all_tests