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