diff options
6 files changed, 94 insertions, 25 deletions
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index f2930fe45295..8e860c35388d 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -465,9 +465,7 @@ public final class Parcel { private static native byte[] nativeMarshall(long nativePtr); private static native void nativeUnmarshall( long nativePtr, byte[] data, int offset, int length); - @RavenwoodThrow private static native int nativeCompareData(long thisNativePtr, long otherNativePtr); - @RavenwoodThrow private static native boolean nativeCompareDataInRange( long ptrA, int offsetA, long ptrB, int offsetB, int length); private static native void nativeAppendFrom( diff --git a/core/tests/coretests/src/android/os/BundleTest.java b/core/tests/coretests/src/android/os/BundleTest.java index 8c231de5598f..e7b5dff60110 100644 --- a/core/tests/coretests/src/android/os/BundleTest.java +++ b/core/tests/coretests/src/android/os/BundleTest.java @@ -197,7 +197,6 @@ public class BundleTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void kindofEquals_bothParcelled_same() { Bundle bundle1 = new Bundle(); bundle1.putString("StringKey", "S"); @@ -215,7 +214,6 @@ public class BundleTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void kindofEquals_bothParcelled_different() { Bundle bundle1 = new Bundle(); bundle1.putString("StringKey", "S"); @@ -247,7 +245,6 @@ public class BundleTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void kindofEquals_lazyValues() { Parcelable p1 = new CustomParcelable(13, "Tiramisu"); Parcelable p2 = new CustomParcelable(13, "Tiramisu"); @@ -281,7 +278,6 @@ public class BundleTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void kindofEquals_lazyValuesWithIdenticalParcels_returnsTrue() { Parcelable p1 = new CustomParcelable(13, "Tiramisu"); Parcelable p2 = new CustomParcelable(13, "Tiramisu"); diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java index 5bbd2219e2f0..26f6d696768a 100644 --- a/core/tests/coretests/src/android/os/ParcelTest.java +++ b/core/tests/coretests/src/android/os/ParcelTest.java @@ -132,7 +132,6 @@ public class ParcelTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void testCompareDataInRange_whenSameData() { Parcel pA = Parcel.obtain(); int iA = pA.dataPosition(); @@ -169,7 +168,6 @@ public class ParcelTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void testCompareDataInRange_whenDifferentData() { Parcel pA = Parcel.obtain(); int iA = pA.dataPosition(); @@ -186,7 +184,6 @@ public class ParcelTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void testCompareDataInRange_whenLimitOutOfBounds_throws() { Parcel pA = Parcel.obtain(); int iA = pA.dataPosition(); @@ -213,7 +210,6 @@ public class ParcelTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void testCompareDataInRange_whenLengthZero() { Parcel pA = Parcel.obtain(); int iA = pA.dataPosition(); @@ -232,7 +228,6 @@ public class ParcelTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void testCompareDataInRange_whenNegativeLength_throws() { Parcel pA = Parcel.obtain(); int iA = pA.dataPosition(); @@ -248,7 +243,6 @@ public class ParcelTest { } @Test - @IgnoreUnderRavenwood(blockedBy = Parcel.class) public void testCompareDataInRange_whenNegativeOffset_throws() { Parcel pA = Parcel.obtain(); int iA = pA.dataPosition(); diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java index d175713eb92f..513c09587026 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java @@ -16,6 +16,8 @@ package android.platform.test.ravenwood; +import static org.junit.Assert.fail; + import android.platform.test.annotations.IgnoreUnderRavenwood; import org.junit.Assume; @@ -36,6 +38,15 @@ public class RavenwoodRule implements TestRule { private static final boolean IS_UNDER_RAVENWOOD = RavenwoodRuleImpl.isUnderRavenwood(); + /** + * When probing is enabled, all tests will be unconditionally run under Ravenwood to detect + * cases where a test is able to pass despite being marked as {@code IgnoreUnderRavenwood}. + * + * This is typically helpful for internal maintainers discovering tests that had previously + * been ignored, but now have enough Ravenwood-supported functionality to be enabled. + */ + private static final boolean ENABLE_PROBE_IGNORED = false; // DO NOT SUBMIT WITH TRUE + private static final int SYSTEM_UID = 1000; private static final int NOBODY_UID = 9999; private static final int FIRST_APPLICATION_UID = 10000; @@ -97,26 +108,76 @@ public class RavenwoodRule implements TestRule { return IS_UNDER_RAVENWOOD; } + /** + * Test if the given {@link Description} has been marked with an {@link IgnoreUnderRavenwood} + * annotation, either at the method or class level. + */ + private static boolean hasIgnoreUnderRavenwoodAnnotation(Description description) { + if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) { + return true; + } else if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) { + return true; + } else { + return false; + } + } + @Override public Statement apply(Statement base, Description description) { + if (ENABLE_PROBE_IGNORED) { + return applyProbeIgnored(base, description); + } else { + return applyDefault(base, description); + } + } + + /** + * Run the given {@link Statement} with no special treatment. + */ + private Statement applyDefault(Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { - if (description.getTestClass().getAnnotation(IgnoreUnderRavenwood.class) != null) { - Assume.assumeFalse(IS_UNDER_RAVENWOOD); - } - if (description.getAnnotation(IgnoreUnderRavenwood.class) != null) { + if (hasIgnoreUnderRavenwoodAnnotation(description)) { Assume.assumeFalse(IS_UNDER_RAVENWOOD); } - if (IS_UNDER_RAVENWOOD) { - RavenwoodRuleImpl.init(RavenwoodRule.this); - } + + RavenwoodRuleImpl.init(RavenwoodRule.this); try { base.evaluate(); } finally { - if (IS_UNDER_RAVENWOOD) { - RavenwoodRuleImpl.reset(RavenwoodRule.this); + RavenwoodRuleImpl.reset(RavenwoodRule.this); + } + } + }; + } + + /** + * Run the given {@link Statement} with probing enabled. All tests will be unconditionally + * run under Ravenwood to detect cases where a test is able to pass despite being marked as + * {@code IgnoreUnderRavenwood}. + */ + private Statement applyProbeIgnored(Statement base, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + RavenwoodRuleImpl.init(RavenwoodRule.this); + try { + base.evaluate(); + } catch (Throwable t) { + if (hasIgnoreUnderRavenwoodAnnotation(description)) { + // This failure is expected, so eat the exception and report the + // assumption failure that test authors expect + Assume.assumeFalse(IS_UNDER_RAVENWOOD); } + throw t; + } finally { + RavenwoodRuleImpl.reset(RavenwoodRule.this); + } + + if (hasIgnoreUnderRavenwoodAnnotation(description) && IS_UNDER_RAVENWOOD) { + fail("Test was annotated with IgnoreUnderRavenwood, but it actually " + + "passed under Ravenwood; consider removing the annotation"); } } }; diff --git a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java index fb71e9d1ac6f..0ff6a1ad846b 100644 --- a/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java +++ b/ravenwood/junit-stub-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java @@ -22,12 +22,10 @@ public class RavenwoodRuleImpl { } public static void init(RavenwoodRule rule) { - // Must be provided by impl to reference runtime internals - throw new UnsupportedOperationException(); + // No-op when running on a real device } public static void reset(RavenwoodRule rule) { - // Must be provided by impl to reference runtime internals - throw new UnsupportedOperationException(); + // No-op when running on a real device } } diff --git a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java index 3bcabcb01c5e..d63bff6f4da3 100644 --- a/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java +++ b/tools/hoststubgen/hoststubgen/helper-framework-runtime-src/framework/com/android/hoststubgen/nativesubstitution/Parcel_host.java @@ -343,6 +343,28 @@ public class Parcel_host { p.mPos += length; p.updateSize(); } + public static int nativeCompareData(long thisNativePtr, long otherNativePtr) { + var a = getInstance(thisNativePtr); + var b = getInstance(otherNativePtr); + if ((a.mSize == b.mSize) && Arrays.equals(a.mBuffer, b.mBuffer)) { + return 0; + } else { + return -1; + } + } + public static boolean nativeCompareDataInRange( + long ptrA, int offsetA, long ptrB, int offsetB, int length) { + var a = getInstance(ptrA); + var b = getInstance(ptrB); + if (offsetA < 0 || offsetA + length > a.mSize) { + throw new IllegalArgumentException(); + } + if (offsetB < 0 || offsetB + length > b.mSize) { + throw new IllegalArgumentException(); + } + return Arrays.equals(Arrays.copyOfRange(a.mBuffer, offsetA, offsetA + length), + Arrays.copyOfRange(b.mBuffer, offsetB, offsetB + length)); + } public static void nativeAppendFrom( long thisNativePtr, long otherNativePtr, int srcOffset, int length) { var dst = getInstance(thisNativePtr); |