Skip to content

Commit

Permalink
Reduce references to android.util.Log$TerribleFailure in ShadowLog
Browse files Browse the repository at this point in the history
`android.util.Log$TerribleFailure` is a `@hide` class in `android.util.Log`.  If
tests reference ShadowLog in static blocks or outside of a Robolectric
ClassLoader, a NoClassDefFoundError would result. Update
TerribleFailureReflector to return a generic Throwable in the `@Constructor`
method.

Fixes #8957

PiperOrigin-RevId: 621187529
  • Loading branch information
hoisie authored and Copybara-Service committed Apr 2, 2024
1 parent 5b99268 commit b9c768d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
@@ -0,0 +1,22 @@
package org.robolectric;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.robolectric.shadows.ShadowLog;

/**
* This test attempts to reference ShadowLow from outside of the context of a Robolectric
* environment. ShadowLog contained reflector interfaces that referenced `@hide` classes (e.g.
* TerribleFailure), which cannot be referenced outside of a Robolectric ClassLoader.
*
* @see <a href="https://github.com/robolectric/robolectric/issues/8957">Issue 8957 </a> for more
* details.
*/
@RunWith(JUnit4.class)
public class ShadowLogResolutionTest {
@Test
public void reference_shadowLog_outsideRobolectric() {
ShadowLog.stream = System.out;
}
}
Expand Up @@ -115,17 +115,17 @@ protected static int wtf(String tag, String msg) {
protected static int wtf(String tag, String msg, Throwable throwable) {
addLog(Log.ASSERT, tag, msg, throwable);
// invoking the wtfHandler
TerribleFailure terribleFailure =
Throwable terribleFailure =
reflector(TerribleFailureReflector.class).newTerribleFailure(msg, throwable);
if (wtfIsFatal) {
Util.sneakyThrow(terribleFailure);
}
TerribleFailureHandler terribleFailureHandler = reflector(LogReflector.class).getWtfHandler();
if (RuntimeEnvironment.getApiLevel() >= L.SDK_INT) {
terribleFailureHandler.onTerribleFailure(tag, terribleFailure, false);
terribleFailureHandler.onTerribleFailure(tag, (TerribleFailure) terribleFailure, false);
} else {
reflector(TerribleFailureHandlerReflector.class, terribleFailureHandler)
.onTerribleFailure(tag, terribleFailure);
.onTerribleFailure(tag, (TerribleFailure) terribleFailure);
}
return 0;
}
Expand Down Expand Up @@ -374,7 +374,8 @@ interface TerribleFailureHandlerReflector {

@ForType(TerribleFailure.class)
interface TerribleFailureReflector {
// The return value should be generic because TerribleFailure is a hidden class.
@Constructor
TerribleFailure newTerribleFailure(String msg, Throwable cause);
Throwable newTerribleFailure(String msg, Throwable cause);
}
}

0 comments on commit b9c768d

Please sign in to comment.