blob: 7c82f315e4f11f74023829dff1be5a232ad5b255 [file] [log] [blame]
Jeremy Johnson0ecfa372022-06-30 14:27:56 +01001#!/usr/bin/env python3
Jeremy Johnson14087952024-02-29 16:13:10 +00002# Copyright (c) 2021-2024, ARM Limited.
Jeremy Johnson0ecfa372022-06-30 14:27:56 +01003# SPDX-License-Identifier: Apache-2.0
4"""Build conformance tests.
5
6Steps:
7- Specific input shapes (or tests) are specified and produced by using the
8 settings in the .json files.
9- Tests are selected to produce a good coverage.
10- Tests are run on the reference model to produce the correct output files.
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +010011- Tests are converted to JSON and/or copied and saved to desired output directory.
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010012"""
13import argparse
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +000014import copy
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010015import json
16import logging
17import multiprocessing as mp
18import os
Jeremy Johnsonfd8c8fe2023-10-23 11:55:38 +010019import re
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010020import shlex
21import shutil
22import subprocess
23from functools import partial
24from itertools import tee
25from pathlib import Path
26
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +010027import conformance.model_files as cmf
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010028from conformance.test_select import Operator
29from convert2conformance.convert2conformance import main as c2c_main
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +010030from convert2conformance.convert2conformance import OUTPUT_TYPE_DEFAULT
31from convert2conformance.convert2conformance import OUTPUT_TYPES
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010032from distutils.dir_util import copy_tree
Jeremy Johnsonfd8c8fe2023-10-23 11:55:38 +010033from serializer.tosa_serializer import TOSA_VERSION
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010034
35logging.basicConfig()
36logger = logging.getLogger("tosa_verif_conformance_generator")
37
38# Configuration for each TOSA profile
39PROFILE_OPS_INFO = {
Jeremy Johnson88588622022-07-12 16:42:29 +010040 "tosa-bi": {
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010041 "operator_test_params": "tosa_base_profile_ops_info.json",
42 "framework_tests": "tosa_base_profile_framework_ops_info.json",
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +010043 },
44 "tosa-mi": {
45 # Note: This is just the extra tests not in the base profile!
46 "operator_test_params": "tosa_main_profile_ops_info.json",
47 "framework_tests": "tosa_main_profile_framework_ops_info.json",
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +010048 },
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010049}
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +010050PROFILES_ALL = "all"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010051
Jeremy Johnson93d43902022-09-27 12:26:14 +010052DEFAULT_SEED = 42
53
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +000054# When there is a dictionary of generator argument lists (groups) only the
55# standard group will have negative tests generated for it
56STANDARD_GENERATOR_GROUP = "standard"
57
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +010058TEST_VERSION_LATEST = "latest"
59TEST_VERSION_V0_60_0 = "v0.60.0"
60TEST_VERSIONS = (TEST_VERSION_LATEST, TEST_VERSION_V0_60_0)
Jeremy Johnsonfd8c8fe2023-10-23 11:55:38 +010061REGEX_VERSION = re.compile(r"v([0-9]+)\.([0-9]+)\.([0-9]+)")
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +010062
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010063
64class GenConformanceError(Exception):
65 """Generation error reporting exception."""
66
67 pass
68
69
70def _run_sh_command(args, cwd, full_cmd):
71 """Run an external command and capture stdout/stderr."""
72 # Quote the command line for printing
Jeremy Johnsonaf090182024-02-13 18:25:39 +000073 try:
74 full_cmd_esc = [shlex.quote(x) for x in full_cmd]
75 except Exception as e:
76 raise Exception(f"Error quoting command: {e}")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010077 if args.capture_output:
Jeremy Johnsonaf090182024-02-13 18:25:39 +000078 logger.info(f"Command: {full_cmd_esc}")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010079
80 rc = subprocess.run(
81 full_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
82 )
83
84 if args.capture_output:
85 stdout = rc.stdout.decode("utf-8")
Jeremy Johnsonaf090182024-02-13 18:25:39 +000086 logger.info(f"stdout: \n{stdout}")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +010087 if rc.returncode != 0:
88
89 raise Exception(
90 "Error running command: {}.\n{}".format(
91 " ".join(full_cmd_esc), rc.stderr.decode("utf-8")
92 )
93 )
94 return (rc.stdout, rc.stderr)
95
96
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +000097def build_op_tests(
Jeremy Johnson1271c442023-09-05 11:39:26 +010098 args,
99 test_type,
100 profile,
101 operator,
102 group,
103 gen_args_list,
104 gen_neg_dim_range,
105 supports=[],
Jeremy Johnson1d5dded2024-03-06 10:11:10 +0000106 gen_filter=None,
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000107 selector_info=None,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000108):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100109 """Build tests for a given operator.
110
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000111 Builds a set of tests based on the given generator arguments list
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100112
113 Returns operator output directory
114 """
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100115 build_tests_cmd = "tosa_verif_build_tests"
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000116 op_build_dir = args.build_dir / profile / group
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100117
Jeremy Johnson1d5dded2024-03-06 10:11:10 +0000118 if gen_filter is None:
119 gen_filter = f"^{operator}$"
120
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000121 build_cmd_base = [
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100122 build_tests_cmd,
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100123 "--generate-lib-path",
124 str(args.generate_lib_path),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100125 "--filter",
Jeremy Johnson1d5dded2024-03-06 10:11:10 +0000126 gen_filter,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100127 "-o",
128 str(op_build_dir),
129 "--seed",
Jeremy Johnson93d43902022-09-27 12:26:14 +0100130 str(args.random_seed),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100131 ]
132
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000133 if args.verbosity:
134 build_cmd_base.append("-" + ("v" * args.verbosity))
135
136 if args.tests_list_file is not None:
137 build_cmd_base.append("--list-tests")
138
Jeremy Johnson1271c442023-09-05 11:39:26 +0100139 if "lazy_data_gen" in supports and args.lazy_data_generation:
140 build_cmd_base.append("--lazy-data-generation")
141
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000142 if "generator_select" in supports:
143 if selector_info is None:
144 logger.error(
145 "build_op_tests error: generator_select mode without selector information"
146 )
147 raise (GenConformanceError())
148 selector_config, selector_name = selector_info
149 build_cmd_base.extend(
150 [
151 "--test-selection-config",
152 str(selector_config),
153 "--test-selection-criteria",
154 selector_name,
155 ]
156 )
157
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000158 build_cmds_list = []
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100159
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000160 if test_type in ["positive", "both"]:
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100161 # Append extra parameters and run test generator for each set of parameters.
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000162 for arglist in gen_args_list:
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000163 build_cmd_pos_test = build_cmd_base.copy()
164 build_cmd_pos_test.extend(["--test-type", "positive"])
165 build_cmd_pos_test.extend(arglist)
166 build_cmds_list.append(build_cmd_pos_test)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100167
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000168 if test_type in ["negative", "both"]:
Jeremy Johnson35396f22023-01-04 17:05:25 +0000169 # Get target-dtypes options and any filter string to limit tests
Jeremy Johnson93d43902022-09-27 12:26:14 +0100170 target_dtypes_args = []
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000171 for arglist in gen_args_list:
Jeremy Johnson93d43902022-09-27 12:26:14 +0100172 idx = 0
173 while idx < len(arglist):
174 if arglist[idx] == "--target-dtype":
175 if arglist[idx + 1] not in target_dtypes_args:
176 target_dtypes_args.extend(arglist[idx : idx + 2])
177 idx += 1 # skip over option (and then argument below)
178 idx += 1
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000179 build_cmd_neg_test = build_cmd_base.copy()
180 build_cmd_neg_test.extend(["--test-type", "negative"])
Jeremy Johnson93d43902022-09-27 12:26:14 +0100181 # Limit sizes of negative tests
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000182 dim_range = gen_neg_dim_range if gen_neg_dim_range is not None else "1,16"
183
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000184 build_cmd_neg_test.extend(["--tensor-dim-range", dim_range])
185 build_cmd_neg_test.extend(target_dtypes_args)
186 build_cmds_list.append(build_cmd_neg_test)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100187
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000188 logger.info(f"Creating {operator} tests in {len(build_cmds_list)} batch(es)")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100189 error = False
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000190 for i, cmd in enumerate(build_cmds_list):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100191 try:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000192 raw_stdout, _ = _run_sh_command(args, args.ref_model_path.parent, cmd)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100193 logger.info(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000194 f"{operator} test batch {(i+1)}/{len(build_cmds_list)} created successfully"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100195 )
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000196
197 if args.tests_list_file is not None:
198 with args.tests_list_file.open("a") as fd:
199 fd.write(raw_stdout.decode("utf-8"))
200
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100201 except Exception as e:
202 logger.error(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000203 f"{operator} test batch {(i+1)}/{len(build_cmds_list)} unsuccessful, skipping"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100204 )
205 logger.error(f" build_op_tests error: {e} ")
206 error = True
207 if error:
208 raise (GenConformanceError())
209
210 return op_build_dir
211
212
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000213def _check_to_include_test(test_type, test_name):
214 """Check test name for inclusion based on test_type, returns True to include."""
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100215
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000216 if test_type == "both":
217 return True
218 else:
219 error_test = "_ERRORIF_" in test_name
220 return (error_test and test_type == "negative") or (
221 not error_test and test_type == "positive"
222 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100223
224
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000225def _get_all_tests_list(test_type, test_root_dir, operator):
226 """Create test list from tests in the test_dir based on chosen type."""
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100227 test_dir = test_root_dir / operator
228 if not test_dir.is_dir():
229 # Tests are split into multiple dirs, for example: conv2d_1x1, conv2d_3x3
230 test_dir = test_root_dir
231 directories = [
232 tdir for tdir in test_dir.glob("*") if tdir.name.startswith(operator)
233 ]
234 else:
235 directories = [test_dir]
236
237 tests = []
238 for tdir in directories:
239 tests.extend(
240 [
241 test
242 for test in tdir.glob("*")
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000243 if _check_to_include_test(test_type, test.name)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100244 ]
245 )
246 return tests
247
248
Jeremy Johnson1271c442023-09-05 11:39:26 +0100249def generate_results(args, profile, operator, op_build_dir, supports=[], tests=None):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100250 """Run tests on reference model and save result to the test directory."""
Jeremy Johnson1271c442023-09-05 11:39:26 +0100251 if "lazy_data_gen" in supports and args.lazy_data_generation:
252 logger.info("Skipping running tests due to lazy data gen")
253 return
254
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100255 num_cores = args.num_cores
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100256
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100257 # Use the test runner
258 ref_cmd_base = [
259 "tosa_verif_run_tests",
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100260 "--ref-model-path",
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100261 str(args.ref_model_path),
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100262 "--schema-path",
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100263 str(args.schema_path),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100264 "-j",
265 str(num_cores),
266 "-v",
267 "-t",
268 ]
269 ref_cmds = []
270
271 if not tests:
272 # Do not need to run ERRORIF tests as they don't have result files
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000273 tests = _get_all_tests_list("positive", op_build_dir, operator)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100274
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000275 skipped = 0
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100276 for test in tests:
Jeremy Johnsone2b5e872023-09-14 17:02:09 +0100277 desc = test / "desc.json"
278 with desc.open("r") as fd:
279 test_desc = json.load(fd)
280 if "meta" in test_desc and "compliance" in test_desc["meta"]:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000281 skipped += 1
282 logger.debug(
Jeremy Johnsone2b5e872023-09-14 17:02:09 +0100283 f"Skipping generating results for new compliance test - {str(test)}"
284 )
285 continue
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100286 ref_cmd = ref_cmd_base.copy()
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100287 ref_cmd.append(str(test.absolute()))
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100288 ref_cmds.append(ref_cmd)
289
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000290 if skipped:
291 logger.info(f"{skipped} new compliance tests skipped for results generation")
292
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100293 fail_string = "UNEXPECTED_FAILURE"
294 failed_counter = 0
295
296 job_pool = mp.Pool(args.num_cores)
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100297 sh_partial = partial(_run_sh_command, args, args.ref_model_path.parent)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100298 pool_results = job_pool.map(sh_partial, ref_cmds)
299 job_pool.close()
300 job_pool.join()
301
302 # Use captured output for run_sh_command to work out if test passed.
303 for i, rc in enumerate(pool_results):
304 if fail_string in str(rc[0]):
305 logger.error(f"Test {i+1}/{len(ref_cmds)}: {ref_cmds[i][-1]} failed.")
306 failed_counter += 1
307 else:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000308 logger.debug(f"Test {i+1}/{len(ref_cmds)}: {ref_cmds[i][-1]} passed.")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100309
310 logger.info(f"{len(ref_cmds)-failed_counter}/{len(ref_cmds)} tests passed")
311 logger.info("Ran tests on model and saved results of passing tests")
312
313
314def convert_tests(
315 args,
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000316 test_type,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100317 profile,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100318 operator,
319 op_build_dir,
320 output_dir,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100321 op_profiles_list,
Jeremy Johnson1271c442023-09-05 11:39:26 +0100322 supports=[],
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100323 tests=None,
324 group=None,
325 trim_op_subdir=False,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000326 tags=None,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100327):
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100328 """Convert/copy tests to output directory."""
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100329 if group:
330 output_dir = output_dir / group
331
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100332 c2c_args_base = ["--strict"]
333 c2c_args_base.extend(["--schema-path", str(args.schema_path)])
334 c2c_args_base.extend(["--flatc-path", str(args.flatc_path)])
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100335 c2c_args_base.extend(["--output-type", args.output_type])
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100336 # This op maybe in more than one profile - e.g. tosa_bi and tosa_mi
337 # even if we are only producing tests for tosa_mi
338 for op_profile in op_profiles_list:
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000339 c2c_args_base.extend(["--profile", op_profile])
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000340 if tags is not None:
341 for tag in tags:
342 c2c_args_base.extend(["--tag", tag])
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100343 if args.framework_schema:
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000344 c2c_args_base.extend(["--framework-schema", str(args.framework_schema)])
Jeremy Johnson1271c442023-09-05 11:39:26 +0100345 if "lazy_data_gen" in supports and args.lazy_data_generation:
346 c2c_args_base.append("--lazy-data-generation")
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000347 c2c_args_base.append("--output-directory")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100348
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000349 c2c_args_list = []
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100350
351 if not tests:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000352 tests = _get_all_tests_list(test_type, op_build_dir, operator)
353 logger.info(f"Converting all {profile} profile tests of type {test_type}")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100354
355 # Controls if we copy the tests in their operator sub-directory or not
356 output_dir_relative_pos = -1 if trim_op_subdir else -2
357 for test in tests:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000358 logger.debug(f"Test chosen: {test}")
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000359 c2c_args = c2c_args_base.copy()
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100360 full_output_directory = output_dir / test.relative_to(
361 *test.parts[:output_dir_relative_pos]
362 )
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000363 c2c_args.append(str(full_output_directory))
364 c2c_args.append(str(test))
365 c2c_args_list.append(c2c_args)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100366
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000367 if len(c2c_args_list) == 0:
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000368 logger.error(
369 f"No tests found for {operator}. Nothing to convert in {op_build_dir}"
370 )
371 raise (GenConformanceError())
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100372
373 job_pool = mp.Pool(args.num_cores)
374
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000375 pool_results = job_pool.map(c2c_main, c2c_args_list)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100376 job_pool.close()
377 job_pool.join()
378
379 failed_counter = 0
380 for i, result in enumerate(pool_results):
381 if result != 0:
382 logger.error(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000383 f"test {i+1}/{len(c2c_args_list)}: {c2c_args_list[i][-1]} failed to convert."
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100384 )
385 failed_counter += 1
386 else:
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000387 logger.debug(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000388 f"test {i+1}/{len(c2c_args_list)}: {c2c_args_list[i][-1]} converted"
389 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100390 logger.info(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000391 f"{len(c2c_args_list)-failed_counter}/{len(c2c_args_list)} tests successfully converted"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100392 )
393
394 if failed_counter > 0:
395 logger.error(f"Stopping due to {failed_counter} test conversion errors")
396 raise (GenConformanceError())
397
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100398 logger.info("Converted/copied tests and saved to output directory")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100399
400 return output_dir
401
402
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100403def get_op_tests_selection(
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000404 args,
405 profile,
406 operator,
407 op_build_dir,
408 selection_config,
409 negative=False,
410 ignore_missing=False,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100411):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100412 """Use test picker to get subsection of tests generated."""
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000413 # Need a full copy of the config as the selector updates it
414 config = copy.deepcopy(selection_config)
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100415 logger.info("Choosing {} tests".format(("negative" if negative else "positive")))
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100416 try:
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100417 op = Operator.registry[operator](
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000418 op_build_dir, config, negative=negative, ignore_missing=ignore_missing
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100419 )
420 except KeyError:
421 logger.error(f"{operator} operator is not supported by test_select")
422 raise (GenConformanceError())
423
424 return op.select_tests()
425
426
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100427def check_op_tests(args, profile, operator, output_dir):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100428 """Move test folders than contain files larger than 30MB to new directory."""
429 destination_dir = str(args.output_dir) + "_large_files"
430
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000431 # Include all tests - both positive and negative
432 tests = _get_all_tests_list("both", output_dir, operator)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100433 if not tests:
434 logger.error(
435 f"Couldn't find any tests to size check for {operator} in {output_dir}"
436 )
437 raise (GenConformanceError())
438
439 for tdir in tests:
440 move_dir = False
441 test_files = [file for file in tdir.glob("*")]
442 for file in test_files:
443 file_size = os.stat(file).st_size / 1024**2
444 if file_size > 30:
445 move_dir = True
446
447 if move_dir:
448 move_destination = destination_dir / tdir.relative_to(output_dir)
449 logger.warning(
450 f"{tdir.relative_to(output_dir)} contains files that are too large (>30MB), test moved to new folder: {destination_dir}"
451 )
452
453 if move_destination.is_dir():
454 logger.warning(
455 f"{move_destination} directory already exists, deleting existing."
456 )
457 shutil.rmtree(str(move_destination))
458 shutil.move(str(tdir), move_destination)
459
460
461def copy_rename_framework_tests(args, operator, test_picks):
462 """Copy framework tests into new folder and rename them if needed.
463
464 The tests are renamed to match the framework operator names if an
465 alternate name has been used instead.
466 """
467 framework_tests_dir = args.framework_tests_dir
468 new_tests_dir = args.build_dir / "frameworks" / operator
469 os.makedirs(new_tests_dir, exist_ok=True)
470
471 # Get the framework tests operator name
472 if "alternate_names" in test_picks[operator]:
473 alternate_names = test_picks[operator]["alternate_names"]
474 else:
475 alternate_names = [operator]
476
477 # Get the alternate named test directories for the operator
478 for alt_name in alternate_names:
479 test_prefix = f"test_{alt_name}"
480 test_dirs = list(framework_tests_dir.glob(f"{test_prefix}_*"))
481
482 # Copy tests to new directory and rename to match framework operator names
483 # - if there is just 1 alternate name, replace the full test prefix
484 # test_add_... -> add_...
485 # - if there are multiple alternate names, just replace the "test"
486 # test_concatv2_... -> concatenation_concatv2_...
487 old_prefix = test_prefix if len(alternate_names) == 1 else "test"
488
489 for tdir in test_dirs:
490 new_test_name = tdir.name.replace(old_prefix, operator)
491 copy_destination = new_tests_dir / new_test_name
492 logger.debug(f"copying test folder {tdir} to {copy_destination}")
493 copy_tree(str(tdir), str(copy_destination))
494
495 logger.info(f"Copied and renamed {len(test_dirs)} framework test folders")
496 return new_tests_dir.parent
497
498
499def get_framework_tests_selection(args, operator, test_picks, op_build_dir):
500 """Get the list of pre-chosen tests with relative paths."""
501 try:
502 tests = test_picks[operator]["tests"]
503 except KeyError:
504 logger.error(f"Framework test selection not defined for {operator} operator")
505 raise (GenConformanceError())
506
507 test_paths = [op_build_dir / operator / test for test in tests]
508 return test_paths
509
510
511def parse_args(argv=None):
512 """Parse the arguments."""
513 parser = argparse.ArgumentParser()
Jeremy Johnson88588622022-07-12 16:42:29 +0100514 profiles = list(PROFILE_OPS_INFO.keys())
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100515 profiles.append(PROFILES_ALL)
Jeremy Johnson88588622022-07-12 16:42:29 +0100516 parser.add_argument(
517 "--profile",
518 dest="profile",
519 choices=profiles,
520 default=profiles[0],
521 type=str,
522 help=f"TOSA profile (default is {profiles[0]})",
523 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100524 parser.add_argument(
525 "--operators",
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100526 "--op",
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100527 type=str,
528 nargs="*",
529 help="The operator(s) to create tests for, if not supplied all tests will be created",
530 )
531 parser.add_argument(
Jeremy Johnson88588622022-07-12 16:42:29 +0100532 "--unit-tests",
533 dest="unit_tests",
534 choices=["operator", "framework", "both"],
535 default="operator",
536 type=str,
537 help="Which unit tests are produced (default is operator)",
538 )
539 parser.add_argument(
540 "--test-type",
541 dest="test_type",
542 choices=["positive", "negative", "both"],
543 default="both",
544 type=str,
545 help="Type of tests produced (default is both)",
546 )
547 parser.add_argument(
Jeremy Johnson1271c442023-09-05 11:39:26 +0100548 "--lazy-data-generation",
549 action="store_true",
550 help="Enable lazy data generation (only for tosa-mi)",
551 )
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100552 rm_group = parser.add_mutually_exclusive_group(required=True)
553 rm_group.add_argument(
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100554 "--ref-model-directory",
555 dest="ref_model_dir",
556 type=Path,
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100557 help="(DEPRECATED - use ref-model-path) Reference Model directory - with build directory",
558 )
559 rm_group.add_argument(
560 "--ref-model-path",
561 dest="ref_model_path",
562 type=Path,
563 help="Path to TOSA reference model executable",
564 )
565 parser.add_argument(
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100566 "--generate-lib-path",
567 dest="generate_lib_path",
568 type=Path,
569 help=(
570 "Path to TOSA generate library. Defaults to "
571 "the library in the directory of `ref-model-path`"
572 ),
573 )
574 parser.add_argument(
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100575 "--schema-path",
576 "--operator-fbs",
577 dest="schema_path",
578 type=Path,
579 help=(
580 "Path to TOSA reference model flat buffer schema. Defaults to "
581 f"`{cmf.DEFAULT_REF_MODEL_SCHEMA_PATH}` in parents parent directory of `ref-model-path`"
582 ),
583 )
584 parser.add_argument(
585 "--flatc-path",
586 dest="flatc_path",
587 type=Path,
588 help=(
589 "Path to flatc executable. Defaults to "
590 f"`{cmf.DEFAULT_REF_MODEL_BUILD_FLATC_PATH}` in parent directory of `ref-model-path`"
591 ),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100592 )
Jeremy Johnson88588622022-07-12 16:42:29 +0100593 parser.add_argument(
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100594 "--test-version",
595 dest="test_version",
596 choices=TEST_VERSIONS,
597 default=TEST_VERSION_LATEST,
598 help=f"Version of the tests to produce (default is {TEST_VERSION_LATEST})",
599 )
600 parser.add_argument(
601 "--output-type",
602 dest="output_type",
603 choices=OUTPUT_TYPES,
604 default=OUTPUT_TYPE_DEFAULT,
605 help=f"Output file type produced (default is {OUTPUT_TYPE_DEFAULT})",
606 )
607 parser.add_argument(
Jeremy Johnson93d43902022-09-27 12:26:14 +0100608 "--seed",
609 dest="random_seed",
610 default=DEFAULT_SEED,
611 type=int,
612 help="Random test seed",
613 )
614 parser.add_argument(
Jeremy Johnson88588622022-07-12 16:42:29 +0100615 "--framework-tests-directory",
616 dest="framework_tests_dir",
617 type=Path,
618 default=Path.cwd() / "tests",
619 help="The pre-built framework tests directory (default is tests)",
620 )
621 parser.add_argument(
622 "--framework-schema",
623 dest="framework_schema",
624 type=Path,
625 help="Framework flatbuffers schema needed to convert framework models",
626 )
627 parser.add_argument(
628 "--build-directory",
629 dest="build_dir",
630 type=Path,
631 default=Path.cwd() / "conformance_build",
632 help="Temporary build directory for files created during this process (default is conformance_build)",
633 )
634 parser.add_argument(
635 "--output-directory",
636 dest="output_dir",
637 type=Path,
638 default=Path.cwd() / "conformance",
639 help="Output directory (default is conformance)",
640 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100641 script_dir = Path(__file__).parent.absolute()
642 parser.add_argument(
643 "--test-param-json-directory",
644 dest="param_json_dir",
645 type=Path,
646 default=script_dir,
Jeremy Johnson88588622022-07-12 16:42:29 +0100647 help=f"Test parameters (ops info) JSON file directory (default is {script_dir})",
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100648 )
649 parser.add_argument(
650 "--convert-all-tests",
651 action="store_true",
652 help="Converts all tests instead of those picked by test_select",
653 )
654 parser.add_argument(
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000655 "--list-tests-to-file",
656 dest="tests_list_file",
657 type=Path,
658 help="Lists out the tests to be generated to a file instead of generating them",
659 )
660 parser.add_argument(
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100661 "--keep-large-files",
662 action="store_true",
663 help="Keeps tests that contain files larger than 30MB in output directory",
664 )
665 parser.add_argument(
666 "--capture-output",
667 action="store_true",
668 help="Prints output of running sh commands",
669 )
670 parser.add_argument(
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100671 "-j",
672 dest="num_cores",
673 type=int,
674 default=6,
675 help="Number of simultaneous jobs to split the tasks into for multiprocessing",
676 )
677 parser.add_argument(
678 "-v",
679 dest="verbosity",
680 action="count",
681 default=0,
682 help="Verbosity (can be used multiple times for more details)",
683 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100684 args = parser.parse_args(argv)
685
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000686 if args.ref_model_dir is not None:
687 # Assume the ref model exe path based on the ref model directory
688 args.ref_model_path = cmf.find_tosa_file(
689 cmf.TosaFileType.REF_MODEL, args.ref_model_dir, False
690 )
691 if not args.ref_model_path.is_file():
692 logger.error(
693 f"Missing reference model binary (--ref-model-path): {args.ref_model_path}"
694 )
695 return None
696 args.ref_model_path = args.ref_model_path.absolute()
697
698 if args.generate_lib_path is None:
699 args.generate_lib_path = cmf.find_tosa_file(
700 cmf.TosaFileType.GENERATE_LIBRARY, args.ref_model_path
701 )
702 if not args.generate_lib_path.is_file():
703 logger.error(
704 f"Missing TOSA generate data library (--generate-lib-path): {args.generate_lib_path}"
705 )
706 return None
707 args.generate_lib_path = args.generate_lib_path.absolute()
708
709 if args.schema_path is None:
710 args.schema_path = cmf.find_tosa_file(
711 cmf.TosaFileType.SCHEMA, args.ref_model_path
712 )
713 if not args.schema_path.is_file():
714 logger.error(
715 f"Missing reference model schema (--schema-path): {args.schema_path}"
716 )
717 return None
718 args.schema_path = args.schema_path.absolute()
719
720 if args.flatc_path is None:
721 args.flatc_path = cmf.find_tosa_file(
722 cmf.TosaFileType.FLATC, args.ref_model_path
723 )
724 if not args.flatc_path.is_file():
725 logger.error(f"Missing flatc binary (--flatc-path): {args.flatc_path}")
726 return None
727 args.flatc_path = args.flatc_path.absolute()
728
729 args.param_json_dir = args.param_json_dir.absolute()
730
731 if args.unit_tests in ["framework", "both"]:
732 logger.warning(
733 "DEPRECATION - Framework tests are not part of TOSA conformance testing"
734 )
735 if not args.framework_schema:
736 logger.error(
737 "Need to supply location of Framework flatbuffers schema via --framework-schema"
738 )
739 return None
740 if not args.framework_tests_dir.is_dir():
741 logger.error(
742 f"Missing or invalid framework tests directory: {args.framework_tests_dir}"
743 )
744 return None
745
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100746 return args
747
748
Jeremy Johnsonfd8c8fe2023-10-23 11:55:38 +0100749def in_version(test_version, gen_dict):
750 """Check if the selected test_version is compatible with the tests."""
751
752 def version_string_to_numbers(verstr):
753 # Turn the "vM.mm.pp" string into Major, Minor, Patch versions
754 if verstr == TEST_VERSION_LATEST:
755 return (TOSA_VERSION[0], TOSA_VERSION[1], TOSA_VERSION[2])
756 else:
757 match = re.match(REGEX_VERSION, verstr)
758 if match is None:
759 raise KeyError(f"Invalid version string {verstr}")
760 return (int(v) for v in match.groups())
761
762 if "from_version" in gen_dict:
763 selected_version = version_string_to_numbers(test_version)
764 from_version = version_string_to_numbers(gen_dict["from_version"])
765
766 # Check the Major version is compatible, then Minor, and lastly Patch
767 # Unless the versions match, we can exit early due to obvious precedence
768 for sel, fro in zip(selected_version, from_version):
769 if sel < fro:
770 # From version is later than selected version
771 return False
772 elif sel > fro:
773 # From version is earlier than selected version
774 return True
775 # If we get here, the version numbers match exactly
776 return True
777 else:
778 # No specific version info
779 return True
780
781
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000782def _get_log_level(verbosity):
783 loglevels = (logging.WARNING, logging.INFO, logging.DEBUG)
784 verbosity = max(verbosity, 0)
785 return loglevels[min(verbosity, len(loglevels) - 1)]
786
787
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100788def main():
789 args = parse_args()
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000790 if args is None:
791 # Argument processing error
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100792 return 2
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100793
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000794 loglevel = _get_log_level(args.verbosity)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100795 logger.setLevel(loglevel)
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000796 # Set other loggers to a quieter level
797 loglevel = _get_log_level(args.verbosity - 1)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100798 logging.getLogger("test_select").setLevel(loglevel)
799 logging.getLogger("convert2conformance").setLevel(loglevel)
800
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100801 print(f"Output directory: {args.output_dir}")
802
Jeremy Johnson93d43902022-09-27 12:26:14 +0100803 if args.random_seed != DEFAULT_SEED:
804 logger.warning(
805 "Random test seed changed from default, tests will not match official conformance"
806 )
807
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100808 args.build_dir = args.build_dir.resolve()
809 logger.debug(f"Creating build directory: {args.build_dir}")
810 args.build_dir.mkdir(parents=True, exist_ok=True)
811
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000812 if args.tests_list_file is not None:
813 # Try creating tests list file
814 with args.tests_list_file.open("w") as fd:
815 fd.write("")
816
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100817 # TODO: For tosa-mi should really generate tosa-bi profile as well
818 # - for now leave it as subset instead of as superset (for testing)
819 if args.profile == PROFILES_ALL:
820 profiles = list(PROFILE_OPS_INFO.keys())
821 else:
822 profiles = [args.profile]
823
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100824 try:
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100825 for profile in profiles:
826 print(f"Creating conformance tests for TOSA {profile} profile")
827 # Framework unit tests
828 if args.unit_tests in ["framework", "both"]:
829 logger.debug("Creating FRAMEWORK unit tests")
830 test_picks_file = (
831 args.param_json_dir / PROFILE_OPS_INFO[profile]["framework_tests"]
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100832 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100833 try:
834 with open(test_picks_file, "r") as fd:
835 test_picks = json.load(fd)
836 except Exception as e:
837 logger.error(
838 f"Couldn't load framework tests info - {test_picks_file}: {e}"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100839 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100840 return 1
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100841
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100842 operators = args.operators
843 if not operators:
844 # Create tests for all the operators
845 operators = list(test_picks.keys())
846
847 root_output_dir = (
848 args.output_dir / "frameworks" / "tflite" / "operators"
849 )
850 for op in operators:
851 logger.info(f"FRAMEWORK OP: {op}")
852 if op not in test_picks:
853 logger.warning(
854 f"Framework op {op} not found in {test_picks_file} - skipping"
855 )
856 continue
857
858 op_profiles_list = test_picks[op]["profile"]
859 if (
860 args.profile != PROFILES_ALL
861 and args.profile not in op_profiles_list
862 ):
863 # Skip this operator as not part of the profile chosen
864 logger.debug(f"Skipping {op} as not part of {args.profile}")
865 continue
866
867 logger.debug(f"Copying and renaming {op}")
868 framework_test_dir = copy_rename_framework_tests(
869 args, op, test_picks
870 )
871
872 if args.convert_all_tests:
873 logger.debug("Running and converting all framework tests")
874 framework_tests = None # Don't select any
875 else:
876 logger.debug("Running and converting selected framework tests")
877 framework_tests = get_framework_tests_selection(
878 args, op, test_picks, framework_test_dir
879 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100880 convert_tests(
881 args,
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000882 "positive",
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100883 profile,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100884 op,
885 framework_test_dir,
886 root_output_dir,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100887 op_profiles_list,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100888 tests=framework_tests,
889 trim_op_subdir=True,
890 )
891
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100892 # Operator unit tests
893 if args.unit_tests in ["operator", "both"]:
894 logger.debug("Creating OPERATOR unit tests")
895 test_params_file = (
896 args.param_json_dir
897 / PROFILE_OPS_INFO[profile]["operator_test_params"]
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100898 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100899 try:
900 with open(test_params_file, "r") as fd:
901 test_params = json.load(fd)
902 except Exception as e:
903 logger.error(
904 f"Couldn't load operator test params - {test_params_file}: {e}"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100905 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100906 return 1
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000907 logger.debug(f"Using config file: {str(test_params_file)}")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100908
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100909 operators = args.operators
910 if not operators:
911 # Create tests for all the operators
912 operators = list(test_params.keys())
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100913
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100914 for op in operators:
915 logger.info(f"OPERATOR: {op}")
916 if op not in test_params:
917 logger.warning(
918 f"{op} operator parameters not found in {test_params_file} - skipping"
919 )
920 continue
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100921
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100922 op_profiles_list = test_params[op]["profile"]
923 if (
924 args.profile != PROFILES_ALL
925 and args.profile not in op_profiles_list
926 ):
927 # Skip this operator as not part of the profile chosen
928 logger.debug(f"Skipping {op} as not part of {args.profile}")
929 continue
930
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100931 operator_group = test_params[op]["group"]
932 root_output_dir = args.output_dir / "operators"
Jeremy Johnson1271c442023-09-05 11:39:26 +0100933 supports = (
934 test_params[op]["support_for"]
935 if "support_for" in test_params[op]
936 else []
937 )
Jeremy Johnson1d5dded2024-03-06 10:11:10 +0000938 gen_filter = (
939 test_params[op]["gen_filter"]
940 if "gen_filter" in test_params[op]
941 else None
942 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000943
944 # Iterate through the generation groups selecting tests from each
945 for gen_name, gen_dict in test_params[op]["generation"].items():
Jeremy Johnsonfd8c8fe2023-10-23 11:55:38 +0100946
947 if not in_version(args.test_version, gen_dict):
948 logger.warning(
949 f"{op} [{gen_name}] is not in {args.test_version} - skipping"
950 )
951 continue
952
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000953 no_neg_tests = (
954 "no_negative_tests" in gen_dict
955 and gen_dict["no_negative_tests"] == "true"
956 )
957
958 if no_neg_tests:
959 if args.test_type == "negative":
960 logger.info(
961 f"No negative tests for {op} / generation group {gen_name}"
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100962 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000963 continue
964 # Only produce positive tests
965 test_type = "positive"
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100966 else:
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000967 test_type = args.test_type
968
969 gen_neg_dim_range = (
970 gen_dict["negative_dim_range"]
971 if "negative_dim_range" in gen_dict
972 else None
973 )
974
Jeremy Johnson0c716862023-04-13 17:18:19 +0100975 # Work out which selection criteria we are using
976 if "selector" in gen_dict:
977 selector_name = gen_dict["selector"]
978 if selector_name not in test_params[op]["selection"]:
979 logger.warn(
980 f"Could not find {selector_name} in selection dict for {op} - using default"
981 )
982 selector_name = "default"
983 else:
984 selector_name = "default"
985 if selector_name not in test_params[op]["selection"]:
986 logger.error(
987 f"Could not find {selector_name} in selection dict for {op}"
988 )
989 raise (GenConformanceError())
990
Jeremy Johnsonaf090182024-02-13 18:25:39 +0000991 op_build_dir = build_op_tests(
992 args,
993 test_type,
994 profile,
995 op,
996 gen_name,
997 gen_dict["generator_args"],
998 gen_neg_dim_range,
999 supports=supports,
1000 gen_filter=gen_filter,
1001 selector_info=(test_params_file, selector_name),
1002 )
Jeremy Johnson0c716862023-04-13 17:18:19 +01001003
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001004 if args.tests_list_file is not None:
1005 logger.info("Tests list file extended")
1006 continue
1007
1008 if args.convert_all_tests or "generator_select" in supports:
1009 if test_type in ["positive", "both"]:
1010 logger.info(f"Running and converting all {op} tests")
1011 generate_results(
1012 args, profile, op, op_build_dir, supports=supports
1013 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001014 operator_test_list = None
1015 else:
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001016 logger.info(
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001017 f"Running and converting selection of {op} tests"
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +01001018 )
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001019 # Selection criteria
1020 selection_config = test_params[op]["selection"][
1021 selector_name
1022 ]
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001023 if test_type in ["positive", "both"]:
Jeremy Johnson76c6a552023-09-11 09:30:02 +01001024 if (
1025 "all" in selection_config
1026 and selection_config["all"] == "true"
1027 ):
1028 # Just get all the positive tests
1029 tests_gen, tests_gen2 = tee(
1030 _get_all_tests_list(
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001031 "positive",
Jeremy Johnson76c6a552023-09-11 09:30:02 +01001032 op_build_dir,
1033 op,
Jeremy Johnson76c6a552023-09-11 09:30:02 +01001034 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001035 )
Jeremy Johnson76c6a552023-09-11 09:30:02 +01001036 else:
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001037 ignore_missing = (
1038 gen_name != STANDARD_GENERATOR_GROUP
1039 )
1040
Jeremy Johnson76c6a552023-09-11 09:30:02 +01001041 # Get a selection of positive tests
1042 tests_gen, tests_gen2 = tee(
1043 get_op_tests_selection(
1044 args,
1045 profile,
1046 op,
1047 op_build_dir,
1048 selection_config,
1049 ignore_missing=ignore_missing,
1050 )
1051 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001052 generate_results(
Jeremy Johnson1271c442023-09-05 11:39:26 +01001053 args,
1054 profile,
1055 op,
1056 op_build_dir,
1057 supports=supports,
1058 tests=tests_gen,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001059 )
1060 operator_test_list = list(tests_gen2)
1061 else:
1062 operator_test_list = []
1063 if test_type in ["negative", "both"]:
1064 operator_test_list.extend(
1065 get_op_tests_selection(
1066 args,
1067 profile,
1068 op,
1069 op_build_dir,
1070 selection_config,
1071 negative=True,
1072 )
1073 )
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001074
1075 tags = (
1076 [gen_name] if gen_name != STANDARD_GENERATOR_GROUP else None
1077 )
1078
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001079 output_dir = convert_tests(
1080 args,
Jeremy Johnsonaf090182024-02-13 18:25:39 +00001081 test_type,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001082 profile,
1083 op,
1084 op_build_dir,
1085 root_output_dir,
1086 op_profiles_list,
Jeremy Johnson1271c442023-09-05 11:39:26 +01001087 supports=supports,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001088 tests=operator_test_list,
1089 group=operator_group,
1090 tags=tags,
1091 )
1092 if not args.keep_large_files:
1093 check_op_tests(args, profile, op, output_dir)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +01001094 except GenConformanceError:
1095 return 1
1096
1097 return 0
1098
1099
1100if __name__ == "__main__":
1101 exit(main())