diff options
Diffstat (limited to 'tools/generate_test_list/generate_test_list.pl')
-rwxr-xr-x | tools/generate_test_list/generate_test_list.pl | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/tools/generate_test_list/generate_test_list.pl b/tools/generate_test_list/generate_test_list.pl new file mode 100755 index 000000000..bcfdaffba --- /dev/null +++ b/tools/generate_test_list/generate_test_list.pl @@ -0,0 +1,192 @@ +#!/usr/bin/env perl + +# +# Copyright (c) 2018, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Arg0: Name of the C file to generate. +# Arg1: Name of the header file to generate. +# Arg2: XML file that contains the list of test suites. +# Arg3: Text file listing the files to skip. Takes precedence over Arg2 file. +# + +my $TESTLIST_SRC_FILENAME = $ARGV[0]; +my $TESTLIST_HDR_FILENAME = $ARGV[1]; +my $XML_TEST_FILENAME = $ARGV[2]; +my $SKIPPED_LIST_FILENAME = $ARGV[3]; + +use strict; +use warnings; +use File::Temp; +use XML::LibXML; + +# Create the source & header files +open FILE_SRC, ">", $TESTLIST_SRC_FILENAME or die $!; +open FILE_HDR, ">", $TESTLIST_HDR_FILENAME or die $!; + +# +# Open the test list +# +my $doc; +my $testsuite_elem; +my $failure_elem; + +if (-e $XML_TEST_FILENAME) { + my $parser = XML::LibXML->new(); + $doc = $parser->parse_file($XML_TEST_FILENAME); +} else { + exit 1 +} + +# We assume if there is a root then it is a 'testsuites' element +my $root = $doc->documentElement(); +my @all_testcases = $root->findnodes("//testcase"); +my @all_testsuites = $root->findnodes("//testsuite"); + + +# Check the validity of the XML file: +# - A testsuite name must be unique. +# - A testsuite name must not contain a '/' character. +# - All test cases belonging to a given testsuite must have unique names. +for my $testsuite (@all_testsuites) { + my $testsuite_name = $testsuite->getAttribute('name'); + if ($testsuite_name =~ /\//) { + print "ERROR: $XML_TEST_FILENAME: Invalid test suite name '$testsuite_name'.\n"; + print "ERROR: $XML_TEST_FILENAME: Test suite names can't include a '/' character.\n"; + exit 1; + } + my @testsuites = $root->findnodes("//testsuite[\@name='$testsuite_name']"); + if (@testsuites != 1) { + print "ERROR: $XML_TEST_FILENAME: Can't have 2 test suites named '$testsuite_name'.\n"; + exit 1; + } + + my @testcases_of_testsuite = $testsuite->findnodes("testcase"); + for my $testcase (@testcases_of_testsuite) { + my $testcase_name = $testcase->getAttribute('name'); + my @testcases = $testsuite->findnodes("testcase[\@name='$testcase_name']"); + if (@testcases != 1) { + print "ERROR: $XML_TEST_FILENAME: Can't have 2 tests named '$testsuite_name/$testcase_name'.\n"; + exit 1; + } + } +} + +# +# Get the list of tests to skip. +# For each test to skip, find it in the XML tree and remove its node. +# +if (($SKIPPED_LIST_FILENAME) && (open SKIPPED_FILE, "<", $SKIPPED_LIST_FILENAME)) { + my @lines = <SKIPPED_FILE>; + close $SKIPPED_LIST_FILENAME; + + # Remove the newlines from the end of each line. + chomp @lines; + + my $line_no = 0; + my $testsuite_name; + my $testcase_name; + my $index = 0; + + for my $line (@lines) { + ++$line_no; + + # Skip empty lines. + if ($line =~ /^ *$/) { next; } + # Skip comments. + if ($line =~ /^#/) { next; } + + ($testsuite_name, $testcase_name) = split('/', $line); + + my @testsuites = $root->findnodes("//testsuite[\@name=\"$testsuite_name\"]"); + if (!@testsuites) { + print "WARNING: $SKIPPED_LIST_FILENAME:$line_no: Test suite '$testsuite_name' doesn't exist or has already been deleted.\n"; + next; + } + + if (!defined $testcase_name) { + print "INFO: Testsuite '$testsuite_name' will be skipped.\n"; + $testsuites[0]->unbindNode(); + next; + } + + my @testcases = $testsuites[0]->findnodes("testcase[\@name=\"$testcase_name\"]"); + if (!@testcases) { + print "WARNING: $SKIPPED_LIST_FILENAME:$line_no: Test case '$testsuite_name/$testcase_name' doesn't exist or has already been deleted.\n"; + next; + } + + print "INFO: Testcase '$testsuite_name/$testcase_name' will be skipped.\n"; + $testcases[0]->unbindNode(); + } +} + + +@all_testcases = $root->findnodes("//testcase"); + +# +# Generate the test function prototypes +# +my $testcase_count = 0; + +print FILE_SRC "#include \"tftf.h\"\n\n"; + +for my $testcase (@all_testcases) { + my $testcase_function = $testcase->getAttribute('function'); + $testcase_count++; + print FILE_SRC "test_result_t $testcase_function(void);\n"; +} + +# +# Generate the header file. +# +print FILE_HDR "#ifndef __TEST_LIST_H__\n"; +print FILE_HDR "#define __TEST_LIST_H__\n\n"; +print FILE_HDR "#define TESTCASE_RESULT_COUNT $testcase_count\n\n"; +print FILE_HDR "#endif\n"; + +# +# Generate the lists of testcases +# +my $testsuite_index = 0; +my $testcase_index = 0; +@all_testsuites = $root->findnodes("//testsuite"); +for my $testsuite (@all_testsuites) { + my $testsuite_name = $testsuite->getAttribute('name'); + my @testcases = $testsuite->findnodes("//testsuite[\@name='$testsuite_name']//testcase"); + + print FILE_SRC "\nconst test_case_t testcases_${testsuite_index}[] = {\n"; + + for my $testcase (@testcases) { + my $testcase_name = $testcase->getAttribute('name'); + my $testcase_description = $testcase->getAttribute('description'); + my $testcase_function = $testcase->getAttribute('function'); + + if (!defined($testcase_description)) { $testcase_description = ""; } + + print FILE_SRC " { $testcase_index, \"$testcase_name\", \"$testcase_description\", $testcase_function },\n"; + + $testcase_index++; + } + print FILE_SRC " { 0, NULL, NULL, NULL }\n"; + print FILE_SRC "};\n\n"; + $testsuite_index++; +} + +# +# Generate the lists of testsuites +# +$testsuite_index = 0; +print FILE_SRC "const test_suite_t testsuites[] = {\n"; +for my $testsuite (@all_testsuites) { + my $testsuite_name = $testsuite->getAttribute('name'); + my $testsuite_description = $testsuite->getAttribute('description'); + print FILE_SRC " { \"$testsuite_name\", \"$testsuite_description\", testcases_${testsuite_index} },\n"; + $testsuite_index++; +} +print FILE_SRC " { NULL, NULL, NULL }\n"; +print FILE_SRC "};\n"; + |