diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index aed4a5966..e444735c2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -158,6 +158,66 @@ function(generate_cts_test) add_dependencies(generate_test_sources ${GEN_TEST_FILE_NAME}_gen) endfunction() +# Test generation routine +function(generate_multifile_cts_test) + cmake_parse_arguments( + GEN_TEST + "" + "TESTS;GENERATOR;FILE_PREFIX;EXT;INPUT" + "EXTRA_ARGS;DEPENDS" + ${ARGN} + ) + get_filename_component(test_dir ${CMAKE_CURRENT_SOURCE_DIR} NAME) + if(${test_dir} IN_LIST exclude_categories) + return() + endif() + + message(STATUS "Setup test generation rules for prefix: " ${GEN_TEST_FILE_PREFIX}) + + set(GEN_TEST_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${GEN_TEST_INPUT}) + + # Execute generator to get the files that will be generated. + execute_process(COMMAND + ${PYTHON_EXECUTABLE} + ${GEN_TEST_GENERATOR} + ${GEN_TEST_INPUT} + -output-prefix ${CMAKE_CURRENT_BINARY_DIR}/${GEN_TEST_FILE_PREFIX} + -ext ${GEN_TEST_EXT} + -print-output-files + ${GEN_TEST_EXTRA_ARGS} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE GEN_TEST_OUTPUT_FILES + OUTPUT_STRIP_TRAILING_WHITESPACE + ECHO_ERROR_VARIABLE) + + # Add the file to the out test list + set(${GEN_TEST_TESTS} ${${GEN_TEST_TESTS}} ${GEN_TEST_OUTPUT_FILES} PARENT_SCOPE) + + set(extra_deps "") + foreach(filename ${GEN_TEST_DEPENDS}) + list(APPEND extra_deps ${CMAKE_CURRENT_SOURCE_DIR}/${filename}) + endforeach() + + add_custom_command(OUTPUT ${GEN_TEST_OUTPUT_FILES} + COMMAND + ${PYTHON_EXECUTABLE} + ${GEN_TEST_GENERATOR} + ${GEN_TEST_INPUT} + -output-prefix ${CMAKE_CURRENT_BINARY_DIR}/${GEN_TEST_FILE_PREFIX} + -ext ${GEN_TEST_EXT} + ${GEN_TEST_EXTRA_ARGS} + DEPENDS + ${GEN_TEST_GENERATOR} + ${GEN_TEST_INPUT} + ${extra_deps} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Generating test ${GEN_TEST_FILE_PREFIX}..." + ) + + add_custom_target(${GEN_TEST_FILE_PREFIX}_gen DEPENDS ${GEN_TEST_OUTPUT_FILES}) + add_dependencies(generate_test_sources ${GEN_TEST_FILE_PREFIX}_gen) +endfunction() + # create a target to encapsulate all test categories. add_custom_target(test_conformance) diff --git a/tests/math_builtin_api/CMakeLists.txt b/tests/math_builtin_api/CMakeLists.txt index b408ac7e9..8b80d5430 100644 --- a/tests/math_builtin_api/CMakeLists.txt +++ b/tests/math_builtin_api/CMakeLists.txt @@ -25,11 +25,12 @@ foreach(cat ${MATH_CAT_WITH_VARIANT}) endif() # Invoke our generator # the path to the generated cpp file will be added to TEST_CASES_LIST - generate_cts_test(TESTS TEST_CASES_LIST + generate_multifile_cts_test(TESTS TEST_CASES_LIST GENERATOR "generate_math_builtin.py" - OUTPUT "math_builtin_${cat}_${var}.cpp" + FILE_PREFIX "math_builtin_${cat}_${var}" + EXT "cpp" INPUT "math_builtin.template" - EXTRA_ARGS -test ${cat} -variante ${var} -marray true + EXTRA_ARGS -test ${cat} -variante ${var} -marray true -fragment-size 150 DEPENDS ${math_builtin_depends} ) endforeach() @@ -38,11 +39,12 @@ endforeach() foreach(cat ${MATH_CAT}) # Invoke our generator # the path to the generated cpp file will be added to TEST_CASES_LIST - generate_cts_test(TESTS TEST_CASES_LIST + generate_multifile_cts_test(TESTS TEST_CASES_LIST GENERATOR "generate_math_builtin.py" - OUTPUT "math_builtin_${cat}.cpp" + FILE_PREFIX "math_builtin_${cat}" + EXT "cpp" INPUT "math_builtin.template" - EXTRA_ARGS -test ${cat} -marray true + EXTRA_ARGS -test ${cat} -marray true -fragment-size 150 DEPENDS ${math_builtin_depends} ) endforeach() diff --git a/tests/math_builtin_api/generate_math_builtin.py b/tests/math_builtin_api/generate_math_builtin.py index 354aa2f08..8f0f6b014 100755 --- a/tests/math_builtin_api/generate_math_builtin.py +++ b/tests/math_builtin_api/generate_math_builtin.py @@ -24,6 +24,7 @@ import os import sys import argparse +import math from modules import sycl_types from modules import sycl_functions from modules import test_generator @@ -74,34 +75,9 @@ def write_cases_to_file(generated_test_cases, inputFile, outputFile, extension=N with open(outputFile, 'w+') as output: output.write(newSource) -def create_tests(test_id, types, signatures, kind, template, file_name, check = False): - expanded_signatures = test_generator.expand_signatures(types, signatures) - - # Extensions should be placed on separate files. - base_signatures = [] - half_signatures = [] - double_signatures = [] - for sig in expanded_signatures: - if contains_base_type(sig, "double"): - double_signatures.append(sig) - continue - if contains_base_type(sig, "sycl::half"): - half_signatures.append(sig) - continue - base_signatures.append(sig) - - if base_signatures and kind == 'base': - generated_base_test_cases = test_generator.generate_test_cases(test_id, types, base_signatures, check) - write_cases_to_file(generated_base_test_cases, template, file_name) - elif half_signatures and kind == 'half': - generated_half_test_cases = test_generator.generate_test_cases(test_id + 300000, types, half_signatures, check) - write_cases_to_file(generated_half_test_cases, template, file_name, "fp16") - elif double_signatures and kind == 'double': - generated_double_test_cases = test_generator.generate_test_cases(test_id + 600000, types, double_signatures, check) - write_cases_to_file(generated_double_test_cases, template, file_name, "fp64") - else: - print("No %s overloads to generate for the test category" % kind) - sys.exit(1) +def create_tests(test_id, types, signatures, template, file_name, extension, check = False): + generated_test_cases = test_generator.generate_test_cases(test_id, types, signatures, check) + write_cases_to_file(generated_test_cases, template, file_name, extension) def main(): argparser = argparse.ArgumentParser( @@ -127,11 +103,22 @@ def main(): default='false', help='Generate tests with marray function arguments') argparser.add_argument( - '-o', - dest="output", + '-print-output-files', + action='store_true', + help='Print all generated output files instead of generating the test files') + argparser.add_argument( + '-fragment-size', + type=int, + required=False, + help='Generate test files with tests for N math function signatures') + argparser.add_argument( + '-output-prefix', required=True, - metavar='', - help='CTS test output') + help='CTS test output file name prefix') + argparser.add_argument( + '-ext', + required=True, + help='CTS test output file extension') args = argparser.parse_args() use_marray = (args.marray == 'true') @@ -145,33 +132,81 @@ def main(): verifyResults = True + test_signatures = [] + test_id_offset = 0 if args.test == 'integer': - integer_signatures = sycl_functions.create_integer_signatures() - create_tests(0, expanded_types, integer_signatures, args.variante, args.template, args.output, verifyResults) - - if args.test == 'common': - common_signatures = sycl_functions.create_common_signatures() - create_tests(1000000, expanded_types, common_signatures, args.variante, args.template, args.output, verifyResults) + test_signatures = sycl_functions.create_integer_signatures() + test_id_offset = 0 + elif args.test == 'common': + test_signatures = sycl_functions.create_common_signatures() + test_id_offset = 1000000 + elif args.test == 'geometric': + test_signatures = sycl_functions.create_geometric_signatures() + test_id_offset = 2000000 + elif args.test == 'relational': + test_signatures = sycl_functions.create_relational_signatures() + test_id_offset = 3000000 + elif args.test == 'float': + test_signatures = sycl_functions.create_float_signatures() + test_id_offset = 4000000 + elif args.test == 'native': + test_signatures = sycl_functions.create_native_signatures() + test_id_offset = 5000000 + elif args.test == 'half': + test_signatures = sycl_functions.create_half_signatures() + test_id_offset = 6000000 + + test_signatures = test_generator.expand_signatures(expanded_types, test_signatures, silent=args.print_output_files) - if args.test == 'geometric': - geomteric_signatures = sycl_functions.create_geometric_signatures() - create_tests(2000000, expanded_types, geomteric_signatures, args.variante, args.template, args.output, verifyResults) + # Extensions should be placed on separate files. + base_signatures = [] + half_signatures = [] + double_signatures = [] + for sig in test_signatures: + if contains_base_type(sig, "double"): + double_signatures.append(sig) + continue + if contains_base_type(sig, "sycl::half"): + half_signatures.append(sig) + continue + base_signatures.append(sig) - if args.test == 'relational': - relational_signatures = sycl_functions.create_relational_signatures() - create_tests(3000000, expanded_types, relational_signatures, args.variante, args.template, args.output, verifyResults) + # Update signatures based on the variants + extension = None + if base_signatures and args.variante == 'base': + test_signatures = base_signatures + elif half_signatures and args.variante == 'half': + test_signatures = half_signatures + test_id_offset = test_id_offset + 300000 + extension = "fp16" + elif double_signatures and args.variante == 'double': + test_signatures = double_signatures + test_id_offset = test_id_offset + 600000 + extension = "fp64" + else: + print("No %s overloads to generate for the test category" % args.variante) + sys.exit(1) - if args.test == 'float': - float_signatures = sycl_functions.create_float_signatures() - create_tests(4000000, expanded_types, float_signatures, args.variante, args.template, args.output, verifyResults) + output_files = [] + if len(test_signatures) != 0: + if not args.fragment_size: + output_files = [args.output_prefix + "." + args.ext] + else: + output_files = [args.output_prefix + "_" + str(i) + "." + args.ext for i in range(0, math.ceil(len(test_signatures) / args.fragment_size))] - if args.test == 'native': - native_signatures = sycl_functions.create_native_signatures() - create_tests(5000000, expanded_types, native_signatures, args.variante, args.template, args.output, verifyResults) + if args.print_output_files: + print(';'.join(output_files)) + # If output files are being printed we will not generate files. + return - if args.test == 'half': - half_signatures = sycl_functions.create_half_signatures() - create_tests(6000000, expanded_types, half_signatures, args.variante, args.template, args.output, verifyResults) + if not args.fragment_size: + create_tests(test_id_offset, expanded_types, test_signatures, args.variante, args.template, output_files[0], extension, verifyResults) + else: + for i in range(0, math.ceil(len(test_signatures) / args.fragment_size)): + fragment_start = i * args.fragment_size + fragment_end = fragment_start + args.fragment_size + current_offset = test_id_offset + fragment_start * 100 + create_tests(current_offset, expanded_types, test_signatures[fragment_start:fragment_end], args.template, output_files[i], extension, verifyResults) if __name__ == "__main__": main() diff --git a/tests/math_builtin_api/modules/test_generator.py b/tests/math_builtin_api/modules/test_generator.py index 0f5974a56..dc705f917 100644 --- a/tests/math_builtin_api/modules/test_generator.py +++ b/tests/math_builtin_api/modules/test_generator.py @@ -425,13 +425,14 @@ def bad_mutation(type1, type2, mutation): return True -def expand_signature(types, signature): +def expand_signature(types, signature, silent=False): """ Produces all possible overloads of a function signature. We produce the dict of typelists matched_typelists where each line (with the same index in typelists) contains possible set of individual types for function arguments and return type. """ - print("signature: " + str(signature.ret_type) + " " + signature.name + " " + str(signature.arg_types)) + if not silent: + print("signature: " + str(signature.ret_type) + " " + signature.name + " " + str(signature.arg_types)) exp_sig = [] @@ -513,11 +514,11 @@ def get_unique_signatures(signatures): return uniq_sig -def expand_signatures(types, signatures): +def expand_signatures(types, signatures, silent=False): ex_sig_list = [] for sig in signatures: - ex_sig_list.extend(expand_signature(types, sig)) + ex_sig_list.extend(expand_signature(types, sig, silent)) return get_unique_signatures(ex_sig_list)