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