123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- // ----------------------------------------------------------------------------
- // Copyright (C) 2002-2005 Marcin Kalicinski
- //
- // 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)
- //
- // For more information, see www.boost.org
- // ----------------------------------------------------------------------------
- #ifndef BOOST_PROPERTY_TREE_TEST_UTILS_INCLUDED
- #define BOOST_PROPERTY_TREE_TEST_UTILS_INCLUDED
- #define BOOST_PROPERTY_TREE_DEBUG // Enable ptree debugging
- #include <boost/property_tree/ptree.hpp>
- // Do not deprecate insecure CRT calls on VC8
- #if (defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) && !defined(_CRT_SECURE_NO_DEPRECATE))
- # define _CRT_SECURE_NO_DEPRECATE
- #endif
- #include <boost/test/minimal.hpp>
- #include <boost/property_tree/detail/ptree_utils.hpp>
- #include <fstream>
- #include <cstring>
- #include <sstream>
- template<class Ptree>
- typename Ptree::size_type total_size(const Ptree &pt)
- {
- typename Ptree::size_type size = 1;
- for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it)
- size += total_size(it->second);
- return size;
- }
- template<class Ptree>
- typename Ptree::size_type total_keys_size(const Ptree &pt)
- {
- typename Ptree::size_type size = 0;
- for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it)
- {
- size += it->first.size();
- size += total_keys_size(it->second);
- }
- return size;
- }
- template<class Ptree>
- typename Ptree::size_type total_data_size(const Ptree &pt)
- {
- typename Ptree::size_type size = pt.data().size();
- for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it)
- size += total_data_size(it->second);
- return size;
- }
- class test_file
- {
- public:
- test_file(const char *test_data, const char *filename)
- {
- if (test_data && filename)
- {
- name = filename;
- std::ofstream stream(name.c_str());
- using namespace std;
- stream.write(test_data, strlen(test_data));
- BOOST_CHECK(stream.good());
- }
- }
- ~test_file()
- {
- if (!name.empty())
- remove(name.c_str());
- }
- private:
- std::string name;
- };
- template<class Ptree>
- Ptree get_test_ptree()
- {
- using namespace boost::property_tree;
- typedef typename Ptree::key_type Str;
- Ptree pt;
- pt.put_value(detail::widen<Str>("data0"));
- pt.put(detail::widen<Str>("key1"), detail::widen<Str>("data1"));
- pt.put(detail::widen<Str>("key1.key"), detail::widen<Str>("data2"));
- pt.put(detail::widen<Str>("key2"), detail::widen<Str>("data3"));
- pt.put(detail::widen<Str>("key2.key"), detail::widen<Str>("data4"));
- return pt;
- }
- // Generic test for file parser
- template<class Ptree, class ReadFunc, class WriteFunc>
- void generic_parser_test(Ptree &pt,
- ReadFunc rf,
- WriteFunc wf,
- const char *test_data_1,
- const char *test_data_2,
- const char *filename_1,
- const char *filename_2,
- const char *filename_out)
- {
- using namespace boost::property_tree;
- // Create test files
- test_file file_1(test_data_1, filename_1);
- test_file file_2(test_data_2, filename_2);
- test_file file_out("", filename_out);
- rf(filename_1, pt); // Read file
- wf(filename_out, pt); // Write file
- Ptree pt2;
- rf(filename_out, pt2); // Read file again
- // Compare original with read
- BOOST_CHECK(pt == pt2);
- }
- // Generic test for file parser with expected success
- template<class Ptree, class ReadFunc, class WriteFunc>
- void generic_parser_test_ok(ReadFunc rf,
- WriteFunc wf,
- const char *test_data_1,
- const char *test_data_2,
- const char *filename_1,
- const char *filename_2,
- const char *filename_out,
- unsigned int total_size,
- unsigned int total_data_size,
- unsigned int total_keys_size)
- {
- using namespace boost::property_tree;
- std::cerr << "(progress) Starting generic parser test with test file \"" << filename_1 << "\"\n";
- // Make sure no instances exist
- //BOOST_CHECK(Ptree::debug_get_instances_count() == 0);
- try
- {
- // Read file
- Ptree pt;
- generic_parser_test<Ptree, ReadFunc, WriteFunc>(pt, rf, wf,
- test_data_1, test_data_2,
- filename_1, filename_2, filename_out);
- // Determine total sizes
- typename Ptree::size_type actual_total_size = ::total_size(pt);
- typename Ptree::size_type actual_data_size = ::total_data_size(pt);
- typename Ptree::size_type actual_keys_size = ::total_keys_size(pt);
- if (actual_total_size != total_size ||
- actual_data_size != total_data_size ||
- actual_keys_size != total_keys_size)
- std::cerr << "Sizes: " << (unsigned)::total_size(pt) << ", " << (unsigned)::total_data_size(pt) << ", " << (unsigned)::total_keys_size(pt) << "\n";
- // Check total sizes
- BOOST_CHECK(actual_total_size == total_size);
- BOOST_CHECK(actual_data_size == total_data_size);
- BOOST_CHECK(actual_keys_size == total_keys_size);
- }
- catch (std::runtime_error &e)
- {
- BOOST_ERROR(e.what());
- }
- // Test for leaks
- //BOOST_CHECK(Ptree::debug_get_instances_count() == 0);
- }
- // Generic test for file parser with expected error
- template<class Ptree, class ReadFunc, class WriteFunc, class Error>
- void generic_parser_test_error(ReadFunc rf,
- WriteFunc wf,
- const char *test_data_1,
- const char *test_data_2,
- const char *filename_1,
- const char *filename_2,
- const char *filename_out,
- unsigned long expected_error_line)
- {
- std::cerr << "(progress) Starting generic parser test with test file \"" << filename_1 << "\"\n";
-
- // Make sure no instances exist
- //BOOST_CHECK(Ptree::debug_get_instances_count() == 0);
- {
- // Create ptree as a copy of test ptree (to test if read failure does not damage ptree)
- Ptree pt(get_test_ptree<Ptree>());
- try
- {
- generic_parser_test<Ptree, ReadFunc, WriteFunc>(pt, rf, wf,
- test_data_1, test_data_2,
- filename_1, filename_2, filename_out);
- BOOST_ERROR("No required exception thrown");
- }
- catch (Error &e)
- {
- BOOST_CHECK(e.line() == expected_error_line); // Test line number
- BOOST_CHECK(pt == get_test_ptree<Ptree>()); // Test if error damaged contents
- }
- catch (...)
- {
- BOOST_ERROR("Invalid exception type thrown");
- throw;
- }
- }
- // Test for leaks
- //BOOST_CHECK(Ptree::debug_get_instances_count() == 0);
- }
- template <typename Ch> std::basic_ostream<Ch>& errstream();
- template <> inline
- std::basic_ostream<char>& errstream() { return std::cerr; }
- #ifndef BOOST_NO_CWCHAR
- template <> inline
- std::basic_ostream<wchar_t>& errstream() { return std::wcerr; }
- #endif
- template <class Ptree, class ReadFunc, class WriteFunc>
- void check_exact_roundtrip(ReadFunc rf, WriteFunc wf, const char *test_data) {
- std::cerr << "(progress) Starting exact roundtrip test with test data:\n"
- << test_data << "\n-----\n";
- using namespace boost::property_tree;
- typedef typename Ptree::key_type::value_type Ch;
- typedef typename Ptree::key_type Str;
- Str native_test_data = detail::widen<Str>(test_data);
- std::basic_istringstream<Ch> in_stream(native_test_data);
- std::basic_ostringstream<Ch> out_stream;
- Ptree tree;
- rf(in_stream, tree);
- wf(out_stream, tree);
- std::cerr << "(progress) Roundtripped data:\n";
- errstream<Ch>() << out_stream.str();
- std::cerr << "\n-----\n";
- BOOST_CHECK(native_test_data == out_stream.str());
- }
- #endif
|