blob: bcfdaffba9858f577e6eaaf04c1bf321a5466573 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001#!/usr/bin/env perl
2
3#
4# Copyright (c) 2018, Arm Limited. All rights reserved.
5#
6# SPDX-License-Identifier: BSD-3-Clause
7#
8
9#
10# Arg0: Name of the C file to generate.
11# Arg1: Name of the header file to generate.
12# Arg2: XML file that contains the list of test suites.
13# Arg3: Text file listing the files to skip. Takes precedence over Arg2 file.
14#
15
16my $TESTLIST_SRC_FILENAME = $ARGV[0];
17my $TESTLIST_HDR_FILENAME = $ARGV[1];
18my $XML_TEST_FILENAME = $ARGV[2];
19my $SKIPPED_LIST_FILENAME = $ARGV[3];
20
21use strict;
22use warnings;
23use File::Temp;
24use XML::LibXML;
25
26# Create the source & header files
27open FILE_SRC, ">", $TESTLIST_SRC_FILENAME or die $!;
28open FILE_HDR, ">", $TESTLIST_HDR_FILENAME or die $!;
29
30#
31# Open the test list
32#
33my $doc;
34my $testsuite_elem;
35my $failure_elem;
36
37if (-e $XML_TEST_FILENAME) {
38 my $parser = XML::LibXML->new();
39 $doc = $parser->parse_file($XML_TEST_FILENAME);
40} else {
41 exit 1
42}
43
44# We assume if there is a root then it is a 'testsuites' element
45my $root = $doc->documentElement();
46my @all_testcases = $root->findnodes("//testcase");
47my @all_testsuites = $root->findnodes("//testsuite");
48
49
50# Check the validity of the XML file:
51# - A testsuite name must be unique.
52# - A testsuite name must not contain a '/' character.
53# - All test cases belonging to a given testsuite must have unique names.
54for my $testsuite (@all_testsuites) {
55 my $testsuite_name = $testsuite->getAttribute('name');
56 if ($testsuite_name =~ /\//) {
57 print "ERROR: $XML_TEST_FILENAME: Invalid test suite name '$testsuite_name'.\n";
58 print "ERROR: $XML_TEST_FILENAME: Test suite names can't include a '/' character.\n";
59 exit 1;
60 }
61 my @testsuites = $root->findnodes("//testsuite[\@name='$testsuite_name']");
62 if (@testsuites != 1) {
63 print "ERROR: $XML_TEST_FILENAME: Can't have 2 test suites named '$testsuite_name'.\n";
64 exit 1;
65 }
66
67 my @testcases_of_testsuite = $testsuite->findnodes("testcase");
68 for my $testcase (@testcases_of_testsuite) {
69 my $testcase_name = $testcase->getAttribute('name');
70 my @testcases = $testsuite->findnodes("testcase[\@name='$testcase_name']");
71 if (@testcases != 1) {
72 print "ERROR: $XML_TEST_FILENAME: Can't have 2 tests named '$testsuite_name/$testcase_name'.\n";
73 exit 1;
74 }
75 }
76}
77
78#
79# Get the list of tests to skip.
80# For each test to skip, find it in the XML tree and remove its node.
81#
82if (($SKIPPED_LIST_FILENAME) && (open SKIPPED_FILE, "<", $SKIPPED_LIST_FILENAME)) {
83 my @lines = <SKIPPED_FILE>;
84 close $SKIPPED_LIST_FILENAME;
85
86 # Remove the newlines from the end of each line.
87 chomp @lines;
88
89 my $line_no = 0;
90 my $testsuite_name;
91 my $testcase_name;
92 my $index = 0;
93
94 for my $line (@lines) {
95 ++$line_no;
96
97 # Skip empty lines.
98 if ($line =~ /^ *$/) { next; }
99 # Skip comments.
100 if ($line =~ /^#/) { next; }
101
102 ($testsuite_name, $testcase_name) = split('/', $line);
103
104 my @testsuites = $root->findnodes("//testsuite[\@name=\"$testsuite_name\"]");
105 if (!@testsuites) {
106 print "WARNING: $SKIPPED_LIST_FILENAME:$line_no: Test suite '$testsuite_name' doesn't exist or has already been deleted.\n";
107 next;
108 }
109
110 if (!defined $testcase_name) {
111 print "INFO: Testsuite '$testsuite_name' will be skipped.\n";
112 $testsuites[0]->unbindNode();
113 next;
114 }
115
116 my @testcases = $testsuites[0]->findnodes("testcase[\@name=\"$testcase_name\"]");
117 if (!@testcases) {
118 print "WARNING: $SKIPPED_LIST_FILENAME:$line_no: Test case '$testsuite_name/$testcase_name' doesn't exist or has already been deleted.\n";
119 next;
120 }
121
122 print "INFO: Testcase '$testsuite_name/$testcase_name' will be skipped.\n";
123 $testcases[0]->unbindNode();
124 }
125}
126
127
128@all_testcases = $root->findnodes("//testcase");
129
130#
131# Generate the test function prototypes
132#
133my $testcase_count = 0;
134
135print FILE_SRC "#include \"tftf.h\"\n\n";
136
137for my $testcase (@all_testcases) {
138 my $testcase_function = $testcase->getAttribute('function');
139 $testcase_count++;
140 print FILE_SRC "test_result_t $testcase_function(void);\n";
141}
142
143#
144# Generate the header file.
145#
146print FILE_HDR "#ifndef __TEST_LIST_H__\n";
147print FILE_HDR "#define __TEST_LIST_H__\n\n";
148print FILE_HDR "#define TESTCASE_RESULT_COUNT $testcase_count\n\n";
149print FILE_HDR "#endif\n";
150
151#
152# Generate the lists of testcases
153#
154my $testsuite_index = 0;
155my $testcase_index = 0;
156@all_testsuites = $root->findnodes("//testsuite");
157for my $testsuite (@all_testsuites) {
158 my $testsuite_name = $testsuite->getAttribute('name');
159 my @testcases = $testsuite->findnodes("//testsuite[\@name='$testsuite_name']//testcase");
160
161 print FILE_SRC "\nconst test_case_t testcases_${testsuite_index}[] = {\n";
162
163 for my $testcase (@testcases) {
164 my $testcase_name = $testcase->getAttribute('name');
165 my $testcase_description = $testcase->getAttribute('description');
166 my $testcase_function = $testcase->getAttribute('function');
167
168 if (!defined($testcase_description)) { $testcase_description = ""; }
169
170 print FILE_SRC " { $testcase_index, \"$testcase_name\", \"$testcase_description\", $testcase_function },\n";
171
172 $testcase_index++;
173 }
174 print FILE_SRC " { 0, NULL, NULL, NULL }\n";
175 print FILE_SRC "};\n\n";
176 $testsuite_index++;
177}
178
179#
180# Generate the lists of testsuites
181#
182$testsuite_index = 0;
183print FILE_SRC "const test_suite_t testsuites[] = {\n";
184for my $testsuite (@all_testsuites) {
185 my $testsuite_name = $testsuite->getAttribute('name');
186 my $testsuite_description = $testsuite->getAttribute('description');
187 print FILE_SRC " { \"$testsuite_name\", \"$testsuite_description\", testcases_${testsuite_index} },\n";
188 $testsuite_index++;
189}
190print FILE_SRC " { NULL, NULL, NULL }\n";
191print FILE_SRC "};\n";
192