$search
00001 #include <boost/test/auto_unit_test.hpp> 00002 00003 #include <lang/csupport/standard_types.hh> 00004 00005 #include <test/testsuite.hh> 00006 #include <utilmm/configfile/configset.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/endianness.hh> 00013 #include <typelib/value_cast.hh> 00014 using namespace Typelib; 00015 using namespace std; 00016 00017 #include "test_cimport.1" 00018 00019 // Tests simple value handling 00020 BOOST_AUTO_TEST_CASE( test_value_simple ) 00021 { 00022 Registry registry; 00023 Typelib::CXX::addStandardTypes(registry); 00024 00025 float f32 = 0.52; 00026 uint16_t ui16 = 15; 00027 int32_t i32 = 456; 00028 00029 BOOST_CHECK(f32 == value_cast<float>(&f32, *registry.get("float"))); 00030 BOOST_CHECK(ui16 == value_cast<uint16_t>(&ui16, *registry.get("uint16_t"))); 00031 BOOST_CHECK(i32 == value_cast<int32_t>(&i32, *registry.get("int32_t"))); 00032 BOOST_CHECK_THROW(value_cast<float>(&i32, *registry.get("int32_t")), BadValueCast); 00033 } 00034 00035 // Tests structure handling 00036 BOOST_AUTO_TEST_CASE( test_value_struct ) 00037 { 00038 // Get the test file into repository 00039 Registry registry; 00040 PluginManager::self manager; 00041 auto_ptr<Importer> importer(manager->importer("tlb")); 00042 utilmm::config_set config; 00043 BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) ); 00044 00045 { 00046 A a = { 10, 20, 'b', 52 }; 00047 Value v_a(&a, *registry.get("/A")); 00048 00049 BOOST_CHECK_THROW( value_get_field(v_a, "does_not_exists"), FieldNotFound ); 00050 BOOST_CHECK(a.a == value_cast<long long>(value_get_field(v_a, "a"))); 00051 BOOST_CHECK(a.b == value_cast<int>(value_get_field(v_a, "b"))); 00052 BOOST_CHECK(a.c == value_cast<char>(value_get_field(v_a, "c"))); 00053 BOOST_CHECK(a.d == value_cast<short>(value_get_field(v_a, "d"))); 00054 00055 B b; 00056 b.a = a; 00057 for (int i = 0; i < 100; ++i) 00058 b.c[i] = static_cast<float>(i) / 10.0f; 00059 00060 Value v_b(&b, *registry.get("/B")); 00061 Value v_b_a(value_get_field(v_b, "a")); 00062 BOOST_CHECK(a.a == value_cast<long long>(value_get_field(v_b_a, "a"))); 00063 BOOST_CHECK(a.b == value_cast<int>(value_get_field(v_b_a, "b"))); 00064 BOOST_CHECK(a.c == value_cast<char>(value_get_field(v_b_a, "c"))); 00065 BOOST_CHECK(a.d == value_cast<short>(value_get_field(v_b_a, "d"))); 00066 } 00067 } 00068 00069 00070 struct TestArrayVisitor : public ValueVisitor 00071 { 00072 size_t m_index; 00073 uint8_t* m_element; 00074 bool visit_(Value const& v, Array const& a) 00075 { 00076 m_element = static_cast<uint8_t*>(v.getData()) + m_index * a.getIndirection().getSize(); 00077 return false; 00078 } 00079 00080 public: 00081 uint8_t* apply(int index, Value v) 00082 { 00083 m_element = 0; 00084 m_index = index; 00085 ValueVisitor::apply(v); 00086 return m_element; 00087 } 00088 }; 00089 // Test array handling 00090 BOOST_AUTO_TEST_CASE( test_value_array ) 00091 { 00092 // Get the test file into repository 00093 Registry registry; 00094 Typelib::CXX::addStandardTypes(registry); 00095 00096 float test[10]; 00097 00098 Type const& array_type = *registry.build("/float[10]"); 00099 TestArrayVisitor visitor; 00100 uint8_t* e_0 = visitor.apply(0, Value(test, array_type)); 00101 uint8_t* e_9 = visitor.apply(9, Value(test, array_type)); 00102 BOOST_REQUIRE_EQUAL(e_0, reinterpret_cast<uint8_t*>(&test[0])); 00103 BOOST_REQUIRE_EQUAL(e_9, reinterpret_cast<uint8_t*>(&test[9])); 00104 } 00105 00106 BOOST_AUTO_TEST_CASE( test_value_endian_swap ) 00107 { 00108 // Get the test file into repository 00109 Registry registry; 00110 PluginManager::self manager; 00111 auto_ptr<Importer> importer(manager->importer("tlb")); 00112 utilmm::config_set config; 00113 BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) ); 00114 00115 A a = { 00116 utilmm::endian::swap((long long)10), 00117 utilmm::endian::swap((int)20), 00118 utilmm::endian::swap('b'), 00119 utilmm::endian::swap((short)52) 00120 }; 00121 B b; 00122 b.a = a; 00123 for (int i = 0; i < 10; ++i) 00124 b.c[i] = utilmm::endian::swap(static_cast<float>(i) / 10.0f); 00125 00126 Value v_b(&b, *registry.get("/B")); 00127 Typelib::endian_swap(v_b); 00128 00129 BOOST_REQUIRE_EQUAL(10, b.a.a); 00130 BOOST_REQUIRE_EQUAL(20, b.a.b); 00131 BOOST_REQUIRE_EQUAL('b', b.a.c); 00132 BOOST_REQUIRE_EQUAL(52, b.a.d); 00133 for (int i = 0; i < 10; ++i) 00134 BOOST_REQUIRE_EQUAL(static_cast<float>(i) / 10.0f, b.c[i]); 00135 00136 C c; 00137 Value v_c(&c, *registry.get("/C")); 00138 BOOST_CHECK_THROW(Typelib::endian_swap(v_c), Typelib::UnsupportedEndianSwap); 00139 } 00140 00141 BOOST_AUTO_TEST_CASE( test_compile_endian_swap ) 00142 { 00143 // Get the test file into repository 00144 Registry registry; 00145 PluginManager::self manager; 00146 auto_ptr<Importer> importer(manager->importer("tlb")); 00147 utilmm::config_set config; 00148 BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) ); 00149 00150 size_t expected_a[] = { 00151 CompileEndianSwapVisitor::FLAG_SWAP_8, 00152 CompileEndianSwapVisitor::FLAG_SWAP_4, 00153 CompileEndianSwapVisitor::FLAG_SKIP, 2, // char c plus one alignment byte 00154 15, 14 00155 }; 00156 00157 /* Check a simple structure with alignment issues */ 00158 { 00159 Type const& a_t = *registry.get("/A"); 00160 CompileEndianSwapVisitor compiled_a; 00161 compiled_a.apply(a_t); 00162 00163 size_t expected_size = sizeof(expected_a) / sizeof(size_t); 00164 00165 BOOST_REQUIRE_EQUAL(expected_size, compiled_a.m_compiled.size()); 00166 for (size_t i = 0; i < sizeof(expected_a) / sizeof(size_t); ++i) 00167 BOOST_REQUIRE_EQUAL(expected_a[i], compiled_a.m_compiled[i]); 00168 } 00169 00170 /* Check handling of byte arrays */ 00171 { 00172 Type const& type = *registry.build("/char[100]"); 00173 CompileEndianSwapVisitor compiled; 00174 compiled.apply(type); 00175 00176 BOOST_REQUIRE_EQUAL(2U, compiled.m_compiled.size()); 00177 BOOST_REQUIRE_EQUAL(CompileEndianSwapVisitor::FLAG_SKIP, compiled.m_compiled[0]); 00178 BOOST_REQUIRE_EQUAL(100U, compiled.m_compiled[1]); 00179 } 00180 00181 /* Check a structure with arrays */ 00182 { 00183 Type const& type = *registry.get("/B"); 00184 CompileEndianSwapVisitor compiled; 00185 compiled.apply(type); 00186 00187 // Check the first field, it should be equal to expected_a 00188 size_t offset = sizeof(expected_a) / sizeof(size_t); 00189 for (size_t i = 0; i < offset; ++i) 00190 BOOST_REQUIRE_EQUAL(expected_a[i], compiled.m_compiled[i]); 00191 00192 // The second field is an array of floats, check it 00193 size_t expected[] = { 00194 CompileEndianSwapVisitor::FLAG_ARRAY, 100, 4, 00195 CompileEndianSwapVisitor::FLAG_SWAP_4, 00196 CompileEndianSwapVisitor::FLAG_END 00197 }; 00198 00199 size_t expected_array_size = sizeof(expected) / sizeof(size_t); 00200 for (size_t i = 0; i < expected_array_size; ++i) 00201 BOOST_REQUIRE_EQUAL(expected[i], compiled.m_compiled[i + offset]); 00202 } 00203 00204 /* Check a multidimensional array */ 00205 { 00206 Type const& type = *registry.get("TestMultiDimArray"); 00207 CompileEndianSwapVisitor compiled; 00208 compiled.apply(type); 00209 00210 size_t expected[] = { 00211 CompileEndianSwapVisitor::FLAG_ARRAY, 100, 4, 00212 CompileEndianSwapVisitor::FLAG_SWAP_4, 00213 CompileEndianSwapVisitor::FLAG_END 00214 }; 00215 size_t expected_size = sizeof(expected) / sizeof(size_t); 00216 BOOST_REQUIRE_EQUAL(expected_size, compiled.m_compiled.size()); 00217 00218 for (size_t i = 0; i < expected_size; ++i) 00219 BOOST_REQUIRE_EQUAL(expected[i], compiled.m_compiled[i]); 00220 } 00221 00222 // Check a structure with pointer (must throw) 00223 { 00224 Type const& type = *registry.get("/C"); 00225 CompileEndianSwapVisitor compiled; 00226 BOOST_CHECK_THROW(compiled.apply(type), Typelib::UnsupportedEndianSwap); 00227 } 00228 00229 // Check an opaque type (must throw) 00230 { 00231 OpaqueType type("test_opaque", 10); 00232 CompileEndianSwapVisitor compiled; 00233 BOOST_CHECK_THROW(compiled.apply(type), Typelib::UnsupportedEndianSwap); 00234 } 00235 } 00236 00237 BOOST_AUTO_TEST_CASE( test_apply_endian_swap ) 00238 { 00239 // Get the test file into repository 00240 Registry registry; 00241 PluginManager::self manager; 00242 auto_ptr<Importer> importer(manager->importer("tlb")); 00243 utilmm::config_set config; 00244 BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) ); 00245 00246 A a = { 00247 utilmm::endian::swap((long long)10), 00248 utilmm::endian::swap((int)20), 00249 utilmm::endian::swap('b'), 00250 utilmm::endian::swap((short)52) 00251 }; 00252 B b; 00253 b.a = a; 00254 for (int i = 0; i < 10; ++i) 00255 b.c[i] = utilmm::endian::swap(static_cast<float>(i) / 10.0f); 00256 00257 b.d[0] = utilmm::endian::swap<float>(42); 00258 00259 for (int i = 0; i < 10; ++i) 00260 for (int j = 0; j < 10; ++j) 00261 b.i[i][j] = utilmm::endian::swap<float>(i * 100 + j); 00262 00263 Value v_b(&b, *registry.get("/B")); 00264 B swapped_b; 00265 Value v_swapped_b(&swapped_b, *registry.get("/B")); 00266 00267 CompileEndianSwapVisitor compiled; 00268 compiled.apply(v_b.getType()); 00269 compiled.swap(v_b, v_swapped_b); 00270 00271 BOOST_REQUIRE_EQUAL(10, swapped_b.a.a); 00272 BOOST_REQUIRE_EQUAL(20, swapped_b.a.b); 00273 BOOST_REQUIRE_EQUAL('b', swapped_b.a.c); 00274 BOOST_REQUIRE_EQUAL(52, swapped_b.a.d); 00275 for (int i = 0; i < 10; ++i) 00276 BOOST_REQUIRE_EQUAL(static_cast<float>(i) / 10.0f, swapped_b.c[i]); 00277 BOOST_REQUIRE_EQUAL(42, swapped_b.d[0]); 00278 for (int i = 0; i < 10; ++i) 00279 for (int j = 0; j < 10; ++j) 00280 BOOST_REQUIRE_EQUAL(i * 100 + j, swapped_b.i[i][j]); 00281 } 00282