• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
oteststreamboost::contract::test::detail::oteststream32     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 
strboost::contract::test::detail::oteststream41     std::string str() const { return oss_.str(); }
strboost::contract::test::detail::oteststream42     void str(std::string const& s) { oss_.str(s); }
43 
eqboost::contract::test::detail::oteststream44     bool eq(std::string const& s) { return eq(str(), s); }
45 
46     // Also display mismatching characters.
eqboost::contract::test::detail::oteststream47     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(0, i)
59                 << "(((" << r[i] << ")))"
60                 // Extra () to avoid clashes with MSVC min macro.
61                 << r.substr((std::min)(i + 1, r.size()), r.size())
62                 << std::endl
63             ;
64             std::cout << std::endl;
65             std::cout
66                 << s.substr(0, i)
67                 << "(((" << s[i] << ")))"
68                 // Extra () to avoid clashes with MSVC min macro.
69                 << s.substr((std::min)(i + 1, s.size()), 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