1 // Copyright 2014, VIXL authors 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 <cstdio> 28 #include <cstdlib> 29 #include <cstring> 30 31 #include "test-runner.h" 32 33 // Initialize the list as empty. 34 vixl::Test* vixl::Test::first_ = NULL; 35 vixl::Test* vixl::Test::last_ = NULL; 36 37 bool vixl::Test::verbose_ = false; 38 39 // No debugger to start with. 40 bool vixl::Test::debug_ = false; 41 42 // No tracing to start with. 43 bool vixl::Test::trace_sim_ = false; 44 bool vixl::Test::trace_reg_ = false; 45 bool vixl::Test::trace_write_ = false; 46 bool vixl::Test::trace_branch_ = false; 47 48 // Do not disassemble by default. 49 bool vixl::Test::disassemble_ = false; 50 bool vixl::Test::disassemble_infrastructure_ = false; 51 52 // No colour highlight by default. 53 bool vixl::Test::coloured_trace_ = false; 54 55 // No instruction statistics by default. 56 bool vixl::Test::instruction_stats_ = false; 57 58 // Don't generate traces by default. 59 bool vixl::Test::generate_test_trace_ = false; 60 61 // Instantiate a Test and append it to the linked list. 62 vixl::Test::Test(const char* name, TestFunction* callback) 63 : name_(name), callback_(callback), next_(NULL) { 64 // Append this test to the linked list. 65 if (first_ == NULL) { 66 VIXL_ASSERT(last_ == NULL); 67 first_ = this; 68 } else { 69 last_->next_ = this; 70 } 71 last_ = this; 72 } 73 74 75 // Look for 'search' in the arguments. 76 static bool IsInArgs(const char* search, int argc, char* argv[]) { 77 for (int i = 1; i < argc; i++) { 78 if (strcmp(search, argv[i]) == 0) { 79 return true; 80 } 81 } 82 return false; 83 } 84 85 86 static bool IsOption(const char* arg) { 87 // Any argument like "--option" is an option. 88 return ((arg[0] == '-') && (arg[1] == '-')); 89 } 90 91 92 static void NormalizeOption(char* arg) { 93 // Squash all '_' characters in options. This allows --trace_sim and 94 // --trace-sim to be handled in the same way, for example. 95 VIXL_ASSERT(IsOption(arg)); 96 for (char* c = arg; *c != '\0'; c++) { 97 if (*c == '_') { 98 *c = '-'; 99 } 100 } 101 } 102 103 104 static void PrintHelpMessage() { 105 printf( 106 "Usage: ./test [options] [test names]\n" 107 "Run all tests specified on the command line.\n" 108 "--help Print this help message.\n" 109 "--list List all available tests.\n" 110 "--run_all Run all available tests.\n" 111 "--verbose Print verbose output when available.\n" 112 "--debugger Run in the debugger.\n" 113 "--trace_all " 114 "Enable all trace options, plus --coloured_trace.\n" 115 "--trace_sim " 116 "Generate a trace of simulated instructions, as\n" 117 " well as disassembly from the DISASM tests.\n" 118 "--trace_reg Generate a trace of simulated registers.\n" 119 "--trace_write Generate a trace of memory writes.\n" 120 "--trace_branch Generate a trace of branches taken.\n" 121 "--disassemble Disassemble and print generated instructions.\n" 122 "--disassemble-test-code " 123 "As above, but don't disassemble infrastructure code.\n" 124 "--coloured_trace Generate coloured trace.\n" 125 "--instruction_stats Log instruction statistics to vixl_stats.csv.\n" 126 "--generate_test_trace " 127 "Print result traces for SIM_* and TRACE_* tests.\n"); 128 } 129 130 int main(int argc, char* argv[]) { 131 // Parse the arguments. Option flags must appear first, followed by an 132 // optional list of tests to run. 133 134 int test_specifiers = 0; 135 for (int i = 1; i < argc; i++) { 136 if (IsOption(argv[i])) { 137 NormalizeOption(argv[i]); 138 } else { 139 // Anything that isn't an option is a test specifier. 140 test_specifiers++; 141 } 142 } 143 144 // Options controlling test conditions and debug output. 145 146 if (IsInArgs("--trace-all", argc, argv)) { 147 vixl::Test::set_trace_reg(true); 148 vixl::Test::set_trace_write(true); 149 vixl::Test::set_trace_branch(true); 150 vixl::Test::set_trace_sim(true); 151 vixl::Test::set_coloured_trace(true); 152 } 153 154 if (IsInArgs("--coloured-trace", argc, argv)) { 155 vixl::Test::set_coloured_trace(true); 156 } 157 158 if (IsInArgs("--verbose", argc, argv)) { 159 vixl::Test::set_verbose(true); 160 } 161 162 if (IsInArgs("--debugger", argc, argv)) { 163 vixl::Test::set_debug(true); 164 } 165 166 if (IsInArgs("--trace-write", argc, argv)) { 167 vixl::Test::set_trace_write(true); 168 } 169 170 if (IsInArgs("--trace-branch", argc, argv)) { 171 vixl::Test::set_trace_branch(true); 172 } 173 174 if (IsInArgs("--trace-reg", argc, argv)) { 175 vixl::Test::set_trace_reg(true); 176 } 177 178 if (IsInArgs("--trace-sim", argc, argv)) { 179 vixl::Test::set_trace_sim(true); 180 } 181 182 if (IsInArgs("--disassemble", argc, argv)) { 183 vixl::Test::set_disassemble(true); 184 vixl::Test::set_disassemble_infrastructure(true); 185 } else if (IsInArgs("--disassemble-test-code", argc, argv)) { 186 vixl::Test::set_disassemble(true); 187 vixl::Test::set_disassemble_infrastructure(false); 188 } 189 190 if (IsInArgs("--instruction-stats", argc, argv)) { 191 vixl::Test::set_instruction_stats(true); 192 } 193 194 if (IsInArgs("--generate-test-trace", argc, argv)) { 195 vixl::Test::set_generate_test_trace(true); 196 } 197 198 // Basic (mutually-exclusive) operations. 199 200 if (IsInArgs("--help", argc, argv)) { 201 PrintHelpMessage(); 202 203 } else if (IsInArgs("--list", argc, argv)) { 204 // List all registered tests, then exit. 205 for (vixl::Test* c = vixl::Test::first(); c != NULL; c = c->next()) { 206 printf("%s\n", c->name()); 207 } 208 209 } else if (IsInArgs("--run-all", argc, argv)) { 210 // Run all registered tests. 211 for (vixl::Test* c = vixl::Test::first(); c != NULL; c = c->next()) { 212 printf("Running %s\n", c->name()); 213 c->callback()(); 214 } 215 216 } else { 217 // Run the specified tests. 218 if (test_specifiers == 0) { 219 printf("No tests specified.\n"); 220 PrintHelpMessage(); 221 return EXIT_FAILURE; 222 } 223 224 for (int i = 1; i < argc; i++) { 225 if (!IsOption(argv[i])) { 226 vixl::Test* c; 227 for (c = vixl::Test::first(); c != NULL; c = c->next()) { 228 if (strcmp(c->name(), argv[i]) == 0) { 229 c->callback()(); 230 break; 231 } 232 } 233 // Fail if we have not found a matching test to run. 234 if (c == NULL) { 235 printf("Test '%s' does not exist. Aborting...\n", argv[i]); 236 abort(); 237 } 238 } 239 } 240 } 241 242 return EXIT_SUCCESS; 243 } 244