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