1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2003, 2004, 2008 StatPro Italia srl
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#ifndef quantlib_test_utilities_hpp
21#define quantlib_test_utilities_hpp
22
23#include <ql/indexes/indexmanager.hpp>
24#include <ql/instruments/payoffs.hpp>
25#include <ql/exercise.hpp>
26#include <ql/termstructures/yieldtermstructure.hpp>
27#include <ql/termstructures/volatility/equityfx/blackvoltermstructure.hpp>
28#include <ql/quote.hpp>
29#include <ql/patterns/observable.hpp>
30#include <ql/time/daycounters/actual365fixed.hpp>
31#include <ql/functional.hpp>
32#include <boost/test/unit_test.hpp>
33#if BOOST_VERSION < 105900
34#include <boost/test/floating_point_comparison.hpp>
35#else
36#include <boost/test/tools/floating_point_comparison.hpp>
37#endif
38#include <cmath>
39#include <iomanip>
40#include <numeric>
41#include <string>
42#include <utility>
43#include <vector>
44
45// This adapts the BOOST_CHECK_SMALL and BOOST_CHECK_CLOSE macros to
46// support a struct as Real for arguments, while fully transparant to regular doubles.
47// Unfortunately boost does not provide a portable way to customize these macros' behaviour,
48// so we need to define wrapper macros QL_CHECK_SMALL etc.
49//
50// It is required to have a function `value` defined that returns the double-value
51// of the Real type (or a value function in the Real type's namespace for ADT).
52
53namespace QuantLib {
54 // overload this function in case Real is something different - it should alway return double
55 inline double value(double x) {
56 return x;
57 }
58}
59
60using QuantLib::value;
61
62#define QL_CHECK_SMALL(FPV, T) BOOST_CHECK_SMALL(value(FPV), value(T))
63#define QL_CHECK_CLOSE(L, R, T) BOOST_CHECK_CLOSE(value(L), value(R), value(T))
64
65
66// This makes it easier to use array literals (for new code, use std::vector though)
67#define LENGTH(a) (sizeof(a)/sizeof(a[0]))
68
69#define QUANTLIB_TEST_CASE(f) BOOST_TEST_CASE(QuantLib::detail::quantlib_test_case(f))
70
71namespace QuantLib {
72
73 namespace detail {
74
75 // used to avoid no-assertion messages in Boost 1.35
76 class quantlib_test_case {
77 ext::function<void()> test_;
78 public:
79 template <class F>
80 explicit quantlib_test_case(F test) : test_(test) {}
81 void operator()() const {
82 // Restore settings after each test.
83 SavedSettings restore;
84 // Clear all fixings before running a test to avoid interference.
85 IndexManager::instance().clearHistories();
86 BOOST_CHECK(true);
87 test_();
88 }
89 #if BOOST_VERSION <= 105300
90 // defined to avoid unused-variable warnings. It doesn't
91 // work after Boost 1.53 because the functions were
92 // overloaded and the address can't be resolved.
93 void _use_check(
94 const void* = &boost::test_tools::check_is_close,
95 const void* = &boost::test_tools::check_is_small) const {}
96 #endif
97 };
98
99 }
100
101 std::string payoffTypeToString(const ext::shared_ptr<Payoff>&);
102 std::string exerciseTypeToString(const ext::shared_ptr<Exercise>&);
103
104
105 ext::shared_ptr<YieldTermStructure>
106 flatRate(const Date& today,
107 const ext::shared_ptr<Quote>& forward,
108 const DayCounter& dc);
109
110 ext::shared_ptr<YieldTermStructure>
111 flatRate(const Date& today,
112 Rate forward,
113 const DayCounter& dc);
114
115 ext::shared_ptr<YieldTermStructure>
116 flatRate(const ext::shared_ptr<Quote>& forward,
117 const DayCounter& dc);
118
119 ext::shared_ptr<YieldTermStructure>
120 flatRate(Rate forward,
121 const DayCounter& dc);
122
123
124 ext::shared_ptr<BlackVolTermStructure>
125 flatVol(const Date& today,
126 const ext::shared_ptr<Quote>& volatility,
127 const DayCounter& dc);
128
129 ext::shared_ptr<BlackVolTermStructure>
130 flatVol(const Date& today,
131 Volatility volatility,
132 const DayCounter& dc);
133
134 ext::shared_ptr<BlackVolTermStructure>
135 flatVol(const ext::shared_ptr<Quote>& volatility,
136 const DayCounter& dc);
137
138 ext::shared_ptr<BlackVolTermStructure>
139 flatVol(Volatility volatility,
140 const DayCounter& dc);
141
142
143 Real relativeError(Real x1, Real x2, Real reference);
144
145 //bool checkAbsError(Real x1, Real x2, Real tolerance){
146 // return std::fabs(x1 - x2) < tolerance;
147 //};
148
149 class Flag : public QuantLib::Observer {
150 private:
151 bool up_ = false;
152
153 public:
154 Flag() = default;
155 void raise() { up_ = true; }
156 void lower() { up_ = false; }
157 bool isUp() const { return up_; }
158 void update() override { raise(); }
159 };
160
161 template<class Iterator>
162 Real norm(const Iterator& begin, const Iterator& end, Real h) {
163 // squared values
164 std::vector<Real> f2(end-begin);
165 std::transform(begin, end, begin, f2.begin(), std::multiplies<>());
166 // numeric integral of f^2
167 Real I = h * (std::accumulate(first: f2.begin(),last: f2.end(),init: Real(0.0))
168 - 0.5*f2.front() - 0.5*f2.back());
169 return std::sqrt(x: I);
170 }
171
172
173 inline Integer timeToDays(Time t, Integer daysPerYear = 360) {
174 return Integer(std::lround(x: t * daysPerYear));
175 }
176
177
178 // Used to check that an exception message contains the expected message string
179 struct ExpectedErrorMessage {
180
181 explicit ExpectedErrorMessage(std::string msg) : expected(std::move(msg)) {}
182
183 bool operator()(const Error& ex) const {
184 std::string actual(ex.what());
185 if (actual.find(str: expected) == std::string::npos) {
186 BOOST_TEST_MESSAGE("Error expected to contain: '" << expected << "'.");
187 BOOST_TEST_MESSAGE("Actual error is: '" << actual << "'.");
188 return false;
189 } else {
190 return true;
191 }
192 }
193
194 std::string expected;
195 };
196
197
198 // Allow streaming vectors to error messages.
199
200 // The standard forbids defining new overloads in the std
201 // namespace, so we have to use a wrapper instead of overloading
202 // operator<< to send a vector to the stream directly.
203 // Defining the overload outside the std namespace wouldn't work
204 // with Boost streams because of ADT name lookup rules.
205
206 template <class T>
207 struct vector_streamer {
208 explicit vector_streamer(std::vector<T> v) : v(std::move(v)) {}
209 std::vector<T> v;
210 };
211
212 template <class T>
213 vector_streamer<T> to_stream(const std::vector<T>& v) {
214 return vector_streamer<T>(v);
215 }
216
217 template <class T>
218 std::ostream& operator<<(std::ostream& out, const vector_streamer<T>& s) {
219 out << "{ ";
220 if (!s.v.empty()) {
221 for (size_t n=0; n<s.v.size()-1; ++n)
222 out << s.v[n] << ", ";
223 out << s.v.back();
224 }
225 out << " }";
226 return out;
227 }
228
229
230}
231
232
233#endif
234

source code of quantlib/test-suite/utilities.hpp