defaultreporter.h
Go to the documentation of this file.
1 // HippoMocks, a library for using mocks in unit testing of C++ code.
2 // Copyright (C) 2008, Bas van Tiel, Christian Rexwinkel, Mike Looijmans,
3 // Peter Bindels
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 //
19 // You can also retrieve it from http://www.gnu.org/licenses/lgpl-2.1.html
20 
21 #ifndef HIPPOMOCKS_DEFAULTREPORTER_H
22 #define HIPPOMOCKS_DEFAULTREPORTER_H
23 
24 #ifndef DEBUGBREAK
25 #ifdef _MSC_VER
26 extern "C" __declspec(dllimport) int WINCALL IsDebuggerPresent();
27 extern "C" __declspec(dllimport) void WINCALL DebugBreak();
28 #define DEBUGBREAK(e) if (IsDebuggerPresent()) DebugBreak(); else (void)0
29 #else
30 #define DEBUGBREAK(e)
31 #endif
32 #endif
33 
34 #if !defined(HM_NO_EXCEPTIONS)
35 #include <iostream>
36 #include <sstream>
37 #include <cstring>
38 
39 inline std::ostream &operator<<(std::ostream &os, const Call &call)
40 {
41  os << call.fileName << "(" << call.lineno << ") ";
42  if (call.expectation == Once)
43  os << "Expectation for ";
44  else
45  os << "Result set for ";
46 
47  os << call.funcName;
48 
49  call.printArgs(os);
50 
51  os << " on the mock at 0x" << call.mock << " was ";
52 
53  if (!call.isSatisfied())
54  os << "not ";
55 
56  if (call.expectation == Once)
57  os << "satisfied." << std::endl;
58  else
59  os << "used." << std::endl;
60 
61  return os;
62 }
63 
64 inline std::ostream &operator<<(std::ostream &os, const MockRepository &repo)
65 {
66  if (repo.expectations.size())
67  {
68  os << "Expectations set:" << std::endl;
69  for (auto &exp : repo.expectations)
70  os << *exp;
71  os << std::endl;
72  }
73 
74  if (repo.neverCalls.size())
75  {
76  os << "Functions explicitly expected to not be called:" << std::endl;
77  for (auto &nc : repo.neverCalls)
78  os << *nc;
79  os << std::endl;
80  }
81 
82  if (repo.optionals.size())
83  {
84  os << "Optional results set up:" << std::endl;
85  for (auto &opt : repo.optionals)
86  os << *opt;
87  os << std::endl;
88  }
89  return os;
90 }
91 
92 #include <exception>
93 #ifndef BASE_EXCEPTION
94 #define BASE_EXCEPTION std::exception
95 #endif
96 #define RAISEEXCEPTION(e) { DEBUGBREAK(e); if (std::uncaught_exception()) latentException = [=, &repo]{ throw e; }; else throw e; }
97 
99  : public BASE_EXCEPTION
100 {
101 public:
102  ~BaseException() throw() {}
103  const char *what() const throw() { return txt.c_str(); }
104 protected:
106 };
107 
109 {
110 public:
111  ExpectationException(MockRepository &repo, const std::string &args, const char *funcName)
112  {
113  std::stringstream text;
114  text << "Function " << funcName << args << " called with mismatching expectation!" << std::endl;
115  text << repo;
116  txt = text.str();
117  }
118 };
119 
120 #ifdef LINUX_TARGET
121 #include <execinfo.h>
122 #endif
123 
125 {
126 public:
127  NotImplementedException(MockRepository &repo)
128  {
129  std::stringstream text;
130  text << "Function called without expectation!" << std::endl;
131  text << repo;
132 
133 #ifdef LINUX_TARGET
134  void *stacktrace[256];
135  size_t size = backtrace(stacktrace, sizeof(stacktrace));
136  if (size > 0)
137  {
138  text << "Stackdump:" << std::endl;
139  char **symbols = backtrace_symbols(stacktrace, size);
140  for (size_t i = 0; i < size; i = i + 1)
141  {
142  text << symbols[i] << std::endl;
143  }
144  free(symbols);
145  }
146 #endif
147 
148  txt = text.str();
149  }
150 };
151 
153 {
154 public:
155  CallMissingException(MockRepository &repo)
156  {
157  std::stringstream text;
158  text << "Function with expectation not called!" << std::endl;
159  text << repo;
160  txt = text.str();
161  }
162 };
163 
165 {
166 public:
167  ZombieMockException(MockRepository &repo)
168  {
169  std::stringstream text;
170  text << "Function called on mock that has already been destroyed!" << std::endl;
171  text << repo;
172 
173 #ifdef LINUX_TARGET
174  void *stacktrace[256];
175  size_t size = backtrace(stacktrace, sizeof(stacktrace));
176  if (size > 0)
177  {
178  text << "Stackdump:" << std::endl;
179  char **symbols = backtrace_symbols(stacktrace, size);
180  for (size_t i = 0; i < size; i = i + 1)
181  {
182  text << symbols[i] << std::endl;
183  }
184  free(symbols);
185  }
186 #endif
187 
188  txt = text.str();
189  }
190 };
191 
193 {
194 public:
195  NoResultSetUpException(MockRepository &repo, const std::string &args, const char *funcName)
196  {
197  std::stringstream text;
198  text << "No result set up on call to " << funcName << args << std::endl << repo;
199 
200 #ifdef LINUX_TARGET
201  void *stacktrace[256];
202  size_t size = backtrace(stacktrace, sizeof(stacktrace));
203  if (size > 0)
204  {
205  text << "Stackdump:" << std::endl;
206  char **symbols = backtrace_symbols(stacktrace, size);
207  for (size_t i = 0; i < size; i = i + 1)
208  {
209  text << symbols[i] << std::endl;
210  }
211  free(symbols);
212  }
213 #endif
214 
215  txt = text.str();
216  }
217 };
218 
220 {
221  static struct DefaultReporter : Reporter
222  {
223  DefaultReporter() : latentException([] {}) {}
224  std::function<void()> latentException;
225  void CallMissing(Call &call, MockRepository &repo) override
226  {
227  (void)call;
229  }
230  void ExpectationExceeded(Call &call, MockRepository &repo, const std::string &args, const char *funcName) override
231  {
232  (void)call;
233  RAISEEXCEPTION(ExpectationException(repo, args, funcName));
234  }
235  void FunctionCallToZombie(MockRepository &repo, const std::string &args) override
236  {
237  (void)args;
239  }
240  void InvalidBaseOffset(size_t baseOffset, MockRepository &repo) override
241  {
242  (void)baseOffset;
243  (void)repo;
244  std::terminate();
245  }
246  void InvalidFuncIndex(size_t funcIndex, MockRepository &repo) override
247  {
248  (void)funcIndex;
249  (void)repo;
250  std::terminate();
251  }
252  void NoExpectationMatches(MockRepository &repo, const std::string &args, const char *funcName) override
253  {
254  RAISEEXCEPTION(ExpectationException(repo, args, funcName));
255  }
256  void NoResultSetUp(Call &call, MockRepository &repo, const std::string &args, const char *funcName) override
257  {
258  (void)call;
259  RAISEEXCEPTION(NoResultSetUpException(repo, args, funcName));
260  }
261  void UnknownFunction(MockRepository &repo) override
262  {
264  }
265  void TestStarted() override
266  {
267  latentException = [] {};
268  }
269  void TestFinished() override
270  {
271  if (!std::uncaught_exception() && latentException)
272  {
273  latentException();
274  }
275  }
276  } defaultReporter;
277  return &defaultReporter;
278 }
279 
280 #endif
281 
282 #endif
void free(void *ptr)
Definition: syscall.cpp:370
NotImplementedException(MockRepository &repo)
virtual void InvalidBaseOffset(size_t baseOffset, MockRepository &repo)=0
virtual void CallMissing(Call &call, MockRepository &repo)=0
std::string txt
#define BASE_EXCEPTION
virtual void UnknownFunction(MockRepository &repo)=0
ExpectationException(MockRepository &repo, const std::string &args, const char *funcName)
constexpr const auto size
NoResultSetUpException(MockRepository &repo, const std::string &args, const char *funcName)
CallMissingException(MockRepository &repo)
virtual void FunctionCallToZombie(MockRepository &repo, const std::string &args)=0
Reporter * GetDefaultReporter()
virtual void NoResultSetUp(Call &call, MockRepository &repo, const std::string &args, const char *funcName)=0
std::ostream & operator<<(std::ostream &os, const Call &call)
#define RAISEEXCEPTION(e)
ZombieMockException(MockRepository &repo)
virtual void TestFinished()=0
const char * what() const
virtual void NoExpectationMatches(MockRepository &repo, const std::string &args, const char *funcName)=0
virtual void TestStarted()=0
virtual void ExpectationExceeded(Call &call, MockRepository &repo, const std::string &args, const char *funcName)=0
virtual void InvalidFuncIndex(size_t funcIndex, MockRepository &repo)=0