blob: 987bef52ddaf66b5436ed1e290db8242afb169fa [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
73 full_cmd_esc = [shlex.quote(x) for x in full_cmd]
74 if args.capture_output:
75 logger.debug(f"Command: {full_cmd_esc}")
76
77 rc = subprocess.run(
78 full_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
79 )
80
81 if args.capture_output:
82 stdout = rc.stdout.decode("utf-8")
83 logger.debug(f"stdout: \n{stdout}")
84 if rc.returncode != 0:
85
86 raise Exception(
87 "Error running command: {}.\n{}".format(
88 " ".join(full_cmd_esc), rc.stderr.decode("utf-8")
89 )
90 )
91 return (rc.stdout, rc.stderr)
92
93
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +000094def build_op_tests(
Jeremy Johnson1271c442023-09-05 11:39:26 +010095 args,
96 test_type,
97 profile,
98 operator,
99 group,
100 gen_args_list,
101 gen_neg_dim_range,
102 supports=[],
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000103):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100104 """Build tests for a given operator.
105
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000106 Builds a set of tests based on the given generator arguments list
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100107
108 Returns operator output directory
109 """
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100110 build_tests_cmd = "tosa_verif_build_tests"
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000111 op_build_dir = args.build_dir / profile / group
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100112
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000113 build_cmd_base = [
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100114 build_tests_cmd,
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100115 "--generate-lib-path",
116 str(args.generate_lib_path),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100117 "--filter",
Jeremy Johnson14087952024-02-29 16:13:10 +0000118 f"^{operator}$",
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100119 "-o",
120 str(op_build_dir),
121 "--seed",
Jeremy Johnson93d43902022-09-27 12:26:14 +0100122 str(args.random_seed),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100123 ]
124
Jeremy Johnson1271c442023-09-05 11:39:26 +0100125 if "lazy_data_gen" in supports and args.lazy_data_generation:
126 build_cmd_base.append("--lazy-data-generation")
127
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000128 build_cmds_list = []
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100129
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000130 if test_type in ["positive", "both"]:
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100131 # Append extra parameters and run test generator for each set of parameters.
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000132 for arglist in gen_args_list:
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000133 build_cmd_pos_test = build_cmd_base.copy()
134 build_cmd_pos_test.extend(["--test-type", "positive"])
135 build_cmd_pos_test.extend(arglist)
136 build_cmds_list.append(build_cmd_pos_test)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100137
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000138 if test_type in ["negative", "both"]:
Jeremy Johnson35396f22023-01-04 17:05:25 +0000139 # Get target-dtypes options and any filter string to limit tests
Jeremy Johnson93d43902022-09-27 12:26:14 +0100140 target_dtypes_args = []
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000141 for arglist in gen_args_list:
Jeremy Johnson93d43902022-09-27 12:26:14 +0100142 idx = 0
143 while idx < len(arglist):
144 if arglist[idx] == "--target-dtype":
145 if arglist[idx + 1] not in target_dtypes_args:
146 target_dtypes_args.extend(arglist[idx : idx + 2])
147 idx += 1 # skip over option (and then argument below)
148 idx += 1
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000149 build_cmd_neg_test = build_cmd_base.copy()
150 build_cmd_neg_test.extend(["--test-type", "negative"])
Jeremy Johnson93d43902022-09-27 12:26:14 +0100151 # Limit sizes of negative tests
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000152 dim_range = gen_neg_dim_range if gen_neg_dim_range is not None else "1,16"
153
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000154 build_cmd_neg_test.extend(["--tensor-dim-range", dim_range])
155 build_cmd_neg_test.extend(target_dtypes_args)
156 build_cmds_list.append(build_cmd_neg_test)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100157
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000158 logger.debug(f"Creating {operator} tests with {len(build_cmds_list)} parameter(s)")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100159 error = False
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000160 for i, cmd in enumerate(build_cmds_list):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100161 try:
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100162 _run_sh_command(args, args.ref_model_path.parent, cmd)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100163 logger.info(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000164 f"{operator} test batch {(i+1)}/{len(build_cmds_list)} created successfully"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100165 )
166 except Exception as e:
167 logger.error(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000168 f"{operator} test batch {(i+1)}/{len(build_cmds_list)} unsuccessful, skipping"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100169 )
170 logger.error(f" build_op_tests error: {e} ")
171 error = True
172 if error:
173 raise (GenConformanceError())
174
175 return op_build_dir
176
177
178def _check_to_include_test(profile, test_name, exclude_negative_tests=False):
179 """Check test name for exclusions, return False to indicate excluded."""
180 excludes = ["ERRORIF"] if exclude_negative_tests else []
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100181
182 for exclusion in excludes:
183 if f"_{exclusion}_" in test_name:
184 return False
185 return True
186
187
188def _get_all_tests_list(
189 profile, test_root_dir, operator, exclude_negative_tests=False, include_all=False
190):
191 """Create test list based on tests in the test_dir."""
192 test_dir = test_root_dir / operator
193 if not test_dir.is_dir():
194 # Tests are split into multiple dirs, for example: conv2d_1x1, conv2d_3x3
195 test_dir = test_root_dir
196 directories = [
197 tdir for tdir in test_dir.glob("*") if tdir.name.startswith(operator)
198 ]
199 else:
200 directories = [test_dir]
201
202 tests = []
203 for tdir in directories:
204 tests.extend(
205 [
206 test
207 for test in tdir.glob("*")
208 if include_all
209 or _check_to_include_test(profile, test.name, exclude_negative_tests)
210 ]
211 )
212 return tests
213
214
Jeremy Johnson1271c442023-09-05 11:39:26 +0100215def generate_results(args, profile, operator, op_build_dir, supports=[], tests=None):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100216 """Run tests on reference model and save result to the test directory."""
Jeremy Johnson1271c442023-09-05 11:39:26 +0100217 if "lazy_data_gen" in supports and args.lazy_data_generation:
218 logger.info("Skipping running tests due to lazy data gen")
219 return
220
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100221 num_cores = args.num_cores
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100222
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100223 # Use the test runner
224 ref_cmd_base = [
225 "tosa_verif_run_tests",
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100226 "--ref-model-path",
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100227 str(args.ref_model_path),
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100228 "--schema-path",
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100229 str(args.schema_path),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100230 "-j",
231 str(num_cores),
232 "-v",
233 "-t",
234 ]
235 ref_cmds = []
236
237 if not tests:
238 # Do not need to run ERRORIF tests as they don't have result files
239 tests = _get_all_tests_list(
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100240 profile, op_build_dir, operator, exclude_negative_tests=True
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100241 )
242
243 for test in tests:
Jeremy Johnsone2b5e872023-09-14 17:02:09 +0100244 desc = test / "desc.json"
245 with desc.open("r") as fd:
246 test_desc = json.load(fd)
247 if "meta" in test_desc and "compliance" in test_desc["meta"]:
248 logger.info(
249 f"Skipping generating results for new compliance test - {str(test)}"
250 )
251 continue
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100252 ref_cmd = ref_cmd_base.copy()
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100253 ref_cmd.append(str(test.absolute()))
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100254 ref_cmds.append(ref_cmd)
255
256 fail_string = "UNEXPECTED_FAILURE"
257 failed_counter = 0
258
259 job_pool = mp.Pool(args.num_cores)
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100260 sh_partial = partial(_run_sh_command, args, args.ref_model_path.parent)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100261 pool_results = job_pool.map(sh_partial, ref_cmds)
262 job_pool.close()
263 job_pool.join()
264
265 # Use captured output for run_sh_command to work out if test passed.
266 for i, rc in enumerate(pool_results):
267 if fail_string in str(rc[0]):
268 logger.error(f"Test {i+1}/{len(ref_cmds)}: {ref_cmds[i][-1]} failed.")
269 failed_counter += 1
270 else:
271 logger.info(f"Test {i+1}/{len(ref_cmds)}: {ref_cmds[i][-1]} passed.")
272
273 logger.info(f"{len(ref_cmds)-failed_counter}/{len(ref_cmds)} tests passed")
274 logger.info("Ran tests on model and saved results of passing tests")
275
276
277def convert_tests(
278 args,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100279 profile,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100280 operator,
281 op_build_dir,
282 output_dir,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100283 op_profiles_list,
Jeremy Johnson1271c442023-09-05 11:39:26 +0100284 supports=[],
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100285 tests=None,
286 group=None,
287 trim_op_subdir=False,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000288 tags=None,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100289):
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100290 """Convert/copy tests to output directory."""
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100291 if group:
292 output_dir = output_dir / group
293
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100294 c2c_args_base = ["--strict"]
295 c2c_args_base.extend(["--schema-path", str(args.schema_path)])
296 c2c_args_base.extend(["--flatc-path", str(args.flatc_path)])
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100297 c2c_args_base.extend(["--output-type", args.output_type])
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100298 # This op maybe in more than one profile - e.g. tosa_bi and tosa_mi
299 # even if we are only producing tests for tosa_mi
300 for op_profile in op_profiles_list:
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000301 c2c_args_base.extend(["--profile", op_profile])
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000302 if tags is not None:
303 for tag in tags:
304 c2c_args_base.extend(["--tag", tag])
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100305 if args.framework_schema:
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000306 c2c_args_base.extend(["--framework-schema", str(args.framework_schema)])
Jeremy Johnson1271c442023-09-05 11:39:26 +0100307 if "lazy_data_gen" in supports and args.lazy_data_generation:
308 c2c_args_base.append("--lazy-data-generation")
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000309 c2c_args_base.append("--output-directory")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100310
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000311 c2c_args_list = []
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100312
313 if not tests:
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100314 tests = _get_all_tests_list(profile, op_build_dir, operator)
315 logger.info(f"Converting all {profile} profile tests")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100316
317 # Controls if we copy the tests in their operator sub-directory or not
318 output_dir_relative_pos = -1 if trim_op_subdir else -2
319 for test in tests:
320 logger.info(f"Test chosen: {test}")
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000321 c2c_args = c2c_args_base.copy()
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100322 full_output_directory = output_dir / test.relative_to(
323 *test.parts[:output_dir_relative_pos]
324 )
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000325 c2c_args.append(str(full_output_directory))
326 c2c_args.append(str(test))
327 c2c_args_list.append(c2c_args)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100328
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000329 if len(c2c_args_list) == 0:
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000330 logger.error(
331 f"No tests found for {operator}. Nothing to convert in {op_build_dir}"
332 )
333 raise (GenConformanceError())
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100334
335 job_pool = mp.Pool(args.num_cores)
336
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000337 pool_results = job_pool.map(c2c_main, c2c_args_list)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100338 job_pool.close()
339 job_pool.join()
340
341 failed_counter = 0
342 for i, result in enumerate(pool_results):
343 if result != 0:
344 logger.error(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000345 f"test {i+1}/{len(c2c_args_list)}: {c2c_args_list[i][-1]} failed to convert."
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100346 )
347 failed_counter += 1
348 else:
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000349 logger.info(
350 f"test {i+1}/{len(c2c_args_list)}: {c2c_args_list[i][-1]} converted"
351 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100352 logger.info(
Jeremy Johnsondd8d9c22022-12-12 14:18:10 +0000353 f"{len(c2c_args_list)-failed_counter}/{len(c2c_args_list)} tests successfully converted"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100354 )
355
356 if failed_counter > 0:
357 logger.error(f"Stopping due to {failed_counter} test conversion errors")
358 raise (GenConformanceError())
359
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100360 logger.info("Converted/copied tests and saved to output directory")
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100361
362 return output_dir
363
364
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100365def get_op_tests_selection(
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000366 args,
367 profile,
368 operator,
369 op_build_dir,
370 selection_config,
371 negative=False,
372 ignore_missing=False,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100373):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100374 """Use test picker to get subsection of tests generated."""
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000375 # Need a full copy of the config as the selector updates it
376 config = copy.deepcopy(selection_config)
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100377 logger.info("Choosing {} tests".format(("negative" if negative else "positive")))
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100378 try:
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100379 op = Operator.registry[operator](
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000380 op_build_dir, config, negative=negative, ignore_missing=ignore_missing
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100381 )
382 except KeyError:
383 logger.error(f"{operator} operator is not supported by test_select")
384 raise (GenConformanceError())
385
386 return op.select_tests()
387
388
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100389def check_op_tests(args, profile, operator, output_dir):
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100390 """Move test folders than contain files larger than 30MB to new directory."""
391 destination_dir = str(args.output_dir) + "_large_files"
392
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100393 tests = _get_all_tests_list(profile, output_dir, operator, include_all=True)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100394 if not tests:
395 logger.error(
396 f"Couldn't find any tests to size check for {operator} in {output_dir}"
397 )
398 raise (GenConformanceError())
399
400 for tdir in tests:
401 move_dir = False
402 test_files = [file for file in tdir.glob("*")]
403 for file in test_files:
404 file_size = os.stat(file).st_size / 1024**2
405 if file_size > 30:
406 move_dir = True
407
408 if move_dir:
409 move_destination = destination_dir / tdir.relative_to(output_dir)
410 logger.warning(
411 f"{tdir.relative_to(output_dir)} contains files that are too large (>30MB), test moved to new folder: {destination_dir}"
412 )
413
414 if move_destination.is_dir():
415 logger.warning(
416 f"{move_destination} directory already exists, deleting existing."
417 )
418 shutil.rmtree(str(move_destination))
419 shutil.move(str(tdir), move_destination)
420
421
422def copy_rename_framework_tests(args, operator, test_picks):
423 """Copy framework tests into new folder and rename them if needed.
424
425 The tests are renamed to match the framework operator names if an
426 alternate name has been used instead.
427 """
428 framework_tests_dir = args.framework_tests_dir
429 new_tests_dir = args.build_dir / "frameworks" / operator
430 os.makedirs(new_tests_dir, exist_ok=True)
431
432 # Get the framework tests operator name
433 if "alternate_names" in test_picks[operator]:
434 alternate_names = test_picks[operator]["alternate_names"]
435 else:
436 alternate_names = [operator]
437
438 # Get the alternate named test directories for the operator
439 for alt_name in alternate_names:
440 test_prefix = f"test_{alt_name}"
441 test_dirs = list(framework_tests_dir.glob(f"{test_prefix}_*"))
442
443 # Copy tests to new directory and rename to match framework operator names
444 # - if there is just 1 alternate name, replace the full test prefix
445 # test_add_... -> add_...
446 # - if there are multiple alternate names, just replace the "test"
447 # test_concatv2_... -> concatenation_concatv2_...
448 old_prefix = test_prefix if len(alternate_names) == 1 else "test"
449
450 for tdir in test_dirs:
451 new_test_name = tdir.name.replace(old_prefix, operator)
452 copy_destination = new_tests_dir / new_test_name
453 logger.debug(f"copying test folder {tdir} to {copy_destination}")
454 copy_tree(str(tdir), str(copy_destination))
455
456 logger.info(f"Copied and renamed {len(test_dirs)} framework test folders")
457 return new_tests_dir.parent
458
459
460def get_framework_tests_selection(args, operator, test_picks, op_build_dir):
461 """Get the list of pre-chosen tests with relative paths."""
462 try:
463 tests = test_picks[operator]["tests"]
464 except KeyError:
465 logger.error(f"Framework test selection not defined for {operator} operator")
466 raise (GenConformanceError())
467
468 test_paths = [op_build_dir / operator / test for test in tests]
469 return test_paths
470
471
472def parse_args(argv=None):
473 """Parse the arguments."""
474 parser = argparse.ArgumentParser()
Jeremy Johnson88588622022-07-12 16:42:29 +0100475 profiles = list(PROFILE_OPS_INFO.keys())
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100476 profiles.append(PROFILES_ALL)
Jeremy Johnson88588622022-07-12 16:42:29 +0100477 parser.add_argument(
478 "--profile",
479 dest="profile",
480 choices=profiles,
481 default=profiles[0],
482 type=str,
483 help=f"TOSA profile (default is {profiles[0]})",
484 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100485 parser.add_argument(
486 "--operators",
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100487 "--op",
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100488 type=str,
489 nargs="*",
490 help="The operator(s) to create tests for, if not supplied all tests will be created",
491 )
492 parser.add_argument(
Jeremy Johnson88588622022-07-12 16:42:29 +0100493 "--unit-tests",
494 dest="unit_tests",
495 choices=["operator", "framework", "both"],
496 default="operator",
497 type=str,
498 help="Which unit tests are produced (default is operator)",
499 )
500 parser.add_argument(
501 "--test-type",
502 dest="test_type",
503 choices=["positive", "negative", "both"],
504 default="both",
505 type=str,
506 help="Type of tests produced (default is both)",
507 )
508 parser.add_argument(
Jeremy Johnson1271c442023-09-05 11:39:26 +0100509 "--lazy-data-generation",
510 action="store_true",
511 help="Enable lazy data generation (only for tosa-mi)",
512 )
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100513 rm_group = parser.add_mutually_exclusive_group(required=True)
514 rm_group.add_argument(
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100515 "--ref-model-directory",
516 dest="ref_model_dir",
517 type=Path,
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100518 help="(DEPRECATED - use ref-model-path) Reference Model directory - with build directory",
519 )
520 rm_group.add_argument(
521 "--ref-model-path",
522 dest="ref_model_path",
523 type=Path,
524 help="Path to TOSA reference model executable",
525 )
526 parser.add_argument(
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100527 "--generate-lib-path",
528 dest="generate_lib_path",
529 type=Path,
530 help=(
531 "Path to TOSA generate library. Defaults to "
532 "the library in the directory of `ref-model-path`"
533 ),
534 )
535 parser.add_argument(
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100536 "--schema-path",
537 "--operator-fbs",
538 dest="schema_path",
539 type=Path,
540 help=(
541 "Path to TOSA reference model flat buffer schema. Defaults to "
542 f"`{cmf.DEFAULT_REF_MODEL_SCHEMA_PATH}` in parents parent directory of `ref-model-path`"
543 ),
544 )
545 parser.add_argument(
546 "--flatc-path",
547 dest="flatc_path",
548 type=Path,
549 help=(
550 "Path to flatc executable. Defaults to "
551 f"`{cmf.DEFAULT_REF_MODEL_BUILD_FLATC_PATH}` in parent directory of `ref-model-path`"
552 ),
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100553 )
Jeremy Johnson88588622022-07-12 16:42:29 +0100554 parser.add_argument(
Jeremy Johnson9c2fe6e2023-10-04 16:55:04 +0100555 "--test-version",
556 dest="test_version",
557 choices=TEST_VERSIONS,
558 default=TEST_VERSION_LATEST,
559 help=f"Version of the tests to produce (default is {TEST_VERSION_LATEST})",
560 )
561 parser.add_argument(
562 "--output-type",
563 dest="output_type",
564 choices=OUTPUT_TYPES,
565 default=OUTPUT_TYPE_DEFAULT,
566 help=f"Output file type produced (default is {OUTPUT_TYPE_DEFAULT})",
567 )
568 parser.add_argument(
Jeremy Johnson93d43902022-09-27 12:26:14 +0100569 "--seed",
570 dest="random_seed",
571 default=DEFAULT_SEED,
572 type=int,
573 help="Random test seed",
574 )
575 parser.add_argument(
Jeremy Johnson88588622022-07-12 16:42:29 +0100576 "--framework-tests-directory",
577 dest="framework_tests_dir",
578 type=Path,
579 default=Path.cwd() / "tests",
580 help="The pre-built framework tests directory (default is tests)",
581 )
582 parser.add_argument(
583 "--framework-schema",
584 dest="framework_schema",
585 type=Path,
586 help="Framework flatbuffers schema needed to convert framework models",
587 )
588 parser.add_argument(
589 "--build-directory",
590 dest="build_dir",
591 type=Path,
592 default=Path.cwd() / "conformance_build",
593 help="Temporary build directory for files created during this process (default is conformance_build)",
594 )
595 parser.add_argument(
596 "--output-directory",
597 dest="output_dir",
598 type=Path,
599 default=Path.cwd() / "conformance",
600 help="Output directory (default is conformance)",
601 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100602 script_dir = Path(__file__).parent.absolute()
603 parser.add_argument(
604 "--test-param-json-directory",
605 dest="param_json_dir",
606 type=Path,
607 default=script_dir,
Jeremy Johnson88588622022-07-12 16:42:29 +0100608 help=f"Test parameters (ops info) JSON file directory (default is {script_dir})",
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100609 )
610 parser.add_argument(
611 "--convert-all-tests",
612 action="store_true",
613 help="Converts all tests instead of those picked by test_select",
614 )
615 parser.add_argument(
616 "--keep-large-files",
617 action="store_true",
618 help="Keeps tests that contain files larger than 30MB in output directory",
619 )
620 parser.add_argument(
621 "--capture-output",
622 action="store_true",
623 help="Prints output of running sh commands",
624 )
625 parser.add_argument(
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100626 "-j",
627 dest="num_cores",
628 type=int,
629 default=6,
630 help="Number of simultaneous jobs to split the tasks into for multiprocessing",
631 )
632 parser.add_argument(
633 "-v",
634 dest="verbosity",
635 action="count",
636 default=0,
637 help="Verbosity (can be used multiple times for more details)",
638 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100639 args = parser.parse_args(argv)
640
641 return args
642
643
Jeremy Johnsonfd8c8fe2023-10-23 11:55:38 +0100644def in_version(test_version, gen_dict):
645 """Check if the selected test_version is compatible with the tests."""
646
647 def version_string_to_numbers(verstr):
648 # Turn the "vM.mm.pp" string into Major, Minor, Patch versions
649 if verstr == TEST_VERSION_LATEST:
650 return (TOSA_VERSION[0], TOSA_VERSION[1], TOSA_VERSION[2])
651 else:
652 match = re.match(REGEX_VERSION, verstr)
653 if match is None:
654 raise KeyError(f"Invalid version string {verstr}")
655 return (int(v) for v in match.groups())
656
657 if "from_version" in gen_dict:
658 selected_version = version_string_to_numbers(test_version)
659 from_version = version_string_to_numbers(gen_dict["from_version"])
660
661 # Check the Major version is compatible, then Minor, and lastly Patch
662 # Unless the versions match, we can exit early due to obvious precedence
663 for sel, fro in zip(selected_version, from_version):
664 if sel < fro:
665 # From version is later than selected version
666 return False
667 elif sel > fro:
668 # From version is earlier than selected version
669 return True
670 # If we get here, the version numbers match exactly
671 return True
672 else:
673 # No specific version info
674 return True
675
676
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100677def main():
678 args = parse_args()
679
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100680 if args.ref_model_dir is not None:
681 # Assume the ref model exe path based on the ref model directory
682 args.ref_model_path = cmf.find_tosa_file(
683 cmf.TosaFileType.REF_MODEL, args.ref_model_dir, False
684 )
685 if not args.ref_model_path.is_file():
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100686 logger.error(
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100687 f"Missing reference model binary (--ref-model-path): {args.ref_model_path}"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100688 )
689 return 2
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100690 args.ref_model_path = args.ref_model_path.absolute()
691
692 if args.generate_lib_path is None:
693 args.generate_lib_path = cmf.find_tosa_file(
694 cmf.TosaFileType.GENERATE_LIBRARY, args.ref_model_path
695 )
696 if not args.generate_lib_path.is_file():
697 logger.error(
698 f"Missing TOSA generate data library (--generate-lib-path): {args.generate_lib_path}"
699 )
700 return 2
701 args.generate_lib_path = args.generate_lib_path.absolute()
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100702
703 if args.schema_path is None:
704 args.schema_path = cmf.find_tosa_file(
705 cmf.TosaFileType.SCHEMA, args.ref_model_path
706 )
707 if not args.schema_path.is_file():
708 logger.error(
709 f"Missing reference model schema (--schema-path): {args.schema_path}"
710 )
711 return 2
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100712 args.schema_path = args.schema_path.absolute()
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100713
714 if args.flatc_path is None:
715 args.flatc_path = cmf.find_tosa_file(
716 cmf.TosaFileType.FLATC, args.ref_model_path
717 )
718 if not args.flatc_path.is_file():
719 logger.error(f"Missing flatc binary (--flatc-path): {args.flatc_path}")
720 return 2
Jeremy Johnson65ba8092023-10-09 16:31:13 +0100721 args.flatc_path = args.flatc_path.absolute()
Jeremy Johnsonf0348ea2023-09-27 16:10:59 +0100722
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100723 if args.unit_tests in ["framework", "both"]:
Jeremy Johnsonc1d1c632023-08-02 17:21:36 +0100724 logger.warning(
725 "DEPRECATION - Framework tests are not part of TOSA conformance testing"
726 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100727 if not args.framework_schema:
728 logger.error(
729 "Need to supply location of Framework flatbuffers schema via --framework-schema"
730 )
731 return 2
732 if not args.framework_tests_dir.is_dir():
733 logger.error(
734 f"Missing or invalid framework tests directory: {args.framework_tests_dir}"
735 )
736 return 2
737
738 loglevels = (logging.WARNING, logging.INFO, logging.DEBUG)
739 loglevel = loglevels[min(args.verbosity, len(loglevels) - 1)]
740 logger.setLevel(loglevel)
741 # Set other loggers the same
742 logging.getLogger("test_select").setLevel(loglevel)
743 logging.getLogger("convert2conformance").setLevel(loglevel)
744
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100745 print(f"Output directory: {args.output_dir}")
746
Jeremy Johnson93d43902022-09-27 12:26:14 +0100747 if args.random_seed != DEFAULT_SEED:
748 logger.warning(
749 "Random test seed changed from default, tests will not match official conformance"
750 )
751
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100752 args.build_dir = args.build_dir.resolve()
753 logger.debug(f"Creating build directory: {args.build_dir}")
754 args.build_dir.mkdir(parents=True, exist_ok=True)
755
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100756 # TODO: For tosa-mi should really generate tosa-bi profile as well
757 # - for now leave it as subset instead of as superset (for testing)
758 if args.profile == PROFILES_ALL:
759 profiles = list(PROFILE_OPS_INFO.keys())
760 else:
761 profiles = [args.profile]
762
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100763 try:
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100764 for profile in profiles:
765 print(f"Creating conformance tests for TOSA {profile} profile")
766 # Framework unit tests
767 if args.unit_tests in ["framework", "both"]:
768 logger.debug("Creating FRAMEWORK unit tests")
769 test_picks_file = (
770 args.param_json_dir / PROFILE_OPS_INFO[profile]["framework_tests"]
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100771 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100772 try:
773 with open(test_picks_file, "r") as fd:
774 test_picks = json.load(fd)
775 except Exception as e:
776 logger.error(
777 f"Couldn't load framework tests info - {test_picks_file}: {e}"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100778 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100779 return 1
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100780
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100781 operators = args.operators
782 if not operators:
783 # Create tests for all the operators
784 operators = list(test_picks.keys())
785
786 root_output_dir = (
787 args.output_dir / "frameworks" / "tflite" / "operators"
788 )
789 for op in operators:
790 logger.info(f"FRAMEWORK OP: {op}")
791 if op not in test_picks:
792 logger.warning(
793 f"Framework op {op} not found in {test_picks_file} - skipping"
794 )
795 continue
796
797 op_profiles_list = test_picks[op]["profile"]
798 if (
799 args.profile != PROFILES_ALL
800 and args.profile not in op_profiles_list
801 ):
802 # Skip this operator as not part of the profile chosen
803 logger.debug(f"Skipping {op} as not part of {args.profile}")
804 continue
805
806 logger.debug(f"Copying and renaming {op}")
807 framework_test_dir = copy_rename_framework_tests(
808 args, op, test_picks
809 )
810
811 if args.convert_all_tests:
812 logger.debug("Running and converting all framework tests")
813 framework_tests = None # Don't select any
814 else:
815 logger.debug("Running and converting selected framework tests")
816 framework_tests = get_framework_tests_selection(
817 args, op, test_picks, framework_test_dir
818 )
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100819 convert_tests(
820 args,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100821 profile,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100822 op,
823 framework_test_dir,
824 root_output_dir,
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100825 op_profiles_list,
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100826 tests=framework_tests,
827 trim_op_subdir=True,
828 )
829
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100830 # Operator unit tests
831 if args.unit_tests in ["operator", "both"]:
832 logger.debug("Creating OPERATOR unit tests")
833 test_params_file = (
834 args.param_json_dir
835 / PROFILE_OPS_INFO[profile]["operator_test_params"]
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100836 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100837 try:
838 with open(test_params_file, "r") as fd:
839 test_params = json.load(fd)
840 except Exception as e:
841 logger.error(
842 f"Couldn't load operator test params - {test_params_file}: {e}"
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100843 )
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100844 return 1
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100845
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100846 operators = args.operators
847 if not operators:
848 # Create tests for all the operators
849 operators = list(test_params.keys())
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100850
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100851 for op in operators:
852 logger.info(f"OPERATOR: {op}")
853 if op not in test_params:
854 logger.warning(
855 f"{op} operator parameters not found in {test_params_file} - skipping"
856 )
857 continue
Jeremy Johnson0ecfa372022-06-30 14:27:56 +0100858
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100859 op_profiles_list = test_params[op]["profile"]
860 if (
861 args.profile != PROFILES_ALL
862 and args.profile not in op_profiles_list
863 ):
864 # Skip this operator as not part of the profile chosen
865 logger.debug(f"Skipping {op} as not part of {args.profile}")
866 continue
867
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100868 operator_group = test_params[op]["group"]
869 root_output_dir = args.output_dir / "operators"
Jeremy Johnson1271c442023-09-05 11:39:26 +0100870 supports = (
871 test_params[op]["support_for"]
872 if "support_for" in test_params[op]
873 else []
874 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000875
876 # Iterate through the generation groups selecting tests from each
877 for gen_name, gen_dict in test_params[op]["generation"].items():
Jeremy Johnsonfd8c8fe2023-10-23 11:55:38 +0100878
879 if not in_version(args.test_version, gen_dict):
880 logger.warning(
881 f"{op} [{gen_name}] is not in {args.test_version} - skipping"
882 )
883 continue
884
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000885 no_neg_tests = (
886 "no_negative_tests" in gen_dict
887 and gen_dict["no_negative_tests"] == "true"
888 )
889
890 if no_neg_tests:
891 if args.test_type == "negative":
892 logger.info(
893 f"No negative tests for {op} / generation group {gen_name}"
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100894 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000895 continue
896 # Only produce positive tests
897 test_type = "positive"
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100898 else:
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000899 test_type = args.test_type
900
901 gen_neg_dim_range = (
902 gen_dict["negative_dim_range"]
903 if "negative_dim_range" in gen_dict
904 else None
905 )
906
907 ignore_missing = gen_name != STANDARD_GENERATOR_GROUP
908 tags = (
909 [gen_name] if gen_name != STANDARD_GENERATOR_GROUP else None
910 )
911
912 op_build_dir = build_op_tests(
913 args,
914 test_type,
915 profile,
916 op,
917 gen_name,
918 gen_dict["generator_args"],
919 gen_neg_dim_range,
Jeremy Johnson1271c442023-09-05 11:39:26 +0100920 supports=supports,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000921 )
922
Jeremy Johnson0c716862023-04-13 17:18:19 +0100923 # Work out which selection criteria we are using
924 if "selector" in gen_dict:
925 selector_name = gen_dict["selector"]
926 if selector_name not in test_params[op]["selection"]:
927 logger.warn(
928 f"Could not find {selector_name} in selection dict for {op} - using default"
929 )
930 selector_name = "default"
931 else:
932 selector_name = "default"
933 if selector_name not in test_params[op]["selection"]:
934 logger.error(
935 f"Could not find {selector_name} in selection dict for {op}"
936 )
937 raise (GenConformanceError())
938
939 # Selection criteria
940 selection_config = test_params[op]["selection"][selector_name]
941
Jeremy Johnson76c6a552023-09-11 09:30:02 +0100942 if args.convert_all_tests:
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000943 logger.debug(f"Running and converting all {op} tests")
Jeremy Johnson1271c442023-09-05 11:39:26 +0100944 generate_results(
945 args, profile, op, op_build_dir, supports=supports
946 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000947 operator_test_list = None
948 else:
949 logger.debug(
950 f"Running and converting selection of {op} tests"
Jeremy Johnsone4b08ff2022-09-15 10:38:17 +0100951 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000952 if test_type in ["positive", "both"]:
Jeremy Johnson76c6a552023-09-11 09:30:02 +0100953 if (
954 "all" in selection_config
955 and selection_config["all"] == "true"
956 ):
957 # Just get all the positive tests
958 tests_gen, tests_gen2 = tee(
959 _get_all_tests_list(
960 profile,
961 op_build_dir,
962 op,
963 exclude_negative_tests=True,
964 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000965 )
Jeremy Johnson76c6a552023-09-11 09:30:02 +0100966 else:
967 # Get a selection of positive tests
968 tests_gen, tests_gen2 = tee(
969 get_op_tests_selection(
970 args,
971 profile,
972 op,
973 op_build_dir,
974 selection_config,
975 ignore_missing=ignore_missing,
976 )
977 )
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000978 generate_results(
Jeremy Johnson1271c442023-09-05 11:39:26 +0100979 args,
980 profile,
981 op,
982 op_build_dir,
983 supports=supports,
984 tests=tests_gen,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +0000985 )
986 operator_test_list = list(tests_gen2)
987 else:
988 operator_test_list = []
989 if test_type in ["negative", "both"]:
990 operator_test_list.extend(
991 get_op_tests_selection(
992 args,
993 profile,
994 op,
995 op_build_dir,
996 selection_config,
997 negative=True,
998 )
999 )
1000 output_dir = convert_tests(
1001 args,
1002 profile,
1003 op,
1004 op_build_dir,
1005 root_output_dir,
1006 op_profiles_list,
Jeremy Johnson1271c442023-09-05 11:39:26 +01001007 supports=supports,
Jeremy Johnsonfd05bb32023-02-07 16:39:24 +00001008 tests=operator_test_list,
1009 group=operator_group,
1010 tags=tags,
1011 )
1012 if not args.keep_large_files:
1013 check_op_tests(args, profile, op, output_dir)
Jeremy Johnson0ecfa372022-06-30 14:27:56 +01001014 except GenConformanceError:
1015 return 1
1016
1017 return 0
1018
1019
1020if __name__ == "__main__":
1021 exit(main())