1 // Copyright 2014, ARM Limited
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include "test-runner.h"
31
32 // Initialize the list as empty.
33 vixl::Test* vixl::Test::first_ = NULL;
34 vixl::Test* vixl::Test::last_ = NULL;
35
36 // No debugger to start with.
37 bool vixl::Test::debug_ = false;
38
39 // No tracing to start with.
40 bool vixl::Test::trace_sim_ = false;
41 bool vixl::Test::trace_reg_ = false;
42 bool vixl::Test::trace_write_ = false;
43
44 // No colour highlight by default.
45 bool vixl::Test::coloured_trace_ = false;
46
47 // No instruction statistics by default.
48 bool vixl::Test::instruction_stats_ = false;
49
50 // Don't generate simulator test traces by default.
51 bool vixl::Test::sim_test_trace_ = false;
52
53 // Instantiate a Test and append it to the linked list.
Test(const char * name,TestFunction * callback)54 vixl::Test::Test(const char* name, TestFunction* callback)
55 : name_(name), callback_(callback), next_(NULL) {
56 // Append this test to the linked list.
57 if (first_ == NULL) {
58 VIXL_ASSERT(last_ == NULL);
59 first_ = this;
60 } else {
61 last_->next_ = this;
62 }
63 last_ = this;
64 }
65
66
67 // Look for 'search' in the arguments.
IsInArgs(const char * search,int argc,char * argv[])68 static bool IsInArgs(const char* search, int argc, char* argv[]) {
69 for (int i = 1; i < argc; i++) {
70 if (strcmp(search, argv[i]) == 0) {
71 return true;
72 }
73 }
74 return false;
75 }
76
77
IsOption(const char * arg)78 static bool IsOption(const char* arg) {
79 // Any argument like "--option" is an option.
80 return ((arg[0] == '-') && (arg[1] == '-'));
81 }
82
83
NormalizeOption(char * arg)84 static void NormalizeOption(char * arg) {
85 // Squash all '_' characters in options. This allows --trace_sim and
86 // --trace-sim to be handled in the same way, for example.
87 VIXL_ASSERT(IsOption(arg));
88 for (char * c = arg; *c != '\0'; c++) {
89 if (*c == '_') {
90 *c = '-';
91 }
92 }
93 }
94
95
PrintHelpMessage()96 static void PrintHelpMessage() {
97 printf("Usage: ./test [options] [test names]\n"
98 "Run all tests specified on the command line.\n"
99 "--help Print this help message.\n"
100 "--list List all available tests.\n"
101 "--run_all Run all available tests.\n"
102 "--debugger Run in the debugger.\n"
103 "--trace_all Enable all trace options, plus --coloured_trace.\n"
104 "--trace_sim Generate a trace of simulated instructions, as\n"
105 " well as disassembly from the DISASM tests.\n"
106 "--trace_reg Generate a trace of simulated registers.\n"
107 "--trace_write Generate a trace of memory writes.\n"
108 "--coloured_trace Generate coloured trace.\n"
109 "--instruction_stats Log instruction statistics to vixl_stats.csv.\n"
110 "--sim_test_trace Print result traces for SIM_* tests.\n");
111 }
112
main(int argc,char * argv[])113 int main(int argc, char* argv[]) {
114 // Parse the arguments. Option flags must appear first, followed by an
115 // optional list of tests to run.
116
117 int test_specifiers = 0;
118 for (int i = 1; i < argc; i++) {
119 if (IsOption(argv[i])) {
120 NormalizeOption(argv[i]);
121 } else {
122 // Anything that isn't an option is a test specifier.
123 test_specifiers++;
124 }
125 }
126
127 // Options controlling test conditions and debug output.
128
129 if (IsInArgs("--trace-all", argc, argv)) {
130 vixl::Test::set_trace_reg(true);
131 vixl::Test::set_trace_write(true);
132 vixl::Test::set_trace_sim(true);
133 vixl::Test::set_coloured_trace(true);
134 }
135
136 if (IsInArgs("--coloured-trace", argc, argv)) {
137 vixl::Test::set_coloured_trace(true);
138 }
139
140 if (IsInArgs("--debugger", argc, argv)) {
141 vixl::Test::set_debug(true);
142 }
143
144 if (IsInArgs("--trace-write", argc, argv)) {
145 vixl::Test::set_trace_write(true);
146 }
147
148 if (IsInArgs("--trace-reg", argc, argv)) {
149 vixl::Test::set_trace_reg(true);
150 }
151
152 if (IsInArgs("--trace-sim", argc, argv)) {
153 vixl::Test::set_trace_sim(true);
154 }
155
156 if (IsInArgs("--instruction-stats", argc, argv)) {
157 vixl::Test::set_instruction_stats(true);
158 }
159
160 if (IsInArgs("--sim-test-trace", argc, argv)) {
161 vixl::Test::set_sim_test_trace(true);
162 }
163
164 // Basic (mutually-exclusive) operations.
165
166 if (IsInArgs("--help", argc, argv)) {
167 PrintHelpMessage();
168
169 } else if (IsInArgs("--list", argc, argv)) {
170 // List all registered tests, then exit.
171 for (vixl::Test* c = vixl::Test::first(); c != NULL; c = c->next()) {
172 printf("%s\n", c->name());
173 }
174
175 } else if (IsInArgs("--run-all", argc, argv)) {
176 // Run all registered tests.
177 for (vixl::Test* c = vixl::Test::first(); c != NULL; c = c->next()) {
178 printf("Running %s\n", c->name());
179 c->callback()();
180 }
181
182 } else {
183 // Run the specified tests.
184 if (test_specifiers == 0) {
185 printf("No tests specified.\n");
186 PrintHelpMessage();
187 return EXIT_FAILURE;
188 }
189
190 for (int i = 1; i < argc; i++) {
191 if (!IsOption(argv[i])) {
192 vixl::Test* c;
193 for (c = vixl::Test::first(); c != NULL; c = c->next()) {
194 if (strcmp(c->name(), argv[i]) == 0) {
195 c->callback()();
196 break;
197 }
198 }
199 // Fail if we have not found a matching test to run.
200 if (c == NULL) {
201 printf("Test '%s' does not exist. Aborting...\n", argv[i]);
202 abort();
203 }
204 }
205 }
206 }
207
208 return EXIT_SUCCESS;
209 }
210
211