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 <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