Home | History | Annotate | Download | only in test
      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