| # Copyright 2017, 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. |
| |
| |
| """Generates necessary files for unit test versions for testing. |
| |
| After adding/changing RenderScript unit tests, run `python RSUnitTests.py` |
| to ensure that forward/backward compatibility tests run properly. |
| |
| This file is so when updating/adding unit tests there is one central location |
| for managing the list of unit tests and their versions. |
| |
| This is necessary since forward compatibility unit tests are chosen at compile |
| time where backward compatibility tests are chosen at runtime. |
| |
| Generates a Java file for backward compatibility testing. |
| Generates an Android.mk file for forward compatibility testing. |
| """ |
| |
| |
| import shutil |
| import sys |
| import os |
| |
| |
| # List of API versions and the tests that correspond to the API version |
| # The test name must correspond to a UT_{}.java file |
| # e.g. alloc -> UT_alloc.java |
| UNIT_TESTS = { |
| 19: [ |
| 'alloc', |
| 'array_alloc', |
| 'array_init', |
| 'atomic', |
| 'bitfield', |
| 'bug_char', |
| 'check_dims', |
| 'clamp_relaxed', |
| 'clamp', |
| 'constant', |
| 'convert_relaxed', |
| 'convert', |
| 'copy_test', |
| 'element', |
| 'foreach', |
| 'foreach_bounds', |
| 'fp_mad', |
| 'instance', |
| 'int4', |
| 'kernel', |
| 'kernel_struct', |
| 'math', |
| 'min', |
| 'noroot', |
| 'primitives', |
| 'refcount', |
| 'rsdebug', |
| 'rstime', |
| 'rstypes', |
| 'sampler', |
| 'static_globals', |
| 'struct_field_simple', |
| 'struct', |
| 'unsigned', |
| 'vector', |
| ], |
| |
| 21: [ |
| 'foreach_multi', |
| 'math_agree', |
| 'math_conformance', |
| ], |
| |
| 23: [ |
| 'alloc_copy', |
| 'alloc_copyPadded', |
| 'ctxt_default', |
| 'kernel2d', |
| 'kernel2d_oldstyle', |
| 'kernel3d', |
| 'rsdebug_23', |
| 'script_group2_gatherscatter', |
| 'script_group2_nochain', |
| 'script_group2_pointwise', |
| ], |
| |
| 24: [ |
| 'fp16', |
| 'fp16_globals', |
| 'math_24', |
| 'math_fp16', |
| 'reduce_backward', |
| 'reduce', |
| 'rsdebug_24', |
| 'script_group2_float', |
| 'single_source_alloc', |
| 'single_source_ref_count', |
| 'single_source_script', |
| 'small_struct', |
| 'small_struct_2', |
| ], |
| |
| 26: [ |
| 'blur_validation', |
| 'struct_field', |
| ], |
| } |
| |
| |
| # Tests that only belong to RSTest_Compat (support lib tests) |
| SUPPORT_LIB_ONLY_UNIT_TESTS = { |
| 'alloc_supportlib', |
| 'apitest', |
| } |
| |
| |
| # Tests that are skipped in RSTest_Compat (support lib tests) |
| SUPPORT_LIB_IGNORE_TESTS = { |
| 'fp16', |
| 'fp16_globals', |
| 'math_fp16', |
| } |
| |
| |
| # Dictionary mapping unit tests to the corresponding needed .rs files |
| # Only needed if UT_{}.java does not map to {}.rs |
| UNIT_TEST_RS_FILES_OVERRIDE = { |
| 'alloc_copy': [], |
| 'alloc_copyPadded': [], |
| 'blur_validation': [], |
| 'script_group2_float': ['float_test.rs'], |
| 'script_group2_gatherscatter': ['addup.rs'], |
| 'script_group2_nochain': ['increment.rs', 'increment2.rs', 'double.rs'], |
| 'script_group2_pointwise': ['increment.rs', 'double.rs'], |
| } |
| |
| |
| # List of API versions and the corresponding build tools release version |
| # For use with forward compatibility testing |
| BUILD_TOOL_VERSIONS = { |
| 21: '21.1.2', |
| 22: '22.0.1', |
| 23: '23.0.3', |
| 24: '24.0.3', |
| 25: '25.0.2', |
| } |
| |
| |
| def ThisScriptDir(): |
| """Returns the directory this script is in.""" |
| return os.path.dirname(os.path.realpath(__file__)) |
| |
| |
| def UnitTestDir(): |
| """Returns the path to the directory containing the unit tests.""" |
| return os.path.join(ThisScriptDir(), 'src', 'com', 'android', 'rs', |
| 'unittest') |
| |
| |
| def SupportLibOnlyTestLocation(): |
| """Returns the path to the directory with unit tests for support lib.""" |
| return os.path.join(ThisScriptDir(), 'supportlibonlysrc', 'com', |
| 'android', 'rs', 'unittest') |
| |
| |
| def SupportLibGenTestLocation(): |
| """Returns the path to the directory with unit tests for support lib.""" |
| return os.path.join(ThisScriptDir(), 'supportlibsrc_gen', 'com', |
| 'android', 'rs', 'unittest') |
| |
| |
| def AllUnitTestsExceptSupportLibOnly(): |
| """Returns a set of all unit tests except SUPPORT_LIB_ONLY_UNIT_TESTS.""" |
| ret = set() |
| for _, tests in UNIT_TESTS.iteritems(): |
| ret.update(tests) |
| return ret |
| |
| |
| def JavaFileForUnitTest(test): |
| """Returns the Java file name for a unit test.""" |
| return 'UT_{}.java'.format(test) |
| |
| |
| def RSFilesForUnitTest(test): |
| """Returns a list of .rs files associated with a test.""" |
| if test in UNIT_TEST_RS_FILES_OVERRIDE: |
| return UNIT_TEST_RS_FILES_OVERRIDE[test] |
| else: |
| # Default is one .rs file with the same name as the input |
| return ['{}.rs'.format(test)] |
| |
| |
| def CopyUnitTestJavaFileToSupportLibTest(java_file_name, java_file_dir): |
| """Copies the Java file to the support lib dir. |
| |
| Replaces RenderScript imports with corresponding support lib imports.""" |
| in_path = os.path.join(java_file_dir, java_file_name) |
| out_path = os.path.join(SupportLibGenTestLocation(), java_file_name) |
| with open(in_path, 'r') as in_file, open(out_path, 'w') as out_file: |
| out_file.write( |
| '// This file is automatically generated from\n' |
| '// frameworks/rs/tests/java_api/RSUnitTests/RSUnitTests.py\n' |
| ) |
| for line in in_file.readlines(): |
| if line.startswith('import android.renderscript.'): |
| line = line.replace('android.renderscript.', |
| 'android.support.v8.renderscript.') |
| out_file.write(line) |
| |
| |
| def CopyUnitTestRSToSupportLibTest(rs_file_name, rs_file_dir): |
| """Copies the .rs to the support lib dir.""" |
| in_path = os.path.join(rs_file_dir, rs_file_name) |
| out_path = os.path.join(SupportLibGenTestLocation(), rs_file_name) |
| with open(out_path, 'w') as out_file: |
| out_file.write( |
| '// This file is automatically generated from\n' |
| '// frameworks/rs/tests/java_api/RSUnitTests/RSUnitTests.py\n' |
| ) |
| with open(in_path, 'r') as in_file: |
| out_file.write(in_file.read()) |
| |
| |
| def CopySharedRshToSupportLibTest(): |
| """Copies shared.rsh to the support lib dir. |
| |
| Adds a #define RSTEST_COMPAT at the end.""" |
| shared_rsh = 'shared.rsh' |
| CopyUnitTestRSToSupportLibTest(shared_rsh, UnitTestDir()) |
| with open(os.path.join(SupportLibGenTestLocation(), shared_rsh), 'a') as shared: |
| shared.write('\n#define RSTEST_COMPAT\n') |
| |
| |
| def CopyUnitTestToSupportLibTest(test, test_dir): |
| """Copies all files corresponding to a unit test to support lib dir.""" |
| CopyUnitTestJavaFileToSupportLibTest(JavaFileForUnitTest(test), test_dir) |
| for rs in RSFilesForUnitTest(test): |
| CopyUnitTestRSToSupportLibTest(rs, test_dir) |
| |
| |
| def GenerateSupportLibUnitTests(): |
| """Generates all support lib unit tests.""" |
| if os.path.exists(SupportLibGenTestLocation()): |
| shutil.rmtree(SupportLibGenTestLocation()) |
| os.makedirs(SupportLibGenTestLocation()) |
| |
| CopySharedRshToSupportLibTest() |
| CopyUnitTestJavaFileToSupportLibTest('UnitTest.java', UnitTestDir()) |
| |
| for test in AllUnitTestsExceptSupportLibOnly() - SUPPORT_LIB_IGNORE_TESTS: |
| CopyUnitTestToSupportLibTest(test, UnitTestDir()) |
| |
| for test in SUPPORT_LIB_ONLY_UNIT_TESTS: |
| CopyUnitTestToSupportLibTest(test, SupportLibOnlyTestLocation()) |
| |
| print ('Generated support lib tests at {}' |
| .format(SupportLibGenTestLocation())) |
| |
| |
| def WriteMakeCopyright(gen_file): |
| """Writes the copyright for a Makefile to a file.""" |
| gen_file.write( |
| '#\n' |
| '# Copyright (C) 2017 The Android Open Source Project\n' |
| '#\n' |
| '# Licensed under the Apache License, Version 2.0 (the "License");\n' |
| '# you may not use this file except in compliance with the License.\n' |
| '# You may obtain a copy of the License at\n' |
| '#\n' |
| '# http://www.apache.org/licenses/LICENSE-2.0\n' |
| '#\n' |
| '# Unless required by applicable law or agreed to in writing, software\n' |
| '# distributed under the License is distributed on an "AS IS" BASIS,\n' |
| '# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n' |
| '# See the License for the specific language governing permissions and\n' |
| '# limitations under the License.\n' |
| '#\n\n' |
| ) |
| |
| |
| def WriteMakeSrcFiles(gen_file, api_version): |
| """Writes applicable LOCAL_SRC_FILES to gen_file. |
| |
| Includes everything under ./src, base UnitTest class, and test files. |
| |
| api_version: only tests that can run on this version are added.""" |
| # Get all tests compatible with the build tool version |
| # Compatible means build tool version >= test version |
| tests = [] |
| for test_version, tests_for_version in UNIT_TESTS.iteritems(): |
| if api_version >= test_version: |
| tests.extend(tests_for_version) |
| tests = sorted(tests) |
| gen_file.write( |
| 'LOCAL_SRC_FILES := $(call all-java-files-under,src)\\\n' |
| ' $(my_rs_unit_tests_path)/UnitTest.java\\\n' |
| ) |
| for test in tests: |
| # Add the Java and corresponding rs files to LOCAL_SRC_FILES |
| gen_file.write( |
| ' $(my_rs_unit_tests_path)/{}\\\n' |
| .format(JavaFileForUnitTest(test)) |
| ) |
| for rs_file in RSFilesForUnitTest(test): |
| gen_file.write( |
| ' $(my_rs_unit_tests_path)/{}\\\n'.format( |
| rs_file |
| ) |
| ) |
| |
| |
| |
| def ForwardMakefileLocation(): |
| """Returns the location of the Makefile for forward compatibility testing.""" |
| return os.path.join(ThisScriptDir(), '..', 'RSTestForward', 'Android.mk') |
| |
| |
| def WriteForwardMakefile(gen_file): |
| """Writes the Makefile for forward compatibility testing. |
| |
| Makefile contains a build target per build tool version |
| for forward compatibility testing based on the unit test list at the |
| top of this file.""" |
| WriteMakeCopyright(gen_file) |
| gen_file.write( |
| '# This file is auto-generated by frameworks/rs/tests/java_api/RSUnitTests/RSUnitTests.py.\n' |
| '# To change unit tests version, please run the Python script above.\n\n' |
| 'ifneq ($(ENABLE_RSTESTFORWARD),)\n\n' |
| 'LOCAL_PATH := $(call my-dir)\n' |
| 'my_rs_test_forward_targets :=\n' |
| 'my_rs_unit_tests_path := ../RSUnitTests/src/com/android/rs/unittest\n' |
| ) |
| all_make_target_names = [] |
| for build_tool_version in sorted(BUILD_TOOL_VERSIONS.keys()): |
| build_tool_version_name = BUILD_TOOL_VERSIONS[build_tool_version] |
| make_target_name = 'RSTestForward_{}'.format(build_tool_version_name) |
| make_target_name = make_target_name.replace('.', '_') |
| all_make_target_names.append(make_target_name) |
| gen_file.write( |
| '\n' |
| '# RSTestForward for build tool version {}\n\n' |
| 'include $(CLEAR_VARS)\n\n' |
| 'LOCAL_MODULE_TAGS := tests\n' |
| 'LOCAL_STATIC_JAVA_LIBRARIES := android-support-test\n' |
| 'LOCAL_COMPATIBILITY_SUITE := device-tests\n' |
| 'LOCAL_RENDERSCRIPT_TARGET_API := 0\n' |
| 'LOCAL_PACKAGE_NAME := {}\n' |
| 'my_rs_path := $(TOP)/prebuilts/renderscript/host/linux-x86/{}\n' |
| 'LOCAL_RENDERSCRIPT_CC := $(my_rs_path)/bin/llvm-rs-cc\n' |
| 'LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := $(my_rs_path)/include $(my_rs_path)/clang-include\n' |
| 'my_rs_path :=\n'.format( |
| build_tool_version_name, make_target_name, build_tool_version_name |
| ) |
| ) |
| WriteMakeSrcFiles(gen_file, build_tool_version) |
| # With dist-for-goals, copy the target to DIST_DIR with 'make dist' |
| gen_file.write( |
| '\n' |
| 'include $(BUILD_PACKAGE)\n' |
| '$(call dist-for-goals,RSTestForward,$(LOCAL_BUILT_MODULE):$(LOCAL_PACKAGE_NAME).apk)\n' |
| 'my_rs_test_forward_targets += $(LOCAL_BUILT_MODULE)\n' |
| ) |
| # Create RSTestForward phony target which builds all above targets |
| gen_file.write( |
| '\n' |
| '.PHONY: RSTestForward\n' |
| 'RSTestForward: $(my_rs_test_forward_targets)\n' |
| 'my_rs_unit_tests_path :=\n' |
| 'my_rs_test_forward_targets :=\n\n' |
| 'endif\n'.format(' '.join(all_make_target_names)) |
| ) |
| |
| |
| def GenerateForward(): |
| """Generates the necessary file for forward compatibility testing.""" |
| with open(ForwardMakefileLocation(), 'w') as gen_file: |
| WriteForwardMakefile(gen_file) |
| print ('Generated forward compatibility Makefile at {}' |
| .format(ForwardMakefileLocation())) |
| |
| |
| def BackwardJavaFileLocation(): |
| """Returns the location of Java file for backward compatibility testing.""" |
| return os.path.join(ThisScriptDir(), '..', 'RSTestBackward', 'src', 'com', |
| 'android', 'rs', 'testbackward', 'RSTests.java') |
| |
| |
| def Backward19JavaFileLocation(): |
| """Returns the location of Java file for backward compatibility 19 testing.""" |
| return os.path.join(ThisScriptDir(), '..', 'RSTestBackward19', 'src', 'com', |
| 'android', 'rs', 'testbackward19', 'RSTests.java') |
| |
| |
| def Backward19MakefileLocation(): |
| """Returns the location of Makefile for backward compatibility 19 testing.""" |
| return os.path.join(ThisScriptDir(), '..', 'RSTestBackward19', 'Android.mk') |
| |
| |
| def WriteJavaCopyright(gen_file): |
| """Writes the copyright for a Java file to gen_file.""" |
| gen_file.write( |
| '/*\n' |
| ' * Copyright (C) 2017 The Android Open Source Project\n' |
| ' *\n' |
| ' * Licensed under the Apache License, Version 2.0 (the "License");\n' |
| ' * you may not use this file except in compliance with the License.\n' |
| ' * You may obtain a copy of the License at\n' |
| ' *\n' |
| ' * http://www.apache.org/licenses/LICENSE-2.0\n' |
| ' *\n' |
| ' * Unless required by applicable law or agreed to in writing, software\n' |
| ' * distributed under the License is distributed on an "AS IS" BASIS,\n' |
| ' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n' |
| ' * See the License for the specific language governing permissions and\n' |
| ' * limitations under the License.\n' |
| ' */\n\n' |
| ) |
| |
| |
| def WriteBackwardJavaFile(gen_file, package, max_api_version=None): |
| """Writes the Java file for backward compatibility testing to gen_file. |
| |
| Java file determines unit tests for backward compatibility |
| testing based on the unit test list at the top of this file.""" |
| WriteJavaCopyright(gen_file) |
| gen_file.write( |
| 'package {};\n' |
| '\n' |
| 'import com.android.rs.unittest.*;\n' |
| '\n' |
| 'import java.util.ArrayList;\n' |
| '\n' |
| '/**\n' |
| ' * This class is auto-generated by frameworks/rs/tests/java_api/RSUnitTests/RSUnitTests.py.\n' |
| ' * To change unit tests version, please run the Python script above.\n' |
| ' */\n' |
| 'public class RSTests {{\n' |
| ' public static Iterable<Class<? extends UnitTest>> getTestClassesForCurrentAPIVersion() {{\n' |
| ' int thisApiVersion = android.os.Build.VERSION.SDK_INT;\n' |
| '\n' |
| ' ArrayList<Class<? extends UnitTest>> validClasses = new ArrayList<>();'.format( |
| package |
| ) |
| ) |
| for version in sorted(UNIT_TESTS.keys()): |
| if max_api_version is None or version <= max_api_version: |
| tests = sorted(UNIT_TESTS[version]) |
| gen_file.write( |
| '\n\n if (thisApiVersion >= {}) {{\n'.format(version) |
| ) |
| for test in tests: |
| gen_file.write( |
| ' validClasses.add(UT_{}.class);\n'.format(test) |
| ) |
| gen_file.write(' }') |
| gen_file.write('\n\n return validClasses;\n }\n}\n') |
| |
| |
| def WriteBackward19Makefile(gen_file): |
| """Writes the Makefile for backward compatibility 19 testing.""" |
| WriteMakeCopyright(gen_file) |
| gen_file.write( |
| '# This file is auto-generated by frameworks/rs/tests/java_api/RSUnitTests/RSUnitTests.py.\n' |
| '# To change unit tests version, please run the Python script above.\n\n' |
| 'LOCAL_PATH := $(call my-dir)\n' |
| 'include $(CLEAR_VARS)\n\n' |
| 'LOCAL_MODULE_TAGS := tests\n' |
| 'LOCAL_STATIC_JAVA_LIBRARIES := android-support-test\n' |
| 'LOCAL_COMPATIBILITY_SUITE := device-tests\n' |
| 'LOCAL_RENDERSCRIPT_TARGET_API := 19\n' |
| 'LOCAL_MIN_SDK_VERSION := 17\n' |
| 'LOCAL_PACKAGE_NAME := RSTestBackward19\n' |
| 'my_rs_unit_tests_path := ../RSUnitTests/src/com/android/rs/unittest\n' |
| ) |
| WriteMakeSrcFiles(gen_file, 19) |
| # With dist-for-goals, copy the target to DIST_DIR with 'make dist' |
| gen_file.write( |
| '\n' |
| 'include $(BUILD_PACKAGE)\n\n' |
| 'my_rs_unit_tests_path :=\n\n' |
| '$(call dist-for-goals,$(LOCAL_PACKAGE_NAME),$(LOCAL_BUILT_MODULE):$(LOCAL_PACKAGE_NAME).apk)\n' |
| ) |
| |
| |
| def GenerateBackward(): |
| """Generates Java file for backward compatibility testing.""" |
| with open(BackwardJavaFileLocation(), 'w') as gen_file: |
| WriteBackwardJavaFile(gen_file, 'com.android.rs.testbackward') |
| print ('Generated backward compatibility Java file at {}' |
| .format(BackwardJavaFileLocation())) |
| |
| |
| def GenerateBackward19(): |
| """Generates files for backward compatibility testing for API 19.""" |
| with open(Backward19JavaFileLocation(), 'w') as gen_file: |
| WriteBackwardJavaFile(gen_file, 'com.android.rs.testbackward19', 19) |
| print ('Generated backward compatibility (19) Java file at {}' |
| .format(Backward19JavaFileLocation())) |
| |
| with open(Backward19MakefileLocation(), 'w') as gen_file: |
| WriteBackward19Makefile(gen_file) |
| print ('Generated backward compatibility (19) Makefile at {}' |
| .format(Backward19MakefileLocation())) |
| |
| |
| def DisplayHelp(): |
| """Prints help message.""" |
| print >> sys.stderr, ('Usage: {} [forward] [backward] [backward19] [help|-h|--help]\n' |
| .format(sys.argv[0])) |
| print >> sys.stderr, ('[forward]: write forward compatibility Makefile to\n {}\n' |
| .format(ForwardMakefileLocation())) |
| print >> sys.stderr, ('[backward]: write backward compatibility Java file to\n {}\n' |
| .format(BackwardJavaFileLocation())) |
| print >> sys.stderr, ('[backward19]: write backward compatibility Java file (19) to\n {}\n' |
| .format(Backward19JavaFileLocation())) |
| print >> sys.stderr, ('[backward19]: write backward compatibility Makefile (19) to\n {}\n' |
| .format(Backward19MakefileLocation())) |
| print >> sys.stderr, ('[supportlib]: generate support lib unit tests to\n {}\n' |
| .format(SupportLibGenTestLocation())) |
| print >> sys.stderr, 'if no options are chosen, then all files are generated' |
| |
| |
| def main(): |
| """Parses sys.argv and does stuff.""" |
| display_help = False |
| error = False |
| actions = [] |
| |
| for arg in sys.argv[1:]: |
| if arg in ('help', '-h', '--help'): |
| display_help = True |
| elif arg == 'backward': |
| actions.append(GenerateBackward) |
| elif arg == 'backward19': |
| actions.append(GenerateBackward19) |
| elif arg == 'forward': |
| actions.append(GenerateForward) |
| elif arg == 'supportlib': |
| actions.append(GenerateSupportLibUnitTests) |
| else: |
| print >> sys.stderr, 'unrecognized arg: {}'.format(arg) |
| error = True |
| |
| if display_help or error: |
| DisplayHelp() |
| elif actions: |
| for action in actions: |
| action() |
| else: |
| # No args - do default action. |
| GenerateBackward() |
| GenerateBackward19() |
| GenerateForward() |
| GenerateSupportLibUnitTests() |
| |
| if __name__ == '__main__': |
| main() |