Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5136a6d authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Clean up log initialization

- Make sure RuntimeInit.redirectLogStreams() is always called even
  without RavenwoodRule is used.

- In RuntimeInit.redirectLogStreams(), make sure the Log class is
  initialized properly before setting up the redirect. Otherwise,
  we'd end up trying to use the Log APIs before the Log native code
  is loaded, which would cause an UnsatisfiedLinkError.

- Use $RAVENWOOD_VERBOSE_LOGGING to force enable verbose logging.
  If it's not set, the normal $ANDROID_LOG_TAGS would be used.

Fix: 363315644
Test: $ANDROID_BUILD_TOP/frameworks/base/ravenwood/scripts/run-ravenwood-tests.sh
Flag: EXEMPT host test change only

Change-Id: Ifa4e4859c39380ebb3500cfb6570dfb78f839c0a
parent 02aebb42
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -404,6 +404,17 @@ public class RuntimeInit {
    }
    }


    public static void redirectLogStreams$ravenwood() {
    public static void redirectLogStreams$ravenwood() {
        if (sOut$ravenwood != null && sErr$ravenwood != null) {
            return; // Already initialized.
        }

        // Make sure the Log class is loaded and the JNI methods are hooked up,
        // before redirecting System.out/err.
        // Otherwise, because ClassLoadHook tries to write to System.out, this would cause
        // a circular initialization problem and would cause a UnsatisfiedLinkError
        // on the JNI methods.
        Log.isLoggable("X", Log.VERBOSE);

        if (sOut$ravenwood == null) {
        if (sOut$ravenwood == null) {
            sOut$ravenwood = System.out;
            sOut$ravenwood = System.out;
            System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
            System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
+1 −0
Original line number Original line Diff line number Diff line
@@ -127,6 +127,7 @@ java_library {
    libs: [
    libs: [
        "framework-minus-apex.ravenwood",
        "framework-minus-apex.ravenwood",
        "ravenwood-junit",
        "ravenwood-junit",
        "ravenwood-helper-libcore-runtime",
    ],
    ],
    visibility: ["//visibility:private"],
    visibility: ["//visibility:private"],
}
}
+27 −8
Original line number Original line Diff line number Diff line
@@ -27,6 +27,9 @@ import android.util.Log;


import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.platform.app.InstrumentationRegistry;


import com.android.internal.os.RuntimeInit;
import com.android.ravenwood.common.RavenwoodCommonUtils;

import org.junit.runner.Description;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.Runner;
import org.junit.runners.model.TestClass;
import org.junit.runners.model.TestClass;
@@ -35,7 +38,7 @@ import org.junit.runners.model.TestClass;
 * Provide hook points created by {@link RavenwoodAwareTestRunner}.
 * Provide hook points created by {@link RavenwoodAwareTestRunner}.
 */
 */
public class RavenwoodAwareTestRunnerHook {
public class RavenwoodAwareTestRunnerHook {
    private static final String TAG = "RavenwoodAwareTestRunnerHook";
    private static final String TAG = RavenwoodAwareTestRunner.TAG;


    private RavenwoodAwareTestRunnerHook() {
    private RavenwoodAwareTestRunnerHook() {
    }
    }
@@ -56,20 +59,36 @@ public class RavenwoodAwareTestRunnerHook {
     * Called when a runner starts, before the inner runner gets a chance to run.
     * Called when a runner starts, before the inner runner gets a chance to run.
     */
     */
    public static void onRunnerInitializing(Runner runner, TestClass testClass) {
    public static void onRunnerInitializing(Runner runner, TestClass testClass) {
        // TODO: Move the initialization code to a better place.

        initOnce();

        // This log call also ensures the framework JNI is loaded.
        // This log call also ensures the framework JNI is loaded.
        Log.i(TAG, "onRunnerInitializing: testClass=" + testClass.getJavaClass()
        Log.i(TAG, "onRunnerInitializing: testClass=" + testClass.getJavaClass()
                + " runner=" + runner);
                + " runner=" + runner);


        // TODO: Move the initialization code to a better place.
        // This is needed to make AndroidJUnit4ClassRunner happy.
        InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
    }

    private static boolean sInitialized = false;

    private static void initOnce() {
        if (sInitialized) {
            return;
        }
        sInitialized = true;

        // We haven't initialized liblog yet, so directly write to System.out here.
        RavenwoodCommonUtils.log(TAG, "initOnce()");

        // Redirect stdout/stdin to liblog.
        RuntimeInit.redirectLogStreams();


        // This will let AndroidJUnit4 use the original runner.
        // This will let AndroidJUnit4 use the original runner.
        System.setProperty("android.junit.runner",
        System.setProperty("android.junit.runner",
                "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner");
                "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner");
        System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1");
        System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1");


        // This is needed to make AndroidJUnit4ClassRunner happy.
        InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
    }
    }


    /**
    /**
@@ -87,7 +106,7 @@ public class RavenwoodAwareTestRunnerHook {
     */
     */
    public static boolean onBefore(RavenwoodAwareTestRunner runner, Description description,
    public static boolean onBefore(RavenwoodAwareTestRunner runner, Description description,
            Scope scope, Order order) {
            Scope scope, Order order) {
        Log.i(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
        Log.v(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);


        if (scope == Scope.Class && order == Order.First) {
        if (scope == Scope.Class && order == Order.First) {
            // Keep track of the current class.
            // Keep track of the current class.
@@ -113,7 +132,7 @@ public class RavenwoodAwareTestRunnerHook {
     */
     */
    public static boolean onAfter(RavenwoodAwareTestRunner runner, Description description,
    public static boolean onAfter(RavenwoodAwareTestRunner runner, Description description,
            Scope scope, Order order, Throwable th) {
            Scope scope, Order order, Throwable th) {
        Log.i(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
        Log.v(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);


        if (scope == Scope.Instance && order == Order.First) {
        if (scope == Scope.Instance && order == Order.First) {
            getStats().onTestFinished(sCurrentClassDescription, description,
            getStats().onTestFinished(sCurrentClassDescription, description,
+0 −3
Original line number Original line Diff line number Diff line
@@ -36,7 +36,6 @@ import android.view.DisplayAdjustments;


import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.platform.app.InstrumentationRegistry;


import com.android.internal.os.RuntimeInit;
import com.android.server.LocalServices;
import com.android.server.LocalServices;


import org.junit.runner.Description;
import org.junit.runner.Description;
@@ -92,8 +91,6 @@ public class RavenwoodRuleImpl {
            Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
            Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
        }
        }


        RuntimeInit.redirectLogStreams();

        android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
        android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
        android.os.Binder.init$ravenwood();
        android.os.Binder.init$ravenwood();
        setSystemProperties(rule.mSystemProperties);
        setSystemProperties(rule.mSystemProperties);
+10 −20
Original line number Original line Diff line number Diff line
@@ -23,7 +23,6 @@ import static java.lang.annotation.ElementType.TYPE;


import android.util.Log;
import android.util.Log;


import com.android.ravenwood.common.RavenwoodCommonUtils;
import com.android.ravenwood.common.SneakyThrow;
import com.android.ravenwood.common.SneakyThrow;


import org.junit.Assume;
import org.junit.Assume;
@@ -75,7 +74,7 @@ import java.lang.reflect.InvocationTargetException;
 * (no hooks, etc.)
 * (no hooks, etc.)
 */
 */
public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orderable {
public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orderable {
    private static final String TAG = "RavenwoodAwareTestRunner";
    public static final String TAG = "Ravenwood";


    @Inherited
    @Inherited
    @Target({TYPE})
    @Target({TYPE})
@@ -142,16 +141,9 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
    private Description mDescription = null;
    private Description mDescription = null;
    private Throwable mExceptionInConstructor = null;
    private Throwable mExceptionInConstructor = null;


    /** Simple logging method. */
    private Error logAndFail(String message, Throwable exception) {
    private void log(String message) {
        Log.e(TAG, message, exception);
        RavenwoodCommonUtils.log(TAG, "[" + getTestClass().getJavaClass() + "  @" + this + "] "
        throw new AssertionError(message, exception);
                + message);
    }

    private Error logAndFail(String message, Throwable innerException) {
        log(message);
        log("    Exception=" + innerException);
        throw new AssertionError(message, innerException);
    }
    }


    public TestClass getTestClass() {
    public TestClass getTestClass() {
@@ -165,6 +157,8 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        try {
        try {
            mTestClass = new TestClass(testClass);
            mTestClass = new TestClass(testClass);


            onRunnerInitializing();

            /*
            /*
             * If the class has @DisabledOnRavenwood, then we'll delegate to
             * If the class has @DisabledOnRavenwood, then we'll delegate to
             * ClassSkippingTestRunner, which simply skips it.
             * ClassSkippingTestRunner, which simply skips it.
@@ -186,10 +180,8 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
                realRunnerClass = BlockJUnit4ClassRunner.class;
                realRunnerClass = BlockJUnit4ClassRunner.class;
            }
            }


            onRunnerInitializing();

            try {
            try {
                log("Initializing the inner runner: " + realRunnerClass);
                Log.i(TAG, "Initializing the inner runner: " + realRunnerClass);


                mRealRunner = instantiateRealRunner(realRunnerClass, testClass);
                mRealRunner = instantiateRealRunner(realRunnerClass, testClass);
                mDescription = mRealRunner.getDescription();
                mDescription = mRealRunner.getDescription();
@@ -201,8 +193,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        } catch (Throwable th) {
        } catch (Throwable th) {
            // If we throw in the constructor, Tradefed may not report it and just ignore the class,
            // If we throw in the constructor, Tradefed may not report it and just ignore the class,
            // so record it and throw it when the test actually started.
            // so record it and throw it when the test actually started.
            log("Fatal: Exception detected in constructor: " + th.getMessage() + "\n"
            Log.e(TAG, "Fatal: Exception detected in constructor", th);
                    + Log.getStackTraceString(th));
            mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
            mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
                    th);
                    th);
            mDescription = Description.createTestDescription(testClass, "Constructor");
            mDescription = Description.createTestDescription(testClass, "Constructor");
@@ -236,8 +227,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        if (!isOnRavenwood()) {
        if (!isOnRavenwood()) {
            return;
            return;
        }
        }

        // DO NOT USE android.util.Log before calling onRunnerInitializing().
        log("onRunnerInitializing");


        RavenwoodAwareTestRunnerHook.onRunnerInitializing(this, mTestClass);
        RavenwoodAwareTestRunnerHook.onRunnerInitializing(this, mTestClass);


@@ -250,7 +240,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
        if (!isOnRavenwood()) {
        if (!isOnRavenwood()) {
            return;
            return;
        }
        }
        log("runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
        Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());


        for (var method : getTestClass().getAnnotatedMethods(annotationClass)) {
        for (var method : getTestClass().getAnnotatedMethods(annotationClass)) {
            ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
            ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
Loading