1 | |
2 | #ifndef BOOST_CONTRACT_TEST_DETAIL_OTESTSTREAM_HPP_ |
3 | #define BOOST_CONTRACT_TEST_DETAIL_OTESTSTREAM_HPP_ |
4 | |
5 | // Copyright (C) 2008-2018 Lorenzo Caminiti |
6 | // Distributed under the Boost Software License, Version 1.0 (see accompanying |
7 | // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). |
8 | // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html |
9 | |
10 | #include <boost/iostreams/tee.hpp> |
11 | #include <boost/iostreams/stream.hpp> |
12 | #include <string> |
13 | #include <sstream> |
14 | #include <iostream> |
15 | #include <algorithm> |
16 | |
17 | namespace boost { namespace contract { namespace test { namespace detail { |
18 | |
19 | namespace oteststream_ { |
20 | struct oss_base { // Wrap oss data member for proper initialization order. |
21 | protected: |
22 | std::ostringstream oss_; |
23 | }; |
24 | } |
25 | |
26 | // Print to clog plus build internal string (using ostringstream) for checking. |
27 | struct oteststream : |
28 | private oteststream_::oss_base, |
29 | public boost::iostreams::stream<boost::iostreams::tee_device<std::ostream, |
30 | std::ostringstream> > |
31 | { |
32 | oteststream() : |
33 | oteststream_::oss_base(), |
34 | boost::iostreams::stream<boost::iostreams::tee_device< |
35 | std::ostream, std::ostringstream> >( |
36 | boost::iostreams::tee_device<std::ostream, std::ostringstream>( |
37 | std::clog, oss_) |
38 | ) |
39 | {} |
40 | |
41 | std::string str() const { return oss_.str(); } |
42 | void str(std::string const& s) { oss_.str(s: s); } |
43 | |
44 | bool eq(std::string const& s) { return eq(r: str(), s); } |
45 | |
46 | // Also display mismatching characters. |
47 | static bool eq(std::string const& r, std::string const& s) { |
48 | std::string::size_type i = 0; |
49 | for(; i < r.size() && i < s.size(); ++i) if(r[i] != s[i]) break; |
50 | if(i < r.size() || i < s.size()) { |
51 | std::cout << std::endl; |
52 | std::cout << |
53 | "Error: Following strings differ at position " << i << |
54 | ", because '" << r[i] << "' != '" << s[i] << "':" << std::endl |
55 | ; |
56 | std::cout << std::endl; |
57 | std::cout |
58 | << r.substr(pos: 0, n: i) |
59 | << "(((" << r[i] << ")))" |
60 | // Extra () to avoid clashes with MSVC min macro. |
61 | << r.substr(pos: (std::min)(a: i + 1, b: r.size()), n: r.size()) |
62 | << std::endl |
63 | ; |
64 | std::cout << std::endl; |
65 | std::cout |
66 | << s.substr(pos: 0, n: i) |
67 | << "(((" << s[i] << ")))" |
68 | // Extra () to avoid clashes with MSVC min macro. |
69 | << s.substr(pos: (std::min)(a: i + 1, b: s.size()), n: s.size()) |
70 | << std::endl |
71 | ; |
72 | std::cout << std::endl; |
73 | return false; |
74 | } |
75 | return true; |
76 | } |
77 | }; |
78 | |
79 | } } } } // namespace |
80 | |
81 | #endif // #include guard |
82 | |
83 | |