$search
00001 #include <boost/test/auto_unit_test.hpp> 00002 #include <vector> 00003 00004 #include <test/testsuite.hh> 00005 #include <utilmm/configfile/configset.hh> 00006 #include <utilmm/stringtools.hh> 00007 #include <typelib/pluginmanager.hh> 00008 #include <typelib/importer.hh> 00009 #include <typelib/typemodel.hh> 00010 #include <typelib/registry.hh> 00011 #include <typelib/value.hh> 00012 #include <typelib/value_ops.hh> 00013 #include "test_cimport.1" 00014 #include <string.h> 00015 using namespace Typelib; 00016 using namespace std; 00017 using utilmm::split; 00018 using utilmm::join; 00019 00020 template<int ptrsize> struct ptr_value_getter { }; 00021 template<> struct ptr_value_getter<4> { typedef uint32_t result; }; 00022 template<> struct ptr_value_getter<8> { typedef uint64_t result; }; 00023 00024 typedef ptr_value_getter<sizeof(void*)>::result ptr_value_t; 00025 ptr_value_t ptr_value(void* ptr) { return reinterpret_cast<ptr_value_t>(ptr); }; 00026 00027 BOOST_AUTO_TEST_CASE( test_vector_assumptions ) 00028 { 00029 // It is expected that ->size() depends on the type of the vector elements, 00030 // but that the size can be offset by using the ratio of sizeof() 00031 { 00032 vector<int32_t> values; 00033 values.resize(10); 00034 BOOST_REQUIRE_EQUAL(10, values.size()); 00035 BOOST_REQUIRE_EQUAL(5, reinterpret_cast< vector<int64_t>& >(values).size()); 00036 } 00037 { 00038 vector< vector<double> > values; 00039 values.resize(10); 00040 BOOST_REQUIRE_EQUAL(10, values.size()); 00041 BOOST_REQUIRE_EQUAL(10 * sizeof(vector<double>), reinterpret_cast< vector<int8_t>& >(values).size()); 00042 } 00043 00044 // To resize the containers efficiently, we assume that moving the bytes 00045 // around is fine. This is a valid assumption only if the std::vector's 00046 // internal structure does not store any pointer to the memory location 00047 // 00048 // This tests that this assumption is valid 00049 { 00050 vector< vector<double> > values; 00051 values.resize(10); 00052 00053 uint8_t* values_p = reinterpret_cast<uint8_t*>(&values); 00054 uint8_t* it_p = reinterpret_cast<uint8_t*>(&values); 00055 ptr_value_t vector_min = ptr_value(&values); 00056 ptr_value_t vector_max = ptr_value(&values) + sizeof(values); 00057 00058 while ((it_p + sizeof(void*)) - values_p < sizeof(values)) 00059 { 00060 ptr_value_t p = *reinterpret_cast<ptr_value_t*>(it_p); 00061 BOOST_REQUIRE(!(p >= vector_min && p < vector_max)); 00062 ++it_p; 00063 } 00064 } 00065 } 00066 00067 static void import_test_types(Registry& registry) 00068 { 00069 static const char* test_file = TEST_DATA_PATH("test_cimport.tlb"); 00070 00071 utilmm::config_set config; 00072 PluginManager::self manager; 00073 auto_ptr<Importer> importer(manager->importer("tlb")); 00074 BOOST_REQUIRE_NO_THROW( importer->load(test_file, config, registry) ); 00075 } 00076 00077 struct AssertValueVisit : public ValueVisitor 00078 { 00079 vector<int32_t> values; 00080 bool visit_(int32_t& v) 00081 { 00082 values.push_back(v); 00083 return true; 00084 } 00085 }; 00086 00087 BOOST_AUTO_TEST_CASE( test_vector_defines_aliases ) 00088 { 00089 Registry registry; 00090 import_test_types(registry); 00091 registry.alias("/B", "/BAlias"); 00092 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("B")); 00093 00094 Type const* aliased = registry.get("/std/vector</BAlias>"); 00095 BOOST_REQUIRE(aliased); 00096 BOOST_REQUIRE(*aliased == container); 00097 } 00098 00099 BOOST_AUTO_TEST_CASE( test_vector_getElementCount ) 00100 { 00101 Registry registry; 00102 import_test_types(registry); 00103 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("B")); 00104 00105 std::vector<B> vector; 00106 vector.resize(10); 00107 BOOST_REQUIRE_EQUAL(10, container.getElementCount(&vector)); 00108 } 00109 00110 BOOST_AUTO_TEST_CASE( test_vector_init_destroy ) 00111 { 00112 Registry registry; 00113 import_test_types(registry); 00114 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("B")); 00115 BOOST_REQUIRE_EQUAL(Type::Container, container.getCategory()); 00116 00117 void* v_memory = malloc(sizeof(std::vector<B>)); 00118 container.init(v_memory); 00119 BOOST_REQUIRE_EQUAL(0, container.getElementCount(v_memory)); 00120 container.destroy(v_memory); 00121 free(v_memory); 00122 } 00123 00124 BOOST_AUTO_TEST_CASE( test_vector_push ) 00125 { 00126 Registry registry; 00127 import_test_types(registry); 00128 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("int")); 00129 00130 std::vector<int> vector; 00131 for (int value = 0; value < 10; ++value) 00132 { 00133 container.push(&vector, Value(&value, container.getIndirection())); 00134 BOOST_REQUIRE_EQUAL(value + 1, vector.size()); 00135 00136 for (int i = 0; i < value; ++i) 00137 BOOST_REQUIRE_EQUAL(i, vector[i]); 00138 } 00139 } 00140 00141 BOOST_AUTO_TEST_CASE( test_vector_erase ) 00142 { 00143 Registry registry; 00144 import_test_types(registry); 00145 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("int")); 00146 00147 std::vector<int> vector; 00148 for (int value = 0; value < 10; ++value) 00149 vector.push_back(value); 00150 00151 int value = 20; 00152 BOOST_REQUIRE(!container.erase(&vector, Value(&value, container.getIndirection()))); 00153 value = 5; 00154 BOOST_REQUIRE(container.erase(&vector, Value(&value, container.getIndirection()))); 00155 00156 BOOST_REQUIRE_EQUAL(9, vector.size()); 00157 for (int i = 0; i < 5; ++i) 00158 BOOST_REQUIRE_EQUAL(i, vector[i]); 00159 for (int i = 5; i < 9; ++i) 00160 BOOST_REQUIRE_EQUAL(i + 1, vector[i]); 00161 } 00162 00163 bool test_delete_if_pred(Value v) 00164 { 00165 int* value = reinterpret_cast<int*>(v.getData()); 00166 return (*value > 3) && (*value < 6); 00167 } 00168 BOOST_AUTO_TEST_CASE( test_vector_delete_if ) 00169 { 00170 Registry registry; 00171 import_test_types(registry); 00172 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("int")); 00173 00174 std::vector<int> vector; 00175 for (int value = 0; value < 10; ++value) 00176 vector.push_back(value); 00177 00178 container.delete_if(&vector, test_delete_if_pred); 00179 00180 BOOST_REQUIRE_EQUAL(8, vector.size()); 00181 for (int i = 0; i < 4; ++i) 00182 BOOST_REQUIRE_EQUAL(i, vector[i]); 00183 for (int i = 4; i < 8; ++i) 00184 BOOST_REQUIRE_EQUAL(i + 2, vector[i]); 00185 } 00186 00187 BOOST_AUTO_TEST_CASE( test_vector_getElement ) 00188 { 00189 Registry registry; 00190 import_test_types(registry); 00191 00192 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("int32_t")); 00193 00194 std::vector<int32_t> v; 00195 v.resize(10); 00196 for (int i = 0; i < 10; ++i) 00197 v[i] = i; 00198 00199 for (int i = 0; i < 10; ++i) 00200 BOOST_REQUIRE_EQUAL(i, *reinterpret_cast<int*>(container.getElement(&v, i).getData())); 00201 } 00202 00203 BOOST_AUTO_TEST_CASE( test_vector_setElement ) 00204 { 00205 Registry registry; 00206 import_test_types(registry); 00207 00208 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("int32_t")); 00209 00210 std::vector<int32_t> v; 00211 v.resize(10); 00212 00213 for (int i = 0; i < 10; ++i) 00214 container.setElement(&v, i, Typelib::Value(&i, container.getIndirection())); 00215 00216 for (int i = 0; i < 10; ++i) 00217 BOOST_REQUIRE_EQUAL(i, v[i]); 00218 } 00219 00220 BOOST_AUTO_TEST_CASE( test_vector_visit ) 00221 { 00222 Registry registry; 00223 import_test_types(registry); 00224 00225 Container const& container = Container::createContainer(registry, "/std/vector", *registry.get("int32_t")); 00226 00227 std::vector<int32_t> v; 00228 v.resize(10); 00229 for (int i = 0; i < 10; ++i) 00230 v[i] = i; 00231 BOOST_REQUIRE_EQUAL(10, container.getElementCount(&v)); 00232 00233 // Try visiting the value 00234 Value value(&v, container); 00235 AssertValueVisit visitor; 00236 visitor.apply(value); 00237 00238 BOOST_REQUIRE_EQUAL(10, visitor.values.size()); 00239 for (int i = 0; i < 10; ++i) 00240 BOOST_REQUIRE_EQUAL(i, visitor.values[i]); 00241 } 00242 00243 BOOST_AUTO_TEST_CASE( test_erase_collection_of_collections ) 00244 { 00245 Registry registry; 00246 import_test_types(registry); 00247 Container const& inside = Container::createContainer(registry, "/std/vector", *registry.get("int32_t")); 00248 Container const& container = Container::createContainer(registry, "/std/vector", inside); 00249 00250 std::vector< std::vector<int32_t> > v; 00251 v.resize(10); 00252 for (int i = 0; i < 10; ++i) 00253 { 00254 v[i].resize(10); 00255 for (int j = 0; j < 10; ++j) 00256 v[i][j] = i * 100 + j; 00257 } 00258 std::vector<int32_t> new_element; 00259 new_element.push_back(1000); 00260 v.insert(v.begin() + 5, new_element); 00261 00262 BOOST_REQUIRE(container.erase(&v, Value(&new_element, inside))); 00263 00264 BOOST_REQUIRE_EQUAL(10, v.size()); 00265 00266 for (int i = 0; i < 10; ++i) 00267 { 00268 BOOST_REQUIRE_EQUAL(10, v[i].size()); 00269 for (int j = 0; j < 10; ++j) 00270 BOOST_REQUIRE_EQUAL(i * 100 + j, v[i][j]); 00271 } 00272 } 00273 00274 BOOST_AUTO_TEST_CASE( test_copy_collection_of_collections ) 00275 { 00276 Registry registry; 00277 import_test_types(registry); 00278 Container const& inside = Container::createContainer(registry, "/std/vector", *registry.get("int32_t")); 00279 Container const& container = Container::createContainer(registry, "/std/vector", inside); 00280 00281 std::vector< std::vector<int32_t> > v; 00282 v.resize(10); 00283 for (int i = 0; i < 10; ++i) 00284 { 00285 v[i].resize(10); 00286 for (int j = 0; j < 10; ++j) 00287 v[i][j] = i * 100 + j; 00288 } 00289 00290 std::vector< std::vector<int32_t> > copy; 00291 Typelib::copy(Value(©, container), Value(&v, container)); 00292 00293 for (int i = 0; i < 10; ++i) 00294 { 00295 BOOST_REQUIRE_EQUAL(10, v[i].size()); 00296 for (int j = 0; j < 10; ++j) 00297 BOOST_REQUIRE_EQUAL(i * 100 + j, v[i][j]); 00298 } 00299 00300 BOOST_REQUIRE( Typelib::compare(Value(©, container), Value(&v, container)) ); 00301 } 00302