test_value.cc
Go to the documentation of this file.
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 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Thu Jan 2 2014 11:38:41