1 | |
2 | // Copyright 2005 The Trustees of Indiana University. |
3 | |
4 | // Use, modification and distribution is subject to the Boost Software |
5 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
6 | // http://www.boost.org/LICENSE_1_0.txt) |
7 | |
8 | // |
9 | // dynamic_properties_test.cpp - test cases for the dynamic property maps. |
10 | // |
11 | |
12 | // Author: Ronald Garcia |
13 | #include <boost/config.hpp> |
14 | |
15 | // For Borland, act like BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS is defined |
16 | #if defined (BOOST_BORLANDC) && (BOOST_BORLANDC <= 0x570) && !defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS) |
17 | # define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS |
18 | #endif |
19 | |
20 | #include <boost/core/lightweight_test.hpp> |
21 | #include <boost/smart_ptr.hpp> |
22 | #include <boost/property_map/dynamic_property_map.hpp> |
23 | #include <boost/property_map/property_map.hpp> |
24 | #include <map> |
25 | #include <iostream> |
26 | #include <string> |
27 | #include <memory> |
28 | |
29 | // generate a dynamic_property_map that maps strings to strings |
30 | // WARNING: This code leaks memory. For testing purposes only! |
31 | // WARNING: This code uses library internals. For testing purposes only! |
32 | boost::shared_ptr<boost::dynamic_property_map> |
33 | string2string_gen(const std::string&, |
34 | const boost::any&, |
35 | const boost::any&) { |
36 | typedef std::map<std::string,std::string> map_t; |
37 | typedef |
38 | boost::associative_property_map< std::map<std::string, std::string> > |
39 | property_t; |
40 | |
41 | |
42 | map_t* mymap = new map_t(); // hint: leaky memory here! |
43 | |
44 | property_t property_map(*mymap); |
45 | |
46 | boost::shared_ptr<boost::dynamic_property_map> pm( |
47 | new |
48 | boost::detail::dynamic_property_map_adaptor<property_t>(property_map)); |
49 | |
50 | return pm; |
51 | } |
52 | |
53 | |
54 | int main() { |
55 | |
56 | // build property maps using associative_property_map |
57 | |
58 | std::map<std::string, int> string2int; |
59 | std::map<double,std::string> double2string; |
60 | boost::associative_property_map< std::map<std::string, int> > |
61 | int_map(string2int); |
62 | boost::associative_property_map< std::map<double, std::string> > |
63 | dbl_map(double2string); |
64 | |
65 | |
66 | // add key-value information |
67 | string2int["one" ] = 1; |
68 | string2int["five" ] = 5; |
69 | |
70 | double2string[5.3] = "five point three" ; |
71 | double2string[3.14] = "pi" ; |
72 | |
73 | |
74 | // build and populate dynamic interface |
75 | boost::dynamic_properties properties; |
76 | properties.property(name: "int" ,property_map_: int_map); |
77 | properties.property(name: "double" ,property_map_: dbl_map); |
78 | |
79 | using boost::get; |
80 | using boost::put; |
81 | using boost::type; |
82 | // Get tests |
83 | { |
84 | BOOST_TEST(get("int" ,properties,std::string("one" )) == "1" ); |
85 | #ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS |
86 | BOOST_TEST(boost::get<int>("int" ,properties,std::string("one" )) == 1); |
87 | #endif |
88 | BOOST_TEST(get("int" ,properties,std::string("one" ), type<int>()) == 1); |
89 | BOOST_TEST(get("double" ,properties,5.3) == "five point three" ); |
90 | try { |
91 | get(name: "not_there" ,dp: properties,key: "" ); |
92 | BOOST_ERROR("No exception thrown." ); |
93 | } catch (boost::dynamic_get_failure& ex) { |
94 | BOOST_TEST_CSTR_EQ(ex.what(), "dynamic property get cannot retrieve value for property: not_there." ); |
95 | // test idempotent error string generator branch |
96 | BOOST_TEST_CSTR_EQ(ex.what(), "dynamic property get cannot retrieve value for property: not_there." ); |
97 | } |
98 | } |
99 | |
100 | // Put tests |
101 | { |
102 | put(name: "int" ,dp&: properties,key: std::string("five" ),value: 6); |
103 | BOOST_TEST(get("int" ,properties,std::string("five" )) == "6" ); |
104 | put(name: "int" ,dp&: properties,key: std::string("five" ),value: std::string("5" )); |
105 | #ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS |
106 | BOOST_TEST(get<int>("int" ,properties,std::string("five" )) == 5); |
107 | #endif |
108 | BOOST_TEST(get("int" ,properties,std::string("five" ),type<int>()) == 5); |
109 | put(name: "double" ,dp&: properties,key: 3.14,value: std::string("3.14159" )); |
110 | BOOST_TEST(get("double" ,properties,3.14) == "3.14159" ); |
111 | put(name: "double" ,dp&: properties,key: 3.14,value: std::string("pi" )); |
112 | #ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS |
113 | BOOST_TEST(get<std::string>("double" ,properties,3.14) == "pi" ); |
114 | #endif |
115 | BOOST_TEST(get("double" ,properties,3.14,type<std::string>()) == "pi" ); |
116 | } |
117 | |
118 | // Nonexistent property |
119 | { |
120 | try { |
121 | get(name: "nope" ,dp: properties,key: 3.14); |
122 | BOOST_ERROR("No exception thrown." ); |
123 | } catch (boost::dynamic_get_failure&) { } |
124 | |
125 | try { |
126 | put(name: "nada" ,dp&: properties,key: 3.14,value: std::string("3.14159" )); |
127 | BOOST_ERROR("No exception thrown." ); |
128 | } catch (boost::property_not_found& ex) { |
129 | BOOST_TEST_CSTR_EQ(ex.what(), "Property not found: nada." ); |
130 | // test idempotent error string generator branch |
131 | BOOST_TEST_CSTR_EQ(ex.what(), "Property not found: nada." ); |
132 | } |
133 | } |
134 | |
135 | // Nonexistent property gets generated |
136 | { |
137 | boost::dynamic_properties props(&string2string_gen); |
138 | put(name: "nada" ,dp&: props,key: std::string("3.14" ),value: std::string("pi" )); |
139 | BOOST_TEST(get("nada" ,props,std::string("3.14" )) == "pi" ); |
140 | } |
141 | |
142 | // Use the ignore_other_properties generator |
143 | { |
144 | boost::dynamic_properties props(&boost::ignore_other_properties); |
145 | bool value = put(name: "nada" ,dp&: props,key: std::string("3.14" ),value: std::string("pi" )); |
146 | BOOST_TEST(value == false); |
147 | } |
148 | |
149 | return boost::report_errors(); |
150 | } |
151 | |