blitzdg
an open-source project aiming to implement parallel discontinuous Galerkin (dg) solvers for common partial differential equations systems using blitz++ for array and tensor manipulations and MPI for distributed parallelism.
testrunner.h
1 
2 // Copyright Joakim Karlsson & Kim Gräsman 2010-2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef IGLOO_TESTRUNNER_H
8 #define IGLOO_TESTRUNNER_H
9 
10 #include <igloo/core/testresult.h>
11 #include <igloo/core/testresults.h>
12 #include <igloo/core/testlisteners/minimalprogresstestlistener.h>
13 #include <igloo/external/choices/choices.h>
14 
15 namespace igloo {
16 
17  namespace c = choices;
18 
19  class TestRunner
20  {
21  public:
22  typedef std::list<BaseContextRunner*> ContextRunners;
23 
24  static int RunAllTests(int argc = 0, const char *argv[] = 0)
25  {
26  choices::options opt = choices::parse_cmd(argc, argv);
27 
28  if(c::has_option("version", opt))
29  {
30  std::cout << IGLOO_VERSION << std::endl;
31  return 0;
32  }
33 
34  if(c::has_option("help", opt))
35  {
36  std::cout << "Usage: <igloo-executable> [--version] [--output=color|vs|xunit]" << std::endl;
37  std::cout << "Options:" << std::endl;
38  std::cout << " --version:\tPrint version of igloo and exit." << std::endl;
39  std::cout << " --output:\tFormat output of test results." << std::endl;
40  std::cout << "\t\t--output=color:\tColored output" << std::endl;
41  std::cout << "\t\t--output=vs:\tVisual studio friendly output." << std::endl;
42  std::cout << "\t\t--output=xunit:\tXUnit formatted output." << std::endl;
43  std::cout << "\t\t--output=default:\tDefault output format." << std::endl;
44  return 0;
45  }
46 
47  std::auto_ptr<TestResultsOutput> output;
48  if(c::has_option("output", opt))
49  {
50  std::string val = c::option_value("output", opt);
51  if(val == "vs")
52  {
53  output = std::auto_ptr<TestResultsOutput>(new VisualStudioResultsOutput());
54  }
55  else if(val == "color")
56  {
57  output = std::auto_ptr<TestResultsOutput>(new ColoredConsoleTestResultsOutput());
58  }
59  else if(val == "xunit")
60  {
61  output = std::auto_ptr<TestResultsOutput>(new XUnitResultsOutput());
62  }
63  else if(val == "default")
64  {
65  output = std::auto_ptr<TestResultsOutput>(new DefaultTestResultsOutput());
66  }
67  else
68  {
69  std::cerr << "Unknown output: " << c::option_value("output", opt) << std::endl;
70  return 1;
71  }
72  }
73  else
74  {
75  output = std::auto_ptr<TestResultsOutput>(new DefaultTestResultsOutput());
76  }
77 
78 
79  TestRunner runner(*(output.get()));
80 
81  MinimalProgressTestListener progressOutput;
82  runner.AddListener(&progressOutput);
83 
84  return runner.Run();
85  }
86 
87 
88  TestRunner(const TestResultsOutput& output)
89  : output_(output)
90  {}
91 
92  static bool is_only(const BaseContextRunner* runner)
93  {
94  return runner->IsContextMarkedAsOnly();
95  }
96 
97  int Run(const ContextRunners& runners)
98  {
99  TestResults results;
100 
101  listenerAggregator_.TestRunStarting();
102 
103  bool only_has_been_found = std::find_if(runners.begin(), runners.end(), is_only) != runners.end();
104 
105  for (ContextRunners::const_iterator it = runners.begin(); it != runners.end(); it++)
106  {
107  BaseContextRunner* contextRunner = *it;
108  if(!only_has_been_found || contextRunner->IsContextMarkedAsOnly()) {
109  if(!contextRunner->IsMarkedAsSkip()) {
110  contextRunner->Run(results, listenerAggregator_);
111  }
112  }
113  }
114 
115  listenerAggregator_.TestRunEnded(results);
116 
117  output_.PrintResult(results);
118  return results.NumberOfFailedTests();
119  }
120 
121  int Run()
122  {
123  int numberOfFailedTests = Run(RegisteredRunners());
124  CleanUpRunners();
125  return numberOfFailedTests;
126  }
127 
128 
129  template <typename ContextRunnerType>
130  static void RegisterContext(const std::string& name, const char* fileName, int lineNumber)
131  {
132  if(!ContextIsRegistered(name, fileName, lineNumber))
133  {
134  ContextRunnerType* contextRunner = 0;
135 
136  try
137  {
138  // Must add runner first...
139  contextRunner = new ContextRunnerType(name, fileName, lineNumber);
140  TestRunner::RegisteredRunners().push_back(contextRunner);
141 
142  // ... and then instantiate context, because context ctor calls this method again,
143  // possibly for the same context, depending on inheritance chain.
144  contextRunner->InstantiateContext();
145  }
146  catch (...)
147  {
148  delete contextRunner;
149  throw;
150  }
151  }
152  }
153 
154  void AddListener(TestListener* listener)
155  {
156  listenerAggregator_.AddListener(listener);
157  }
158 
159  private:
160  static void CleanUpRunners()
161  {
162  while(!RegisteredRunners().empty())
163  {
164  delete RegisteredRunners().front();
165  RegisteredRunners().pop_front();
166  }
167  }
168 
169  static bool ContextIsRegistered(const std::string& name, const char* fileName, int lineNumber)
170  {
171  for (ContextRunners::const_iterator it = RegisteredRunners().begin(); it != RegisteredRunners().end(); ++it)
172  {
173  if((*it)->ContextName() == name &&
174  (*it)->FileName() == fileName &&
175  (*it)->LineNumber() == lineNumber)
176  {
177  return true;
178  }
179  }
180 
181  return false;
182  }
183 
184  static TestRunner::ContextRunners& RegisteredRunners()
185  {
186  static TestRunner::ContextRunners contextRunners;
187  return contextRunners;
188  }
189 
190  private:
191  const TestResultsOutput& output_;
192  TestListenerAggregator listenerAggregator_;
193  };
194 }
195 
196 #endif // IGLOO_TESTRUNNER_H
Definition: testresultsoutput.h:12
Definition: testlistener.h:14
Definition: testlisteneraggregator.h:11
Definition: minimalprogresstestlistener.h:12
Definition: contextrunner.h:13
Definition: visualstudiooutput.h:12
Definition: xunitoutput.h:15
Definition: defaulttestresultsoutput.h:12
Definition: testrunner.h:19
Definition: context.h:13
Definition: coloredconsoletestresultsoutput.h:13
Definition: choices.h:27
Definition: testresults.h:12