Commit 8e6f8572 authored by Kevin McNee's avatar Kevin McNee Committed by Commit Bot

Revert "base/android: Remove linker tests support."

This reverts commit d3cc8c2a.

Reason for revert: Suspect for compile failure https://ci.chromium.org/p/chromium/builders/ci/android-archive-rel/9949?

../../content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/LinkerTests.java:16: error: cannot find symbol
public class LinkerTests implements Linker.TestRunner {
                                          ^
  symbol:   class TestRunner
  location: class Linker

Original change's description:
> base/android: Remove linker tests support.
> 
> The linker tests don't run on bots (and likely not locally either) and
> do not support the latest library loading patterns. This is the first
> step to remove them, as they add non-trivial complexity in the codebase.
> 
> Bug: 1059707
> Change-Id: Ia14693419792f57dc4f65b2fc7f999e833aec42e
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2095059
> Reviewed-by: Yaron Friedman <yfriedman@chromium.org>
> Reviewed-by: Egor Pasko <pasko@chromium.org>
> Commit-Queue: Benoit L <lizeb@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#748365}

TBR=pasko@chromium.org,yfriedman@chromium.org,lizeb@chromium.org

Change-Id: Ib45bd99a42903407e92dfb4a386b31ec0e7f7ee1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1059707
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2095777Reviewed-by: default avatarKevin McNee <mcnee@chromium.org>
Commit-Queue: Kevin McNee <mcnee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748390}
parent d831b52e
...@@ -36,7 +36,6 @@ class LegacyLinker extends Linker { ...@@ -36,7 +36,6 @@ class LegacyLinker extends Linker {
void loadLibraryImplLocked(String library, boolean isFixedAddressPermitted) { void loadLibraryImplLocked(String library, boolean isFixedAddressPermitted) {
ensureInitializedLocked(); ensureInitializedLocked();
assert mState == State.INITIALIZED; // Only one successful call. assert mState == State.INITIALIZED; // Only one successful call.
assert !NativeLibraries.sEnableLinkerTests;
boolean provideRelro = mInBrowserProcess; boolean provideRelro = mInBrowserProcess;
long loadAddress = isFixedAddressPermitted ? mBaseLoadAddress : 0; long loadAddress = isFixedAddressPermitted ? mBaseLoadAddress : 0;
...@@ -51,6 +50,17 @@ class LegacyLinker extends Linker { ...@@ -51,6 +50,17 @@ class LegacyLinker extends Linker {
} }
libInfo.mLibFilePath = libFilePath; libInfo.mLibFilePath = libFilePath;
// Print the load address to the logcat when testing the linker. The format
// of the string is expected by the Python test_runner script as one of:
// BROWSER_LIBRARY_ADDRESS: <library-name> <address>
// RENDERER_LIBRARY_ADDRESS: <library-name> <address>
// Where <library-name> is the library name, and <address> is the hexadecimal load
// address.
if (NativeLibraries.sEnableLinkerTests) {
String tag = mInBrowserProcess ? "BROWSER_LIBRARY_ADDRESS" : "RENDERER_LIBRARY_ADDRESS";
Log.i(TAG, "%s: %s %x", tag, libFilePath, libInfo.mLoadAddress);
}
if (provideRelro) { if (provideRelro) {
if (!nativeCreateSharedRelro(sharedRelRoName, mBaseLoadAddress, libInfo)) { if (!nativeCreateSharedRelro(sharedRelRoName, mBaseLoadAddress, libInfo)) {
Log.w(TAG, "Could not create shared RELRO for %s at %x", libFilePath, Log.w(TAG, "Could not create shared RELRO for %s at %x", libFilePath,
...@@ -75,6 +85,9 @@ class LegacyLinker extends Linker { ...@@ -75,6 +85,9 @@ class LegacyLinker extends Linker {
mLibInfo = null; mLibInfo = null;
mState = State.DONE; mState = State.DONE;
} }
// If testing, run tests now that all libraries are loaded and initialized.
if (NativeLibraries.sEnableLinkerTests) runTestRunnerClassForTesting(mInBrowserProcess);
} }
/** /**
......
...@@ -268,6 +268,10 @@ public class LibraryLoader { ...@@ -268,6 +268,10 @@ public class LibraryLoader {
return mUseModernLinker; return mUseModernLinker;
} }
public boolean areTestsEnabled() {
return NativeLibraries.sEnableLinkerTests;
}
@RemovableInRelease @RemovableInRelease
public void enableJniChecks() { public void enableJniChecks() {
if (!BuildConfig.DCHECK_IS_ON) return; if (!BuildConfig.DCHECK_IS_ON) return;
...@@ -719,8 +723,7 @@ public class LibraryLoader { ...@@ -719,8 +723,7 @@ public class LibraryLoader {
} }
/** /**
* Overrides the library loader (normally with a mock) for testing. * Override the library loader (normally with a mock) for testing.
*
* @param loader the mock library loader. * @param loader the mock library loader.
*/ */
@VisibleForTesting @VisibleForTesting
......
...@@ -129,6 +129,16 @@ public abstract class Linker { ...@@ -129,6 +129,16 @@ public abstract class Linker {
public static final String EXTRA_LINKER_SHARED_RELROS = public static final String EXTRA_LINKER_SHARED_RELROS =
"org.chromium.base.android.linker.shared_relros"; "org.chromium.base.android.linker.shared_relros";
// The name of a class that implements TestRunner.
private String mTestRunnerClassName;
// Constants used to indicate a given Linker implementation, for testing.
// LEGACY -> Always uses the LegacyLinker implementation.
// MODERN -> Always uses the ModernLinker implementation.
// NOTE: These names are known and expected by the Linker test scripts.
public static final int LINKER_IMPLEMENTATION_LEGACY = 1;
public static final int LINKER_IMPLEMENTATION_MODERN = 2;
// Singleton. // Singleton.
protected static final Object sLock = new Object(); protected static final Object sLock = new Object();
...@@ -229,7 +239,7 @@ public abstract class Linker { ...@@ -229,7 +239,7 @@ public abstract class Linker {
// regular library loading. See http://crbug.com/980304 as example. // regular library loading. See http://crbug.com/980304 as example.
// //
// This is only called if LibraryLoader.useChromiumLinker() returns true, meaning this is // This is only called if LibraryLoader.useChromiumLinker() returns true, meaning this is
// either Chrome{,Modern} or Trichrome. // either Chrome{,Modern}, the linker tests or Trichrome.
synchronized (sLock) { synchronized (sLock) {
if (sSingleton == null) { if (sSingleton == null) {
// With incremental install, it's important to fall back to the "normal" // With incremental install, it's important to fall back to the "normal"
...@@ -583,6 +593,128 @@ public abstract class Linker { ...@@ -583,6 +593,128 @@ public abstract class Linker {
public int mRelroFd = -1; // shared RELRO file descriptor, or -1 public int mRelroFd = -1; // shared RELRO file descriptor, or -1
} }
/* ---------------------- Testing support methods. ---------------------- */
/**
* Get Linker implementation type.
* For testing.
*
* @return LINKER_IMPLEMENTATION_LEGACY or LINKER_IMPLEMENTATION_MODERN
*/
public final int getImplementationForTesting() {
// Sanity check. This method may only be called during tests.
assert NativeLibraries.sEnableLinkerTests;
synchronized (sLock) {
assert sSingleton == this;
if (sSingleton instanceof ModernLinker) {
return LINKER_IMPLEMENTATION_MODERN;
} else if (sSingleton instanceof LegacyLinker) {
return LINKER_IMPLEMENTATION_LEGACY;
}
throw new AssertionError("Invalid linker: " + sSingleton.getClass().getName());
}
}
/**
* A public interface used to run runtime linker tests after loading
* libraries. Should only be used to implement the linker unit tests,
* which is controlled by the value of NativeLibraries.sEnableLinkerTests
* configured at build time.
*/
public interface TestRunner {
/**
* Run runtime checks and return true if they all pass.
*
* @param inBrowserProcess true iff this is the browser process.
* @return true if all checks pass.
*/
public boolean runChecks(boolean inBrowserProcess);
}
/**
* Call this to retrieve the name of the current TestRunner class name
* if any. This can be useful to pass it from the browser process to
* child ones.
*
* @return null or a String holding the name of the class implementing
* the TestRunner set by calling setTestRunnerClassNameForTesting() previously.
*/
public final String getTestRunnerClassNameForTesting() {
assert NativeLibraries.sEnableLinkerTests;
synchronized (sLock) {
return mTestRunnerClassName;
}
}
/**
* Set up the Linker for a test.
* Convenience function that calls setImplementationForTesting() to force an
* implementation, and then setTestRunnerClassNameForTesting() to set the test
* class name.
*
* On first call, instantiates a Linker of the requested type and sets its test
* runner class name. On subsequent calls, checks that the singleton produced by
* the first call matches the requested type and test runner class name.
*/
public static final void setupForTesting(int type, String testRunnerClassName) {
assert NativeLibraries.sEnableLinkerTests;
assert type == LINKER_IMPLEMENTATION_LEGACY || type == LINKER_IMPLEMENTATION_MODERN;
if (DEBUG) Log.i(TAG, "setupForTesting(%d, %s) called", type, testRunnerClassName);
synchronized (sLock) {
assert sSingleton == null;
if (type == LINKER_IMPLEMENTATION_MODERN) {
sSingleton = new ModernLinker();
} else if (type == LINKER_IMPLEMENTATION_LEGACY) {
sSingleton = new LegacyLinker();
}
Log.i(TAG, "Forced linker: %s", sSingleton.getClass().getName());
Linker.getInstance().mTestRunnerClassName = testRunnerClassName;
}
}
/**
* Instantiate and run the current TestRunner, if any. The TestRunner implementation
* must be instantiated _after_ all libraries are loaded to ensure that its
* native methods are properly registered.
*
* @param inBrowserProcess true if in the browser process
*/
protected final void runTestRunnerClassForTesting(boolean inBrowserProcess) {
assert NativeLibraries.sEnableLinkerTests;
if (DEBUG) Log.i(TAG, "runTestRunnerClassForTesting called");
synchronized (sLock) {
if (mTestRunnerClassName == null) {
Log.wtf(TAG, "Linker runtime tests not set up for this process");
assert false;
}
if (DEBUG) {
Log.i(TAG, "Instantiating " + mTestRunnerClassName);
}
TestRunner testRunner = null;
try {
testRunner = (TestRunner) Class.forName(mTestRunnerClassName)
.getDeclaredConstructor()
.newInstance();
} catch (Exception e) {
Log.wtf(TAG, "Could not instantiate test runner class by name", e);
assert false;
}
if (!testRunner.runChecks(inBrowserProcess)) {
Log.wtf(TAG, "Linker runtime tests failed in this process");
assert false;
}
Log.i(TAG, "All linker tests passed");
}
}
/** /**
* Return a random address that should be free to be mapped with the given size. * Return a random address that should be free to be mapped with the given size.
* Maps an area large enough for the largest library we might attempt to load, * Maps an area large enough for the largest library we might attempt to load,
......
...@@ -163,6 +163,13 @@ public class ContentChildProcessServiceDelegate implements ChildProcessServiceDe ...@@ -163,6 +163,13 @@ public class ContentChildProcessServiceDelegate implements ChildProcessServiceDe
// Return a Linker instance. If testing, the Linker needs special setup. // Return a Linker instance. If testing, the Linker needs special setup.
private Linker getLinker() { private Linker getLinker() {
if (LibraryLoader.getInstance().areTestsEnabled()) {
// For testing, set the Linker implementation and the test runner
// class name to match those used by the parent.
assert mLinkerParams != null;
Linker.setupForTesting(mLinkerParams.mLinkerImplementationForTesting,
mLinkerParams.mTestRunnerClassNameForTesting);
}
return Linker.getInstance(); return Linker.getInstance();
} }
......
...@@ -640,7 +640,14 @@ public final class ChildProcessLauncherHelperImpl { ...@@ -640,7 +640,14 @@ public final class ChildProcessLauncherHelperImpl {
// Always wait for the shared RELROs in service processes. // Always wait for the shared RELROs in service processes.
final boolean waitForSharedRelros = true; final boolean waitForSharedRelros = true;
return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros); if (LibraryLoader.getInstance().areTestsEnabled()) {
Linker linker = Linker.getInstance();
return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros,
linker.getTestRunnerClassNameForTesting(),
linker.getImplementationForTesting());
} else {
return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros);
}
} }
private static Bundle populateServiceBundle(Bundle bundle) { private static Bundle populateServiceBundle(Bundle bundle) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment