1// Copyright Joakim Karlsson & Kim Gräsman 2010-2012.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef SNOWHOUSE_ASSERT_H
7#define SNOWHOUSE_ASSERT_H
8
9#include "assertionexception.h"
10#include "fluent/expressionbuilder.h"
11
12// clang-format off
13#define SNOWHOUSE_ASSERT_THAT(P1, P2, FAILURE_HANDLER) \
14 ::snowhouse::ConfigurableAssert<FAILURE_HANDLER>::That((P1), (P2), __FILE__, __LINE__)
15
16#ifndef SNOWHOUSE_NO_MACROS
17# define AssertThat(P1, P2) \
18 SNOWHOUSE_ASSERT_THAT((P1), (P2), ::snowhouse::DefaultFailureHandler)
19#endif
20// clang-format on
21
22namespace snowhouse
23{
24 struct DefaultFailureHandler
25 {
26 template<typename ExpectedType, typename ActualType>
27 static void Handle(const ExpectedType& expected, const ActualType& actual, const char* file_name, int line_number)
28 {
29 std::ostringstream str;
30
31 str << "Expected: " << snowhouse::Stringize(expected) << std::endl;
32 str << "Actual: " << snowhouse::Stringize(actual) << std::endl;
33
34 throw AssertionException(str.str(), file_name, line_number);
35 }
36
37 static void Handle(const std::string& message)
38 {
39 throw AssertionException(message);
40 }
41 };
42
43 template<typename FailureHandler>
44 struct ConfigurableAssert
45 {
46 template<typename ActualType, typename ConstraintListType>
47 static void That(const ActualType& actual, ExpressionBuilder<ConstraintListType> expression, const char* file_name = "", int line_number = 0)
48 {
49 try
50 {
51 ResultStack result;
52 OperatorStack operators;
53 expression.Evaluate(result, operators, actual);
54
55 while (!operators.empty())
56 {
57 ConstraintOperator* op = operators.top();
58 op->PerformOperation(result);
59 operators.pop();
60 }
61
62 if (result.empty())
63 {
64 throw InvalidExpressionException("The expression did not yield any result");
65 }
66
67 if (!result.top())
68 {
69 FailureHandler::Handle(expression, actual, file_name, line_number);
70 }
71 }
72 catch (const InvalidExpressionException& e)
73 {
74 FailureHandler::Handle("Malformed expression: \"" + snowhouse::Stringize(expression) + "\"\n" + e.Message());
75 }
76 }
77
78 template<typename ConstraintListType>
79 static void That(const char* actual, ExpressionBuilder<ConstraintListType> expression, const char* file_name = "", int line_number = 0)
80 {
81 return That(std::string(actual), expression, file_name, line_number);
82 }
83
84 template<typename ActualType, typename ExpressionType>
85 static void That(const ActualType& actual, const ExpressionType& expression, const char* file_name = "", int line_number = 0)
86 {
87 if (!expression(actual))
88 {
89 FailureHandler::Handle(expression, actual, file_name, line_number);
90 }
91 }
92
93 template<typename ExpressionType>
94 static void That(const char* actual, const ExpressionType& expression, const char* file_name = "", int line_number = 0)
95 {
96 return That(std::string(actual), expression, file_name, line_number);
97 }
98
99 static void That(bool actual)
100 {
101 if (!actual)
102 {
103 FailureHandler::Handle("Expected: true\nActual: false");
104 }
105 }
106
107 static void Failure(const std::string& message)
108 {
109 FailureHandler::Handle(message);
110 }
111 };
112
113 typedef ConfigurableAssert<DefaultFailureHandler> Assert;
114}
115
116#endif
117