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