123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- // -----------------------------------------------------------
- // Copyright (c) 2001 Jeremy Siek
- // Copyright (c) 2003-2006 Gennaro Prota
- //
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // -----------------------------------------------------------
- #include <fstream>
- #include <string>
- #include <cstddef> // for std::size_t
- #include <stdexcept> // for std::logic_error
- #include <assert.h>
- #include <boost/config.hpp>
- #if !defined (BOOST_NO_STRINGSTREAM)
- # include <sstream>
- #endif
- #include "bitset_test.hpp"
- #include <boost/dynamic_bitset/dynamic_bitset.hpp>
- #include <boost/config/workaround.hpp>
- // Codewarrior 8.3 for Win fails without this.
- // Thanks Howard Hinnant ;)
- #if defined __MWERKS__ && BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
- # pragma parse_func_templ off
- #endif
- #if defined BOOST_NO_STD_WSTRING || defined BOOST_NO_STD_LOCALE
- # define BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
- #endif
- #if !defined BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
- std::wstring widen_string( const std::string & str,
- const std::locale & loc = std::locale() )
- {
- std::wstring result;
- const std::string::size_type len = str.length();
- if(len != 0) {
- typedef std::ctype<wchar_t> ct_type;
- typedef std::wstring::traits_type tr_type;
- const ct_type & ct = BOOST_USE_FACET(ct_type, loc);
- result.resize(len);
- for (std::size_t i = 0; i < len; ++i)
- tr_type::assign(result[i], ct.widen(str[i]));
- }
- return result;
- }
- #endif
- template <typename Block>
- void run_test_cases( BOOST_EXPLICIT_TEMPLATE_TYPE(Block) )
- {
- typedef boost::dynamic_bitset<Block> bitset_type;
- typedef bitset_test<bitset_type> Tests;
- //=====================================================================
- // Test stream operator<<
- {
- // The test "variables" are: the stream type and its state, the
- // exception mask, the width, the fill char and the padding side (left/right)
- std::ios::iostate masks[] = {
- std::ios::goodbit,
- std::ios::eofbit,
- std::ios::failbit,
- std::ios::eofbit | std::ios::failbit
- };
- static std::string strings[] = {
- std::string(""),
- std::string("0"),
- std::string("1"),
- std::string("11100"),
- get_long_string()
- };
- char fill_chars[] = { '*', 'x', ' ' };
- std::size_t num_masks = sizeof(masks) / sizeof(masks[0]);
- std::size_t num_strings = sizeof(strings) / sizeof(strings[0]);
- std::size_t num_chars = sizeof(fill_chars) / sizeof(fill_chars[0]);
- std::fstream not_good_stream("dynamic_bitset_tests - this file shouldn't exist",
- std::ios::in);
- for (std::size_t mi = 0; mi < num_masks; ++mi) {
- for (std::size_t si = 0; si < num_strings; ++si) {
- std::streamsize slen = (std::streamsize)(strings[si].length());
- assert( (std::numeric_limits<std::streamsize>::max)()
- >=(std::streamsize)(1+slen*2) );
- for (std::size_t ci = 0; ci < num_chars; ++ci) {
- // note how "negative widths" are tested too
- const std::streamsize widths[] = { -1 - slen/2, 0, slen/2, 1 + slen*2 };
- std::size_t num_widths = sizeof(widths) / sizeof(widths[0]);
- for (std::size_t wi = 0; wi < num_widths; ++wi) {
- std::streamsize w = widths[wi];
- {
- // test 0 - stream !good()
- if(not_good_stream.good())
- throw std::logic_error("Error in operator << tests"
- " - please, double check");
- bitset_type b(strings[si]);
- not_good_stream.width(w);
- not_good_stream.fill(fill_chars[ci]);
- try { not_good_stream.exceptions(masks[mi]); } catch(...) {}
- Tests::stream_inserter(b, not_good_stream, "<unused_string>");
- }
- {
- // test 1a - file stream
- scoped_temp_file stf;
- bitset_type b(strings[si]);
- std::ofstream file(stf.path().string().c_str(), std::ios::trunc);
- file.width(w);
- file.fill(fill_chars[ci]);
- file.exceptions(masks[mi]);
- Tests::stream_inserter(b, file, stf.path().string().c_str());
- }
- {
- //NOTE: there are NO string stream tests
- }
- #if !defined (BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS)
- {
- // test 1b - wide file stream
- scoped_temp_file stf;
- bitset_type b(strings[si]);
- std::wofstream file(stf.path().string().c_str());
- file.width(w);
- file.fill(fill_chars[ci]);
- file.exceptions(masks[mi]);
- Tests::stream_inserter(b, file, stf.path().string().c_str());
- }
- #endif
- }
- }
- }
- } // for (; mi..)
- }
- //=====================================================================
- // Test stream operator>>
- {
- // The test "variables" are: the stream type, the exception mask,
- // the actual contents (and/or state) of the stream, and width.
- //
- // With few exceptions, each test case consists of writing a different
- // assortment of digits and "whitespaces" to a text stream and then checking
- // that what was written gets read back unchanged. That's NOT guaranteed by
- // the standard, unless the assortment always ends with a '\n' and satisfies
- // other conditions (see C99, 7.19.2/2), however it works in practice and is
- // a good "real life" test. Some characters, such as '\v' and '\f', are not
- // used exactly because they are the ones which will most likely give problems
- // on some systems (for instance '\f' could actually be written as a sequence
- // of new-lines, and we could never be able to read it back)
- //
- // Note how the bitset object is not initially empty. That helps checking
- // that it isn't erroneously clear()ed by operator>>.
- std::ios::iostate masks[] = {
- std::ios::goodbit,
- std::ios::eofbit,
- std::ios::failbit,
- std::ios::eofbit | std::ios::failbit
- };
- const std::string spaces = "\t\n "; //"\t\n\v\f ";
- const std::string long_string = get_long_string();
- /*const*/ static std::string strings[] = {
- // NOTE: "const" gives the usual problems with Borland
- // (in Tests::stream_extractor instantiation)
- #if !(defined __BORLANDC__ \
- && BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)))
- // Borland 5.5.1 with RW library crashes
- // empty string
- std::string(""),
- // no bitset
- spaces,
- #endif
- // no bitset
- std::string("x"),
- std::string("\t xyz"),
- // bitset of size 1
- std::string("0"),
- std::string("1"),
- std::string(" 0 "),
- std::string(" 1 "),
- spaces + "1",
- "1" + spaces,
- spaces + "1" + spaces,
- std::string(" x1x "),
- std::string(" 1x "),
- // long bitset
- long_string,
- " " + long_string + " xyz",
- spaces + long_string,
- spaces + long_string + spaces
- };
- //-----------------------------------------------------
- std::stringstream not_good_stream;
- not_good_stream << "test";
- std::string sink;
- not_good_stream >> sink; // now the stream should be in eof state
- const std::size_t num_masks = sizeof(masks) / sizeof(masks[0]);
- const std::size_t num_strings = sizeof(strings) / sizeof(strings[0]);
- for (std::size_t mi = 0; mi < num_masks; ++mi) {
- for (std::size_t si = 0; si < num_strings; ++si) {
- const std::streamsize slen = (std::streamsize)(strings[si].length());
- assert((std::numeric_limits<std::streamsize>::max)() >= (std::streamsize)(1+slen*2));
- std::streamsize widths[] = { -1, 0, slen/2, slen, 1 + slen*2 };
- std::size_t num_widths = sizeof(widths) / sizeof(widths[0]);
- for(std::size_t wi = 0; wi < num_widths; ++wi) {
- const std::streamsize w = widths[wi];
- // test 0 - !good() stream
- {
- if(not_good_stream.good())
- throw std::logic_error("Error in operator >> tests"
- " - please, double check");
- bitset_type b(1, 15ul); // note: b is not empty
- not_good_stream.width(w);
- try { not_good_stream.exceptions(masks[mi]); } catch(...) {}
- std::string irrelevant;
- Tests::stream_extractor(b, not_good_stream, irrelevant);
- }
- // test 1a - (narrow) file stream
- {
- scoped_temp_file stf;
- bitset_type b(1, 255ul);
- {
- std::ofstream f(stf.path().string().c_str());
- f << strings[si];
- }
- std::ifstream f(stf.path().string().c_str());
- f.width(w);
- f.exceptions(masks[mi]);
- Tests::stream_extractor(b, f, strings[si]);
- }
- #if !defined(BOOST_NO_STRINGSTREAM)
- // test 2a - stringstream
- {
- bitset_type b(1, 255ul);
- std::istringstream stream(strings[si]);
- stream.width(w);
- stream.exceptions(masks[mi]);
- Tests::stream_extractor(b, stream, strings[si]);
- }
- #endif
- #if !defined(BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS)
- // test 1b - wchar_t file stream
- {
- scoped_temp_file stf;
- std::wstring wstr = widen_string(strings[si]);
- bitset_type b(1, 255ul);
- {
- std::basic_ofstream<wchar_t> of(stf.path().string().c_str());
- of << wstr;
- }
- std::basic_ifstream<wchar_t> f(stf.path().string().c_str());
- f.width(w);
- f.exceptions(masks[mi]);
- Tests::stream_extractor(b, f, wstr);
- }
- // test 2b - wstringstream
- {
- bitset_type b(1, 255ul);
- std::wstring wstr = widen_string(strings[si]);
- std::wistringstream wstream(wstr);
- wstream.width(w);
- wstream.exceptions(masks[mi]);
- Tests::stream_extractor(b, wstream, wstr);
- }
- #endif // BOOST_DYNAMIC_BITSET_NO_WCHAR_T_TESTS
- }
- }
- } // for ( mi = 0; ...)
- }
- //=====================================================================
- // << Any other tests go here >>
- // .....
- }
- int
- main()
- {
- run_test_cases<unsigned char>();
- run_test_cases<unsigned short>();
- run_test_cases<unsigned int>();
- run_test_cases<unsigned long>();
- # ifdef BOOST_HAS_LONG_LONG
- run_test_cases< ::boost::ulong_long_type>();
- # endif
- return boost::report_errors();
- }
|