$search
00001 #include <boost/test/auto_unit_test.hpp> 00002 00003 #include <test/testsuite.hh> 00004 #include <utilmm/configfile/configset.hh> 00005 #include <typelib/pluginmanager.hh> 00006 #include <typelib/importer.hh> 00007 #include <typelib/typemodel.hh> 00008 #include <typelib/registry.hh> 00009 #include <typelib/value.hh> 00010 #include <typelib/memory_layout.hh> 00011 00012 00013 #include <typelib/value_ops.hh> 00014 #include <test/test_cimport.1> 00015 #include <string.h> 00016 00017 using namespace Typelib; 00018 using namespace std; 00019 00020 BOOST_AUTO_TEST_CASE( test_layout_simple ) 00021 { 00022 // Get the test file into repository 00023 Registry registry; 00024 PluginManager::self manager; 00025 auto_ptr<Importer> importer(manager->importer("tlb")); 00026 utilmm::config_set config; 00027 BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) ); 00028 00029 /* Check a simple structure with alignment issues */ 00030 { 00031 Type const& type = *registry.get("/A"); 00032 MemoryLayout ops = Typelib::layout_of(type); 00033 00034 BOOST_REQUIRE_EQUAL(2U, ops.size()); 00035 BOOST_REQUIRE_EQUAL(MemLayout::FLAG_MEMCPY, ops[0]); 00036 A data; 00037 BOOST_REQUIRE_EQUAL(offsetof(A, d) + sizeof(data.d), ops[1]); 00038 } 00039 00040 /* Check handling of simple arrays */ 00041 { 00042 Type const& type = *registry.build("/char[100]"); 00043 MemoryLayout ops = Typelib::layout_of(type); 00044 00045 BOOST_REQUIRE_EQUAL(2U, ops.size()); 00046 BOOST_REQUIRE_EQUAL(MemLayout::FLAG_MEMCPY, ops[0]); 00047 BOOST_REQUIRE_EQUAL(100U, ops[1]); 00048 } 00049 00050 /* Check a structure with arrays */ 00051 { 00052 Type const& type = *registry.get("/B"); 00053 MemoryLayout ops = Typelib::layout_of(type); 00054 00055 BOOST_REQUIRE_EQUAL(2U, ops.size()); 00056 BOOST_REQUIRE_EQUAL(MemLayout::FLAG_MEMCPY, ops[0]); 00057 B data; 00058 BOOST_REQUIRE_EQUAL(offsetof(B, z) + sizeof(data.z), ops[1]); 00059 } 00060 00061 /* Check a multidimensional array */ 00062 { 00063 Type const& type = *registry.get("TestMultiDimArray"); 00064 MemoryLayout ops = Typelib::layout_of(type); 00065 00066 BOOST_REQUIRE_EQUAL(2U, ops.size()); 00067 BOOST_REQUIRE_EQUAL(MemLayout::FLAG_MEMCPY, ops[0]); 00068 BOOST_REQUIRE_EQUAL(type.getSize(), ops[1]); 00069 } 00070 00071 // Check a structure with pointer. Must throw by default, but accept if the 00072 // accept_pointers flag is set, in which case FLAG_MEMCPY is used for it. 00073 { 00074 Type const& type = *registry.get("/C"); 00075 BOOST_CHECK_THROW(Typelib::layout_of(type), Typelib::NoLayout); 00076 00077 MemoryLayout ops = Typelib::layout_of(type, true); 00078 BOOST_REQUIRE_EQUAL(2, ops.size()); 00079 BOOST_REQUIRE_EQUAL(MemLayout::FLAG_MEMCPY, ops[0]); 00080 C data; 00081 BOOST_REQUIRE_EQUAL(offsetof(C, z) + sizeof(data.z), ops[1]); 00082 } 00083 00084 // Check an opaque type 00085 { 00086 OpaqueType type("test_opaque", 10); 00087 BOOST_CHECK_THROW(Typelib::layout_of(type), Typelib::NoLayout); 00088 } 00089 } 00090 00091 BOOST_AUTO_TEST_CASE(test_layout_arrays) 00092 { 00093 // Get the test file into repository 00094 Registry registry; 00095 PluginManager::self manager; 00096 auto_ptr<Importer> importer(manager->importer("tlb")); 00097 utilmm::config_set config; 00098 BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) ); 00099 00100 { 00101 Type const& type = *registry.get("/Arrays"); 00102 Compound const& str = static_cast<Compound const&>(*registry.get("/NS1/Test")); 00103 BOOST_REQUIRE(str.getSize() != str.getField("b")->getOffset() + str.getField("b")->getType().getSize()); 00104 00105 Type const& v_str = *registry.get("/std/vector</NS1/Test>"); 00106 Type const& v_double = *registry.get("/std/vector</double>"); 00107 MemoryLayout ops = Typelib::layout_of(type); 00108 00109 StdCollections test; 00110 00111 Arrays arrays_v; 00112 size_t expected[] = { 00113 MemLayout::FLAG_MEMCPY, 00114 reinterpret_cast<uint8_t*>(&arrays_v.a_v_numeric) - reinterpret_cast<uint8_t*>(&arrays_v), 00115 MemLayout::FLAG_ARRAY, 00116 10, 00117 MemLayout::FLAG_CONTAINER, 00118 reinterpret_cast<size_t>(&v_double), 00119 MemLayout::FLAG_MEMCPY, 00120 sizeof(double), 00121 MemLayout::FLAG_END, 00122 MemLayout::FLAG_END, 00123 MemLayout::FLAG_MEMCPY, 00124 reinterpret_cast<uint8_t*>(&arrays_v.a_v_struct[0]) - reinterpret_cast<uint8_t*>(&arrays_v.padding3), 00125 MemLayout::FLAG_ARRAY, 00126 10, 00127 MemLayout::FLAG_CONTAINER, 00128 reinterpret_cast<size_t>(&v_str), 00129 MemLayout::FLAG_MEMCPY, 00130 sizeof(NS1::Test), 00131 MemLayout::FLAG_END, 00132 MemLayout::FLAG_END, 00133 MemLayout::FLAG_MEMCPY, 00134 sizeof(char) 00135 }; 00136 00137 for (size_t i = 0; i < ops.size(); ++i) 00138 if (expected[i] != ops[i]) 00139 { 00140 Typelib::display(cerr, ops.begin(), ops.end()); 00141 std::cerr << "error at index " << i << std::endl; 00142 BOOST_REQUIRE_EQUAL(expected[i], ops[i]); 00143 } 00144 00145 // Check that we have all the operations that we need 00146 size_t expected_size = sizeof(expected) / sizeof(size_t); 00147 BOOST_REQUIRE_EQUAL(expected_size, ops.size()); 00148 } 00149 } 00150 00151 BOOST_AUTO_TEST_CASE(test_layout_containers) 00152 { 00153 // Get the test file into repository 00154 Registry registry; 00155 PluginManager::self manager; 00156 auto_ptr<Importer> importer(manager->importer("tlb")); 00157 utilmm::config_set config; 00158 BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) ); 00159 00160 { 00161 Type const& type = *registry.get("/Collections"); 00162 Compound const& str = static_cast<Compound const&>(*registry.get("/NS1/Test")); 00163 BOOST_REQUIRE(str.getSize() != str.getField("b")->getOffset() + str.getField("b")->getType().getSize()); 00164 00165 Type const& v_str = *registry.get("/std/vector</NS1/Test>"); 00166 Type const& v_v_str = *registry.get("/std/vector</std/vector</NS1/Test>>"); 00167 Type const& v_double = *registry.get("/std/vector</double>"); 00168 Type const& v_v_double = *registry.get("/std/vector</std/vector</double>>"); 00169 MemoryLayout ops = Typelib::layout_of(type); 00170 00171 Collections value; 00172 00173 size_t expected[] = { 00174 MemLayout::FLAG_CONTAINER, 00175 reinterpret_cast<size_t>(&v_double), 00176 MemLayout::FLAG_MEMCPY, 00177 sizeof(double), 00178 MemLayout::FLAG_END, 00179 MemLayout::FLAG_MEMCPY, 00180 reinterpret_cast<uint8_t*>(&value.v_struct) - reinterpret_cast<uint8_t*>(&value.padding1), 00181 MemLayout::FLAG_CONTAINER, 00182 reinterpret_cast<size_t>(&v_str), 00183 MemLayout::FLAG_MEMCPY, 00184 sizeof(NS1::Test), 00185 MemLayout::FLAG_END, 00186 MemLayout::FLAG_MEMCPY, 00187 reinterpret_cast<uint8_t*>(&value.v_v_numeric) - reinterpret_cast<uint8_t*>(&value.padding2), 00188 MemLayout::FLAG_CONTAINER, 00189 reinterpret_cast<size_t>(&v_v_double), 00190 MemLayout::FLAG_CONTAINER, 00191 reinterpret_cast<size_t>(&v_double), 00192 MemLayout::FLAG_MEMCPY, 00193 sizeof(double), 00194 MemLayout::FLAG_END, 00195 MemLayout::FLAG_END, 00196 MemLayout::FLAG_MEMCPY, 00197 reinterpret_cast<uint8_t*>(&value.v_v_struct) - reinterpret_cast<uint8_t*>(&value.padding3), 00198 MemLayout::FLAG_CONTAINER, 00199 reinterpret_cast<size_t>(&v_v_str), 00200 MemLayout::FLAG_CONTAINER, 00201 reinterpret_cast<size_t>(&v_str), 00202 MemLayout::FLAG_MEMCPY, 00203 sizeof(NS1::Test), 00204 MemLayout::FLAG_END, 00205 MemLayout::FLAG_END, 00206 MemLayout::FLAG_MEMCPY, 00207 sizeof(char) 00208 }; 00209 00210 for (size_t i = 0; i < ops.size(); ++i) 00211 if (expected[i] != ops[i]) 00212 { 00213 Typelib::display(cerr, ops.begin(), ops.end()); 00214 std::cerr << "error at index " << i << std::endl; 00215 BOOST_REQUIRE_EQUAL(expected[i], ops[i]); 00216 } 00217 00218 // Check that we have all the operations that we need 00219 size_t expected_size = sizeof(expected) / sizeof(size_t); 00220 BOOST_REQUIRE_EQUAL(expected_size, ops.size()); 00221 } 00222 } 00223