Files
OSACA/tests/test_cli.py

243 lines
8.3 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Unit tests for the CLI of OSACA and running the sample kernels in examples/
"""
import argparse
import os
import unittest
from io import StringIO
from shutil import copyfile
from unittest.mock import patch
import osaca.osaca as osaca
from osaca.parser import ParserAArch64, ParserX86ATT
from osaca.semantics import MachineModel
class ErrorRaisingArgumentParser(argparse.ArgumentParser):
def error(self, message):
raise ValueError(message) # reraise an error
class TestCLI(unittest.TestCase):
###########
# Tests
###########
def test_check_arguments(self):
parser = osaca.create_parser(parser=ErrorRaisingArgumentParser())
args = parser.parse_args(['--arch', 'WRONG_ARCH', self._find_file('gs', 'csx', 'gcc')])
with self.assertRaises(ValueError):
osaca.check_arguments(args, parser)
args = parser.parse_args(
['--arch', 'csx', '--import', 'WRONG_BENCH', self._find_file('gs', 'csx', 'gcc')]
)
with self.assertRaises(ValueError):
osaca.check_arguments(args, parser)
def test_import_data(self):
parser = osaca.create_parser(parser=ErrorRaisingArgumentParser())
args = parser.parse_args(
[
'--arch',
'tx2',
'--import',
'ibench',
self._find_test_file('ibench_import_aarch64.dat'),
]
)
output = StringIO()
osaca.run(args, output_file=output)
args = parser.parse_args(
[
'--arch',
'tx2',
'--import',
'asmbench',
self._find_test_file('asmbench_import_aarch64.dat'),
]
)
osaca.run(args, output_file=output)
def test_check_db(self):
parser = osaca.create_parser(parser=ErrorRaisingArgumentParser())
args = parser.parse_args(
['--arch', 'tx2', '--db-check', '--verbose', self._find_test_file('triad_x86_iaca.s')]
)
output = StringIO()
osaca.run(args, output_file=output)
def test_get_parser(self):
self.assertTrue(isinstance(osaca.get_asm_parser('csx'), ParserX86ATT))
self.assertTrue(isinstance(osaca.get_asm_parser('tx2'), ParserAArch64))
with self.assertRaises(ValueError):
osaca.get_asm_parser('UNKNOWN')
def test_marker_insert_x86(self):
# copy file to add markers
name = self._find_test_file('kernel_x86.s')
name_copy = name + '.copy.s'
copyfile(name, name_copy)
user_input = ['.L10']
output = StringIO()
parser = osaca.create_parser()
args = parser.parse_args(['--arch', 'csx', '--insert-marker', name_copy])
with patch('builtins.input', side_effect=user_input):
osaca.run(args, output_file=output)
lines_orig = len(open(name).readlines())
lines_copy = len(open(name_copy).readlines())
self.assertEqual(lines_copy, lines_orig + 5 + 4)
# remove copy again
os.remove(name_copy)
def test_marker_insert_aarch64(self):
# copy file to add markers
name = self._find_test_file('kernel_aarch64.s')
name_copy = name + '.copy.s'
copyfile(name, name_copy)
user_input = ['.LBB0_32', '64']
parser = osaca.create_parser()
args = parser.parse_args(['--arch', 'tx2', '--insert-marker', name_copy])
with patch('builtins.input', side_effect=user_input):
osaca.run(args)
lines_orig = len(open(name).readlines())
lines_copy = len(open(name_copy).readlines())
self.assertEqual(lines_copy, lines_orig + 3 + 2)
# remove copy again
os.remove(name_copy)
def test_examples(self):
kernels = [
'add',
'copy',
'daxpy',
'gs',
'j2d',
'striad',
'sum_reduction',
'triad',
'update',
]
archs = ['csx', 'tx2', 'zen1']
comps = {'csx': ['gcc', 'icc'], 'tx2': ['gcc', 'clang'], 'zen1': ['gcc']}
parser = osaca.create_parser()
# Analyze all asm files resulting out of kernels, archs and comps
for k in kernels:
for a in archs:
for c in comps[a]:
with self.subTest(kernel=k, arch=a, comp=c):
args = parser.parse_args(
['--arch', a, self._find_file(k, a, c), '--export-graph', '/dev/null']
)
output = StringIO()
osaca.run(args, output_file=output)
self.assertTrue('WARNING' not in output.getvalue())
def test_architectures(self):
parser = osaca.create_parser()
# Run the test kernel for all architectures
archs = osaca.SUPPORTED_ARCHS
for arch in archs:
with self.subTest(micro_arch=arch):
isa = MachineModel.get_isa_for_arch(arch)
kernel = 'kernel_{}.s'.format(isa)
args = parser.parse_args(
['--arch', arch, self._find_test_file(kernel)]
)
output = StringIO()
osaca.run(args, output_file=output)
def test_without_arch(self):
# Run test kernels without --arch flag
parser = osaca.create_parser()
# x86
kernel_x86 = 'kernel_x86.s'
args = parser.parse_args([self._find_test_file(kernel_x86)])
output = StringIO()
osaca.run(args, output_file=output)
# AArch64
kernel_aarch64 = 'kernel_aarch64.s'
args = parser.parse_args([self._find_test_file(kernel_aarch64)])
osaca.run(args, output_file=output)
def test_user_warnings(self):
parser = osaca.create_parser()
kernel = 'triad_x86_unmarked.s'
args = parser.parse_args(
['--arch', 'csx', '--ignore-unknown', self._find_test_file(kernel)]
)
output = StringIO()
osaca.run(args, output_file=output)
# WARNING for length
self.assertTrue(output.getvalue().count('WARNING') == 1)
args = parser.parse_args(
['--lines', '100-299', '--ignore-unknown', self._find_test_file(kernel)]
)
output = StringIO()
osaca.run(args, output_file=output)
# WARNING for arch
self.assertTrue(output.getvalue().count('WARNING') == 1)
def test_lines_arg(self):
# Run tests with --lines option
parser = osaca.create_parser()
kernel_x86 = 'triad_x86_iaca.s'
args_base = parser.parse_args(
['--arch', 'csx', self._find_test_file(kernel_x86)]
)
output_base = StringIO()
osaca.run(args_base, output_file=output_base)
output_base = output_base.getvalue().split('\n')[8:]
args = []
args.append(parser.parse_args(
['--lines', '146-154', '--arch', 'csx', self._find_test_file(kernel_x86)]
))
args.append(parser.parse_args(
['--lines', '146:154', '--arch', 'csx', self._find_test_file(kernel_x86)]
))
args.append(parser.parse_args(
['--lines', '146,147:148,149-154', '--arch', 'csx', self._find_test_file(kernel_x86)]
))
for a in args:
with self.subTest(params=a):
output = StringIO()
osaca.run(a, output_file=output)
self.assertEqual(output.getvalue().split('\n')[8:], output_base)
##################
# Helper functions
##################
@staticmethod
def _find_file(kernel, arch, comp):
testdir = os.path.dirname(__file__)
name = os.path.join(
testdir,
'../examples',
kernel,
kernel + '.s.' + arch[:3].lower() + '.' + comp.lower() + '.s',
)
if kernel == 'j2d' and arch.lower() == 'csx':
name = name[:-1] + 'AVX.s'
assert os.path.exists(name)
return name
@staticmethod
def _find_test_file(name):
testdir = os.path.dirname(__file__)
name = os.path.join(testdir, 'test_files', name)
assert os.path.exists(name)
return name
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TestCLI)
unittest.TextTestRunner(verbosity=2).run(suite)