blob: 2284e35c625ecf9f1c60ae186e1363230dfd97b8 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (c) 2020, ARM Limited.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import sys
import re
import os
import subprocess
import shlex
import json
import glob
import math
import queue
import threading
import traceback
import importlib
from enum import IntEnum, Enum, unique
from datetime import datetime
# Include the ../shared directory in PYTHONPATH
parent_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(parent_dir, '..', 'scripts'))
sys.path.append(os.path.join(parent_dir, '..', 'scripts', 'xunit'))
import xunit
import tosa
from tosa_test_gen import TosaTestGen
from tosa_test_runner import TosaTestRunner
no_color_printing = False
#from run_tf_unit_test import LogColors, print_color, run_sh_command
def parseArgs():
parser = argparse.ArgumentParser()
parser.add_argument('-t', '--test', dest='test', type=str, nargs='+',
help='Test(s) to run')
parser.add_argument('--seed', dest='random_seed', default=42, type=int,
help='Random seed for test generation')
parser.add_argument('--ref-model-path', dest='ref_model_path',
default='build/reference_model/tosa_reference_model', type=str,
help='Path to reference model executable')
parser.add_argument('--ref-debug', dest='ref_debug', default='', type=str,
help='Reference debug flag (low, med, high)')
parser.add_argument('--ref-intermediates', dest='ref_intermediates', default=0, type=int,
help='Reference model dumps intermediate tensors')
parser.add_argument('-v', '--verbose', dest='verbose', action='count',
help='Verbose operation')
parser.add_argument('-j', '--jobs', dest='jobs', type=int, default=1,
help='Number of parallel jobs')
parser.add_argument('--sut-module', '-s', dest='sut_module', type=str, nargs='+', default=['tosa_ref_run'],
help='System under test module to load (derives from TosaTestRunner). May be repeated')
parser.add_argument('--sut-module-args', dest='sut_module_args', type=str, nargs='+', default=[],
help='System under test module arguments. Use sutmodulename:argvalue to pass an argument. May be repeated.')
parser.add_argument('--xunit-file', dest='xunit_file', type=str, default='result.xml',
help='XUnit output file')
args = parser.parse_args()
# Autodetect CPU count
if args.jobs <= 0:
args.jobs = os.cpu_count()
return args
def workerThread(task_queue, runnerList, args, result_queue):
while True:
try:
test = task_queue.get(block=False)
except queue.Empty:
break
if test is None:
break
msg = ''
start_time = datetime.now()
try:
for runnerModule, runnerArgs in runnerList:
if args.verbose:
print('Running runner {} with test {}'.format(runnerModule.__name__, test))
runner = runnerModule.TosaRefRunner(args, runnerArgs, test)
try:
rc = runner.runModel()
except Exception as e:
rc = TosaTestRunner.Result.INTERNAL_ERROR
except Exception as e:
print('Internal regression error: {}'.format(e))
print(''.join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)))
rc = TosaTestRunner.Result.INTERNAL_ERROR
end_time = datetime.now()
result_queue.put((test, rc, msg, end_time - start_time))
task_queue.task_done()
return True
def loadRefModules(args):
# Returns a tuple of (runner_module, [argument list])
runnerList = []
for r in args.sut_module:
if args.verbose:
print('Loading module {}'.format(r))
runner = importlib.import_module(r)
# Look for arguments associated with this runner
runnerArgPrefix = '{}:'.format(r)
runnerArgList = []
for a in args.sut_module_args:
if a.startswith(runnerArgPrefix):
runnerArgList.append(a[len(runnerArgPrefix):])
runnerList.append((runner, runnerArgList))
return runnerList
def main():
args = parseArgs()
runnerList = loadRefModules(args)
threads = []
taskQueue = queue.Queue()
resultQueue = queue.Queue()
for t in args.test:
taskQueue.put((t))
print('Running {} tests '.format(taskQueue.qsize()))
for i in range(args.jobs):
t = threading.Thread(target=workerThread, args=(taskQueue, runnerList, args, resultQueue))
t.setDaemon(True)
t.start()
threads.append(t)
taskQueue.join()
resultList = []
results = [0] * len(TosaTestRunner.Result)
while True:
try:
test, rc, msg, time_delta = resultQueue.get(block=False)
except queue.Empty:
break
resultList.append((test, rc, msg, time_delta))
results[rc] = results[rc] + 1
xunit_result = xunit.xunit_results('Regressions')
xunit_suite = xunit_result.create_suite('Unit tests')
# Sort by test name
for test, rc, msg, time_delta in sorted(resultList, key=lambda tup: tup[0]):
test_name = test
xt = xunit.xunit_test(test_name, 'reference')
xt.time = str(float(time_delta.seconds) + (float(time_delta.microseconds) * 1e-6))
if rc == TosaTestRunner.Result.EXPECTED_PASS or rc == TosaTestRunner.Result.EXPECTED_FAILURE:
if args.verbose:
print('{} {}'.format(rc.name, test_name))
else:
xt.failed(msg)
print('{} {}'.format(rc.name, test_name))
xunit_suite.tests.append(xt)
resultQueue.task_done()
xunit_result.write_results(args.xunit_file)
print('Totals: ', end='')
for result in TosaTestRunner.Result:
print('{} {}, '.format(results[result], result.name.lower()), end ='')
print()
return 0
if __name__ == '__main__':
exit(main())