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
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
00036 BOOST_AUTO_TEST_CASE( test_value_struct )
00037 {
00038
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
00090 BOOST_AUTO_TEST_CASE( test_value_array )
00091 {
00092
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
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
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,
00154 15, 14
00155 };
00156
00157
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
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
00182 {
00183 Type const& type = *registry.get("/B");
00184 CompileEndianSwapVisitor compiled;
00185 compiled.apply(type);
00186
00187
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
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
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
00223 {
00224 Type const& type = *registry.get("/C");
00225 CompileEndianSwapVisitor compiled;
00226 BOOST_CHECK_THROW(compiled.apply(type), Typelib::UnsupportedEndianSwap);
00227 }
00228
00229
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
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