blob: c6db0e40e9b302714dbdb396f263f426a3565b70 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
Copyright (c) 2010 Bryce Lelbach
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 <boost/config/warning_disable.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <boost/functional/hash.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_utree.hpp>
#include <iostream>
#include <sstream>
#include <cstdlib>
inline bool check(boost::spirit::utree const& val, std::string expected)
{
std::stringstream s;
s << val;
if (s.str() == expected + " ")
return true;
std::cerr << "got result: " << s.str()
<< ", expected: " << expected << std::endl;
return false;
}
struct one_two_three
{
boost::spirit::utree operator()(boost::spirit::utree) const
{
return boost::spirit::utree(123);
}
};
struct this_
{
boost::spirit::utree operator()(boost::spirit::utree) const
{
return boost::spirit::utree(static_cast<int>(boost::hash_value(this)));
}
};
int main()
{
using boost::spirit::utree;
using boost::spirit::get;
using boost::spirit::utf8_symbol_type;
using boost::spirit::binary_string_type;
{
// test the size
std::cout << "size of utree is: "
<< sizeof(utree) << " bytes" << std::endl;
BOOST_TEST_EQ(sizeof(utree), sizeof(void*[4]));
}
{
using boost::spirit::nil;
utree val(nil);
BOOST_TEST(check(val, "<nil>"));
}
{
using boost::spirit::empty_list;
utree val(empty_list);
BOOST_TEST(check(val, "( )"));
}
{
utree val(true);
BOOST_TEST(check(val, "true"));
}
{
utree val(123);
BOOST_TEST(check(val, "123"));
}
{
// single element string
utree val('x');
BOOST_TEST(check(val, "\"x\""));
// empty string
utree val1("");
BOOST_TEST(check(val1, "\"\""));
}
{
utree val(123.456);
BOOST_TEST(check(val, "123.456"));
}
{ // strings
utree val("Hello, World");
BOOST_TEST(check(val, "\"Hello, World\""));
utree val2;
val2 = val;
BOOST_TEST(check(val2, "\"Hello, World\""));
utree val3("Hello, World. Chuckie is back!!!");
val = val3;
BOOST_TEST(check(val, "\"Hello, World. Chuckie is back!!!\""));
utree val4("Apple");
utree val5("Apple");
BOOST_TEST_EQ(val4, val5);
utree val6("ApplePie");
BOOST_TEST(val4 < val6);
}
{ // symbols
utree val(utf8_symbol_type("Hello, World"));
BOOST_TEST(check(val, "Hello, World"));
utree val2;
val2 = val;
BOOST_TEST(check(val2, "Hello, World"));
utree val3(utf8_symbol_type("Hello, World. Chuckie is back!!!"));
val = val3;
BOOST_TEST(check(val, "Hello, World. Chuckie is back!!!"));
utree val4(utf8_symbol_type("Apple"));
utree val5(utf8_symbol_type("Apple"));
BOOST_TEST_EQ(val4, val5);
utree val6(utf8_symbol_type("ApplePie"));
BOOST_TEST(val4 < val6);
}
{ // binary_strings
utree val(binary_string_type("\xDE#\xAD"));
BOOST_TEST(check(val, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */));
utree val2;
val2 = val;
BOOST_TEST(check(val2, "#de23ad#" /* FIXME?: "#\xDE#\xAD#" */));
utree val3(binary_string_type("\xDE\xAD\xBE\xEF"));
val = val3;
BOOST_TEST(check(val, "#deadbeef#" /* FIXME?: "#\xDE\xAD\xBE\xEF#" */));
utree val4(binary_string_type("\x01"));
utree val5(binary_string_type("\x01"));
BOOST_TEST_EQ(val4, val5);
utree val6(binary_string_type("\x01\x02"));
BOOST_TEST(val4 < val6);
}
{
using boost::spirit::nil;
utree val;
val.push_back(123);
val.push_back("Chuckie");
BOOST_TEST_EQ(val.size(), 2U);
utree val2;
val2.push_back(123.456);
val2.push_back("Mah Doggie");
val.push_back(val2);
BOOST_TEST_EQ(val.size(), 3U);
BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
BOOST_TEST(check(val.front(), "123"));
utree val3(nil);
val3.swap(val);
BOOST_TEST_EQ(val3.size(), 3U);
BOOST_TEST(check(val, "<nil>"));
val3.swap(val);
BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
val.push_back("another string");
BOOST_TEST_EQ(val.size(), 4U);
BOOST_TEST(check(val, "( 123 \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
val.pop_front();
BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"another string\" )"));
utree::iterator i = val.begin();
++++i;
val.insert(i, "Right in the middle");
BOOST_TEST_EQ(val.size(), 4U);
BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" \"another string\" )"));
val.pop_back();
BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) \"Right in the middle\" )"));
BOOST_TEST_EQ(val.size(), 3U);
utree::iterator it = val.end(); --it;
val.erase(it);
BOOST_TEST(check(val, "( \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
BOOST_TEST_EQ(val.size(), 2U);
val.insert(val.begin(), val2.begin(), val2.end());
BOOST_TEST(check(val, "( 123.456 \"Mah Doggie\" \"Chuckie\" ( 123.456 \"Mah Doggie\" ) )"));
BOOST_TEST_EQ(val.size(), 4U);
// Regeression Ticket #6714
it = val.insert(val.end(), 111);
BOOST_TEST(it != val.begin());
BOOST_TEST(it == --val.end());
BOOST_TEST(*it == 111);
val.clear();
it = val.insert(val.begin(), 222);
BOOST_TEST(it == val.begin());
BOOST_TEST(it == --val.end());
BOOST_TEST(*it == 222);
// Regeression Ticket #6714
}
{
utree val;
val.insert(val.end(), 123);
val.insert(val.end(), "Mia");
val.insert(val.end(), "Chuckie");
val.insert(val.end(), "Poly");
val.insert(val.end(), "Mochi");
BOOST_TEST(check(val, "( 123 \"Mia\" \"Chuckie\" \"Poly\" \"Mochi\" )"));
}
{
using boost::spirit::nil;
using boost::spirit::invalid;
utree a(nil), b(nil);
BOOST_TEST_EQ(a, b);
a = 123;
BOOST_TEST(a != b);
b = 123;
BOOST_TEST_EQ(a, b);
a = 100.00;
BOOST_TEST(a < b);
b = a = utree(invalid);
BOOST_TEST_EQ(a, b);
a.push_back(1);
a.push_back("two");
a.push_back(3.0);
b.push_back(1);
b.push_back("two");
b.push_back(3.0);
BOOST_TEST_EQ(a, b);
b.push_back(4);
BOOST_TEST(a != b);
BOOST_TEST(a < b);
}
{
using boost::spirit::empty_list;
utree a(empty_list);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
a.push_back(0);
for (utree::size_type i = 0; i < a.size(); ++i)
get(a, i) = int(i + 1);
BOOST_TEST_EQ(get(a, 0), utree(1));
BOOST_TEST_EQ(get(a, 1), utree(2));
BOOST_TEST_EQ(get(a, 2), utree(3));
BOOST_TEST_EQ(get(a, 3), utree(4));
BOOST_TEST_EQ(get(a, 4), utree(5));
BOOST_TEST_EQ(get(a, 5), utree(6));
BOOST_TEST_EQ(get(a, 6), utree(7));
BOOST_TEST_EQ(get(a, 7), utree(8));
BOOST_TEST_EQ(get(a, 8), utree(9));
BOOST_TEST_EQ(get(a, 9), utree(10));
BOOST_TEST_EQ(get(a, 10), utree(11));
BOOST_TEST_EQ(get(a, 11), utree(12));
}
{
// test empty list
utree a;
a.push_back(1);
a.pop_front();
BOOST_TEST(check(a, "( )"));
// the other way around
utree b;
b.push_front(1);
b.pop_back();
BOOST_TEST(check(b, "( )"));
}
{ // test references
utree val(123);
utree ref(boost::ref(val));
BOOST_TEST(check(ref, "123"));
BOOST_TEST_EQ(ref, utree(123));
val.clear();
val.push_back(1);
val.push_back(2);
val.push_back(3);
val.push_back(4);
BOOST_TEST(check(ref, "( 1 2 3 4 )"));
BOOST_TEST_EQ(get(ref, 0), utree(1));
BOOST_TEST_EQ(get(ref, 1), utree(2));
BOOST_TEST_EQ(get(ref, 2), utree(3));
BOOST_TEST_EQ(get(ref, 3), utree(4));
}
{ // put it in an array
utree vals[] = {
utree(123),
utree("Hello, World"),
utree(123.456)
};
BOOST_TEST(check(vals[0], "123"));
BOOST_TEST(check(vals[1], "\"Hello, World\""));
BOOST_TEST(check(vals[2], "123.456"));
}
{ // operators
BOOST_TEST((utree(false) && utree(false)) == utree(false));
BOOST_TEST((utree(false) && utree(true)) == utree(false));
BOOST_TEST((utree(true) && utree(false)) == utree(false));
BOOST_TEST((utree(true) && utree(true)) == utree(true));
BOOST_TEST((utree(0) && utree(0)) == utree(false));
BOOST_TEST((utree(0) && utree(1)) == utree(false));
BOOST_TEST((utree(1) && utree(0)) == utree(false));
BOOST_TEST((utree(1) && utree(1)) == utree(true));
BOOST_TEST((utree(false) || utree(false)) == utree(false));
BOOST_TEST((utree(false) || utree(true)) == utree(true));
BOOST_TEST((utree(true) || utree(false)) == utree(true));
BOOST_TEST((utree(true) || utree(true)) == utree(true));
BOOST_TEST((utree(0) || utree(0)) == utree(false));
BOOST_TEST((utree(0) || utree(1)) == utree(true));
BOOST_TEST((utree(1) || utree(0)) == utree(true));
BOOST_TEST((utree(1) || utree(1)) == utree(true));
BOOST_TEST(!utree(true) == utree(false));
BOOST_TEST(!utree(false) == utree(true));
BOOST_TEST(!utree(1) == utree(false));
BOOST_TEST(!utree(0) == utree(true));
BOOST_TEST((utree(456) + utree(123)) == utree(456 + 123));
BOOST_TEST((utree(456) + utree(123.456)) == utree(456 + 123.456));
BOOST_TEST((utree(456) - utree(123)) == utree(456 - 123));
BOOST_TEST((utree(456) - utree(123.456)) == utree(456 - 123.456));
BOOST_TEST((utree(456) * utree(123)) == utree(456 * 123));
BOOST_TEST((utree(456) * utree(123.456)) == utree(456 * 123.456));
BOOST_TEST((utree(456) / utree(123)) == utree(456 / 123));
BOOST_TEST((utree(456) / utree(123.456)) == utree(456 / 123.456));
BOOST_TEST((utree(456) % utree(123)) == utree(456 % 123));
BOOST_TEST(-utree(456) == utree(-456));
BOOST_TEST((utree(456) & utree(123)) == utree(456 & 123));
BOOST_TEST((utree(456) | utree(123)) == utree(456 | 123));
BOOST_TEST((utree(456) ^ utree(123)) == utree(456 ^ 123));
BOOST_TEST((utree(456) << utree(3)) == utree(456 << 3));
BOOST_TEST((utree(456) >> utree(2)) == utree(456 >> 2));
BOOST_TEST(~utree(456) == utree(~456));
}
{ // test reference iterator
utree val;
val.push_back(1);
val.push_back(2);
val.push_back(3);
val.push_back(4);
BOOST_TEST(check(val, "( 1 2 3 4 )"));
utree::ref_iterator b = val.ref_begin();
utree::ref_iterator e = val.ref_end();
utree ref(boost::make_iterator_range(b, e));
BOOST_TEST_EQ(get(ref, 0), utree(1));
BOOST_TEST_EQ(get(ref, 1), utree(2));
BOOST_TEST_EQ(get(ref, 2), utree(3));
BOOST_TEST_EQ(get(ref, 3), utree(4));
BOOST_TEST(check(ref, "( 1 2 3 4 )"));
}
{
// check the tag
// TODO: test tags on all utree types
utree x;
x.tag(123);
BOOST_TEST_EQ(x.tag(), 123);
x = "hello world! my name is bob the builder";
x.tag(123);
BOOST_TEST_EQ(x.tag(), 123);
x.tag(456);
BOOST_TEST_EQ(x.tag(), 456);
BOOST_TEST_EQ(x.size(), 39U);
BOOST_TEST(check(x, "\"hello world! my name is bob the builder\""));
x = "hello";
x.tag(456);
BOOST_TEST_EQ(x.tag(), 456);
x.tag(789);
BOOST_TEST_EQ(x.tag(), 789);
BOOST_TEST_EQ(x.size(), 5U);
BOOST_TEST(check(x, "\"hello\""));
}
{
// test functions
using boost::spirit::stored_function;
utree f = stored_function<one_two_three>();
f.eval(utree());
}
{
// test referenced functions
using boost::spirit::referenced_function;
one_two_three f;
utree ff = referenced_function<one_two_three>(f);
BOOST_TEST_EQ(ff.eval(utree()), f(utree()));
}
{
// shallow ranges
using boost::spirit::shallow;
utree val;
val.push_back(1);
val.push_back(2);
val.push_back(3);
val.push_back(4);
utree::iterator i = val.begin(); ++i;
utree alias(utree::range(i, val.end()), shallow);
BOOST_TEST(check(alias, "( 2 3 4 )"));
BOOST_TEST_EQ(alias.size(), 3U);
BOOST_TEST_EQ(alias.front(), 2);
BOOST_TEST_EQ(alias.back(), 4);
BOOST_TEST(!alias.empty());
BOOST_TEST_EQ(get(alias, 1), 3);
}
{
// shallow string ranges
using boost::spirit::utf8_string_range_type;
using boost::spirit::shallow;
char const* s = "Hello, World";
utree val(utf8_string_range_type(s, s + strlen(s)), shallow);
BOOST_TEST(check(val, "\"Hello, World\""));
utf8_string_range_type r = val.get<utf8_string_range_type>();
utf8_string_range_type pf(r.begin()+1, r.end()-1);
val = utree(pf, shallow);
BOOST_TEST(check(val, "\"ello, Worl\""));
}
{
// any pointer
using boost::spirit::any_ptr;
int n = 123;
utree up = any_ptr(&n);
BOOST_TEST(*up.get<int*>() == 123);
}
// tags
{
short min = (std::numeric_limits<short>::min)();
short max = (std::numeric_limits<short>::max)();
utree::list_type u;
utree u2;
bool ok = true;
for (int t = min ; ok && t <= max ; ++t) {
u.tag(t);
u2 = u;
BOOST_TEST_EQ(t, u.tag());
BOOST_TEST_EQ(t, u2.tag());
ok = t == u.tag() && t == u2.tag();
u2 = utree("12");
}
}
return boost::report_errors();
}