diff options
author | Miao Wang <miaowang@google.com> | 2018-01-25 07:22:45 -0800 |
---|---|---|
committer | Miao Wang <miaowang@google.com> | 2018-03-23 10:24:42 -0700 |
commit | 96a2e0effa320af317c9e2ee047cf542b21c4a38 (patch) | |
tree | 79d2dbeffda64cee8a91da44db62a438c5840375 /tests | |
parent | c8c3eb082ac3b133d26065162c215d1bd6947dae (diff) | |
download | rs-96a2e0effa320af317c9e2ee047cf542b21c4a38.tar.gz |
Add a minimal RS test for fast presubmit tests
- This test is not intended to test all the APIs / functionalities.
It uses IntrinsicBlur to make sure RenderScript is not completely
broken by unexpected changes.
- It runs fast (<200ms), suitable for presubmit tests.
Bug: 72342986
Test: mm
Test: adb shell am instrument -w \
com.android.rs.minimaltest/android.support.test.runner.AndroidJUnitRunner
Change-Id: I2a51b03a2706d25f09224c40cd8f8ad443c4b02f
Diffstat (limited to 'tests')
7 files changed, 499 insertions, 0 deletions
diff --git a/tests/java_api/RsMinimalTest/Android.mk b/tests/java_api/RsMinimalTest/Android.mk new file mode 100644 index 00000000..40088af7 --- /dev/null +++ b/tests/java_api/RsMinimalTest/Android.mk @@ -0,0 +1,32 @@ +# +# Copyright (C) 2018 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. +# + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests +LOCAL_STATIC_JAVA_LIBRARIES := android-support-test + +LOCAL_SRC_FILES := $(call all-java-files-under,src) + +LOCAL_RENDERSCRIPT_TARGET_API := 21 +LOCAL_SDK_VERSION := 26 + +LOCAL_PACKAGE_NAME := RsMinimalTest +LOCAL_COMPATIBILITY_SUITE := device-tests + +include $(BUILD_PACKAGE) + diff --git a/tests/java_api/RsMinimalTest/AndroidManifest.xml b/tests/java_api/RsMinimalTest/AndroidManifest.xml new file mode 100644 index 00000000..43c55834 --- /dev/null +++ b/tests/java_api/RsMinimalTest/AndroidManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 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. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.rs.minimaltest"> + <uses-sdk + android:minSdkVersion="21" + android:targetSdkVersion="26" /> + + <application + android:largeHeap="true" + android:label="_RsMinimalTest" + android:icon="@drawable/test_pattern"> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation + android:name="android.support.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.rs.minimaltest" + android:label="RenderScript Minimal Tests" /> +</manifest> diff --git a/tests/java_api/RsMinimalTest/AndroidTest.xml b/tests/java_api/RsMinimalTest/AndroidTest.xml new file mode 100644 index 00000000..5f39808f --- /dev/null +++ b/tests/java_api/RsMinimalTest/AndroidTest.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 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. +--> +<configuration description="Run RsMinimalTest."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="RsMinimalTest.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-tag" value="RsMinimalTest" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.rs.minimaltest" /> + <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" /> + </test> +</configuration> diff --git a/tests/java_api/RsMinimalTest/res/drawable-nodpi/test_pattern.png b/tests/java_api/RsMinimalTest/res/drawable-nodpi/test_pattern.png Binary files differnew file mode 100644 index 00000000..e7d14555 --- /dev/null +++ b/tests/java_api/RsMinimalTest/res/drawable-nodpi/test_pattern.png diff --git a/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/RsMinimalTest.java b/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/RsMinimalTest.java new file mode 100644 index 00000000..c96fbb19 --- /dev/null +++ b/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/RsMinimalTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 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. + */ + +package com.android.rs.minimaltest; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; +import android.util.Log; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import java.util.ArrayList; +import java.util.List; + +/** + * RsMinimalTest, minimal test for platform RenderScript APIs. + * To run the test, please use command + * + * adb shell am instrument -w com.android.rs.minimaltest/android.support.test.runner.AndroidJUnitRunner + */ +@RunWith(Parameterized.class) +public class RsMinimalTest { + private static final String TAG = RsMinimalTest.class.getSimpleName(); + + /** + * Returns the list of subclasses of UnitTest to run. + */ + @Parameters(name = "{0}") + public static Iterable<?> getParams() throws Exception { + Context ctx = InstrumentationRegistry.getTargetContext(); + + List<UnitTest> validUnitTests = new ArrayList<>(); + + Iterable<Class<? extends UnitTest>> testClasses = + UnitTest.getProperSubclasses(ctx); + for (Class<? extends UnitTest> testClass : testClasses) { + UnitTest test = testClass.getDeclaredConstructor(Context.class).newInstance(ctx); + validUnitTests.add(test); + } + + UnitTest.checkDuplicateNames(validUnitTests); + + return validUnitTests; + } + + @Parameter(0) + public UnitTest mTest; + + @Test + @MediumTest + public void testRSUnitTest() throws Exception { + mTest.logStart(TAG, "RenderScript Testing"); + mTest.runTest(); + mTest.logEnd(TAG); + Assert.assertTrue(mTest.getSuccess()); + } +} diff --git a/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/UT_blur_validation.java b/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/UT_blur_validation.java new file mode 100644 index 00000000..8a20caad --- /dev/null +++ b/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/UT_blur_validation.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2018 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. + */ + +package com.android.rs.minimaltest; + +import android.content.Context; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.RSIllegalArgumentException; +import android.renderscript.ScriptIntrinsicBlur; +import android.renderscript.Type; +import android.util.Log; + +// Tests that ScriptIntrinsicBlur properly throws exception if input or output +// are set to 1D Allocations. +public class UT_blur_validation extends UnitTest { + private static final String TAG = "ScriptIntrinsicBlur validation"; + private RenderScript RS; + private Allocation input1D, output1D; + private Allocation input2D, output2D; + private ScriptIntrinsicBlur scriptBlur; + + public UT_blur_validation(Context ctx) { + super(TAG, ctx); + } + + private void cleanup() { + RS.finish(); + input1D.destroy(); + input2D.destroy(); + output1D.destroy(); + output2D.destroy(); + scriptBlur.destroy(); + RS.destroy(); + } + + public void run() { + RS = createRenderScript(false); + + final int width = 100; + final int height = 100; + + input1D = Allocation.createSized(RS, + Element.U8(RS), + width * height, + Allocation.USAGE_SCRIPT); + + output1D = Allocation.createTyped(RS, input1D.getType()); + + Type.Builder typeBuilder = new Type.Builder(RS, Element.U8(RS)); + typeBuilder.setX(width); + typeBuilder.setY(height); + Type ty = typeBuilder.create(); + + input2D = Allocation.createTyped(RS, ty); + output2D = Allocation.createTyped(RS, ty); + + scriptBlur = ScriptIntrinsicBlur.create(RS, Element.U8(RS)); + + scriptBlur.setRadius(25f); + boolean failed = false; + try { + scriptBlur.setInput(input1D); + } catch (RSIllegalArgumentException e) { + scriptBlur.setInput(input2D); + try { + scriptBlur.forEach(output1D); + } catch (RSIllegalArgumentException e1) { + scriptBlur.forEach(output2D); + cleanup(); + passTest(); + return; + } + Log.e(TAG, "setting 1d output does not trigger exception"); + cleanup(); + failTest(); + return; + } + + Log.e(TAG, "setting 1d input does not trigger exception"); + cleanup(); + failTest(); + } +} diff --git a/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/UnitTest.java b/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/UnitTest.java new file mode 100644 index 00000000..a693dc07 --- /dev/null +++ b/tests/java_api/RsMinimalTest/src/com/android/rs/minimaltest/UnitTest.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2018 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. + */ + +package com.android.rs.minimaltest; + +import android.content.Context; +import android.renderscript.RenderScript; +import android.renderscript.RenderScript.RSMessageHandler; +import android.support.test.InstrumentationRegistry; +import android.util.Log; + +import dalvik.system.DexFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public abstract class UnitTest { + public enum UnitTestResult { + UT_NOT_STARTED, + UT_RUNNING, + UT_SUCCESS, + UT_FAIL; + + @Override + public String toString() { + switch (this) { + case UT_NOT_STARTED: + return "NOT STARTED"; + case UT_RUNNING: + return "RUNNING"; + case UT_SUCCESS: + return "PASS"; + case UT_FAIL: + return "FAIL"; + default: + throw new RuntimeException( + "missing enum case in UnitTestResult#toString()"); + } + } + } + + private final static String TAG = "RSUnitTest"; + + private String mName; + private UnitTestResult mResult; + private Context mCtx; + /* Necessary to avoid race condition on pass/fail message. */ + private CountDownLatch mCountDownLatch; + + /* These constants must match those in shared.rsh */ + public static final int RS_MSG_TEST_PASSED = 100; + public static final int RS_MSG_TEST_FAILED = 101; + + public UnitTest(String n, Context ctx) { + mName = n; + mCtx = ctx; + mResult = UnitTestResult.UT_NOT_STARTED; + mCountDownLatch = null; + } + + protected void _RS_ASSERT(String message, boolean b) { + if (!b) { + Log.e(TAG, message + " FAILED"); + failTest(); + } + } + + /** + * Returns a RenderScript instance created from mCtx. + * + * @param enableMessages + * true if expecting exactly one pass/fail message from the RenderScript instance. + * false if no messages expected. + * Any other messages are not supported. + */ + protected RenderScript createRenderScript(boolean enableMessages) { + RenderScript rs = RenderScript.create(mCtx); + if (enableMessages) { + RSMessageHandler handler = new RSMessageHandler() { + public void run() { + switch (mID) { + case RS_MSG_TEST_PASSED: + passTest(); + break; + case RS_MSG_TEST_FAILED: + failTest(); + break; + default: + Log.w(TAG, String.format("Unit test %s got unexpected message %d", + UnitTest.this.toString(), mID)); + break; + } + mCountDownLatch.countDown(); + } + }; + rs.setMessageHandler(handler); + mCountDownLatch = new CountDownLatch(1); + } + return rs; + } + + protected synchronized void failTest() { + mResult = UnitTestResult.UT_FAIL; + } + + protected synchronized void passTest() { + if (mResult != UnitTestResult.UT_FAIL) { + mResult = UnitTestResult.UT_SUCCESS; + } + } + + public void logStart(String tag, String testSuite) { + String thisDeviceName = android.os.Build.DEVICE; + int thisApiVersion = android.os.Build.VERSION.SDK_INT; + Log.i(tag, String.format("%s: starting '%s' " + + "on device %s, API version %d", + testSuite, toString(), thisDeviceName, thisApiVersion)); + } + + public void logEnd(String tag) { + Log.i(tag, String.format("RenderScript test '%s': %s", + toString(), getResultString())); + } + + public UnitTestResult getResult() { + return mResult; + } + + public String getResultString() { + return mResult.toString(); + } + + public boolean getSuccess() { + return mResult == UnitTestResult.UT_SUCCESS; + } + + public void runTest() { + mResult = UnitTestResult.UT_RUNNING; + run(); + if (mCountDownLatch != null) { + try { + boolean success = mCountDownLatch.await(5 * 60, TimeUnit.SECONDS); + if (!success) { + failTest(); + Log.e(TAG, String.format("Unit test %s waited too long for pass/fail message", + toString())); + } + } catch (InterruptedException e) { + failTest(); + Log.e(TAG, String.format("Unit test %s raised InterruptedException when " + + "listening for pass/fail message", toString())); + } + } + switch (mResult) { + case UT_NOT_STARTED: + case UT_RUNNING: + Log.w(TAG, String.format("unexpected unit test result for test %s: %s", + this.toString(), mResult.toString())); + break; + } + } + + abstract protected void run(); + + @Override + public String toString() { + return mName; + } + + + /** + * Throws RuntimeException if any tests have the same name. + */ + public static void checkDuplicateNames(Iterable<UnitTest> tests) { + Set<String> names = new HashSet<>(); + List<String> duplicates = new ArrayList<>(); + for (UnitTest test : tests) { + String name = test.toString(); + if (names.contains(name)) { + duplicates.add(name); + } + names.add(name); + } + if (!duplicates.isEmpty()) { + throw new RuntimeException("duplicate name(s): " + duplicates); + } + } + + public static Iterable<Class<? extends UnitTest>> getProperSubclasses(Context ctx) + throws ClassNotFoundException, IOException { + return getProperSubclasses(UnitTest.class, ctx); + } + + /** Returns a list of all proper subclasses of the input class */ + private static <T> Iterable<Class<? extends T>> getProperSubclasses(Class<T> klass, Context ctx) + throws ClassNotFoundException, IOException { + ArrayList<Class<? extends T>> ret = new ArrayList<>(); + DexFile df = new DexFile(ctx.getPackageCodePath()); + Enumeration<String> iter = df.entries(); + while (iter.hasMoreElements()) { + String s = iter.nextElement(); + Class<?> cur = Class.forName(s); + while (cur != null) { + if (cur.getSuperclass() == klass) { + break; + } + cur = cur.getSuperclass(); + } + if (cur != null) { + ret.add((Class<? extends T>) cur); + } + } + return ret; + } +} + |