test_marshalling.cc
Go to the documentation of this file.
00001 #include <boost/test/auto_unit_test.hpp>
00002 
00003 #include <test/testsuite.hh>
00004 #include <typelib/utilmm/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/value_ops.hh>
00011 
00012 #include <test/test_cimport.1>
00013 #include <string.h>
00014 
00015 using namespace Typelib;
00016 using namespace std;
00017 
00018 BOOST_AUTO_TEST_CASE( test_marshalling_simple )
00019 {
00020     // Get the test file into repository
00021     Registry registry;
00022     PluginManager::self manager;
00023     auto_ptr<Importer> importer(manager->importer("tlb"));
00024     utilmm::config_set config;
00025     BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) );
00026 
00027     /* Check a simple structure which translates into MEMCPY */
00028     {
00029         Type const& type = *registry.get("/A");
00030         A a;
00031         memset(&a, 1, sizeof(A));
00032         a.a = 10000;
00033         a.b = 1000;
00034         a.c = 100;
00035         a.d = 10;
00036         vector<uint8_t> buffer = dump(Value(&a, type));
00037 
00038         size_t expected_dump_size = offsetof(A, d) + sizeof(a.d);
00039         BOOST_REQUIRE_EQUAL( buffer.size(), expected_dump_size);
00040         BOOST_REQUIRE( !memcmp(&buffer[0], &a, expected_dump_size) );
00041 
00042         A reloaded;
00043         load(Value(&reloaded, type), buffer);
00044         BOOST_REQUIRE( !memcmp(&reloaded, &a, expected_dump_size) );
00045 
00046         // Try (in order)
00047         //  - smaller type
00048         //  - bigger type
00049         //  - bigger buffer
00050         //  - smaller buffer
00051         BOOST_REQUIRE_THROW(load(Value(&reloaded, *registry.build("/int[200]")), buffer), std::runtime_error);
00052         BOOST_REQUIRE_THROW(load(Value(&reloaded, *registry.get("/int")), buffer), std::runtime_error);
00053         buffer.resize(buffer.size() + 2);
00054         BOOST_REQUIRE_THROW(load(Value(&reloaded, type), buffer), std::runtime_error);
00055         buffer.resize(buffer.size() - 4);
00056         BOOST_REQUIRE_THROW(load(Value(&reloaded, type), buffer), std::runtime_error);
00057     }
00058 
00059     /* Now, insert SKIPS into it */
00060     {
00061         A a;
00062         size_t align1 = offsetof(A, b) - sizeof(a.a);
00063         size_t align2 = offsetof(A, c) - sizeof(a.b) - offsetof(A, b);
00064         size_t align3 = offsetof(A, d) - sizeof(a.c) - offsetof(A, c);
00065         size_t align4 = sizeof(A)      - sizeof(a.d) - offsetof(A, d);
00066         size_t raw_ops[] = {
00067             MemLayout::FLAG_MEMCPY, sizeof(long long),
00068             MemLayout::FLAG_SKIP, align1,
00069             MemLayout::FLAG_MEMCPY, sizeof(int),
00070             MemLayout::FLAG_SKIP, align2,
00071             MemLayout::FLAG_MEMCPY, sizeof(char),
00072             MemLayout::FLAG_SKIP, align3,
00073             MemLayout::FLAG_MEMCPY, sizeof(short)
00074         };
00075 
00076         MemoryLayout ops;
00077         ops.insert(ops.end(), raw_ops, raw_ops + 14);
00078 
00079         Type const& type = *registry.get("/A");
00080         memset(&a, 1, sizeof(A));
00081         a.a = 10000;
00082         a.b = 1000;
00083         a.c = 100;
00084         a.d = 10;
00085         vector<uint8_t> buffer;
00086         dump(Value(&a, type), buffer, ops);
00087         BOOST_REQUIRE_EQUAL( sizeof(A) - align1 - align2 - align3 - align4, buffer.size());
00088         BOOST_REQUIRE_EQUAL( *reinterpret_cast<long long*>(&buffer[0]), a.a );
00089 
00090         A reloaded;
00091         memset(&reloaded, 2, sizeof(A));
00092         load(Value(&reloaded, type), buffer, ops);
00093         BOOST_REQUIRE(memcmp(&a, &reloaded, sizeof(A)) < 0);
00094         BOOST_REQUIRE_EQUAL(a.a, reloaded.a);
00095         BOOST_REQUIRE_EQUAL(a.b, reloaded.b);
00096         BOOST_REQUIRE_EQUAL(a.c, reloaded.c);
00097         BOOST_REQUIRE_EQUAL(a.d, reloaded.d);
00098     }
00099 
00100     // And now check the array semantics
00101     {
00102         B b;
00103         for (unsigned int i = 0; i < sizeof(b); ++i)
00104             reinterpret_cast<uint8_t*>(&b)[i] = rand();
00105 
00106         size_t raw_ops[] = {
00107             MemLayout::FLAG_MEMCPY, offsetof(B, c),
00108             MemLayout::FLAG_ARRAY, 100,
00109                 MemLayout::FLAG_MEMCPY, sizeof(b.c[0]),
00110             MemLayout::FLAG_END,
00111             MemLayout::FLAG_MEMCPY, sizeof(B) - offsetof(B, d)
00112         };
00113 
00114         MemoryLayout ops;
00115         ops.insert(ops.end(), raw_ops, raw_ops + 9);
00116 
00117         Type const& type = *registry.get("/B");
00118         vector<uint8_t> buffer;
00119         dump(Value(&b, type), buffer, ops);
00120         BOOST_REQUIRE_EQUAL( sizeof(B), buffer.size());
00121         BOOST_REQUIRE(!memcmp(&buffer[0], &b, sizeof(B)));
00122 
00123         B reloaded;
00124         load(Value(&reloaded, type), buffer, ops);
00125         BOOST_REQUIRE(!memcmp(&b, &reloaded, sizeof(B)));
00126     }
00127 }
00128 
00129 template<typename T>
00130 size_t CHECK_SIMPLE_VALUE(vector<uint8_t> const& buffer, size_t offset, T value)
00131 {
00132     BOOST_REQUIRE_EQUAL(value, *reinterpret_cast<T const*>(&buffer[offset]));
00133     return offset + sizeof(T);
00134 }
00135 
00136 template<typename T>
00137 size_t CHECK_VECTOR_VALUE(vector<uint8_t> const& buffer, size_t offset, vector<T> const& value)
00138 {
00139     // First, check for the size
00140     offset = CHECK_SIMPLE_VALUE(buffer, offset, static_cast<uint64_t>(value.size()));
00141     // Then for the elements
00142     for (size_t i = 0; i < value.size(); ++i)
00143         offset = CHECK_SIMPLE_VALUE(buffer, offset, value[i]);
00144     return offset;
00145 }
00146 
00147 BOOST_AUTO_TEST_CASE(test_marshalapply_containers)
00148 {
00149     // Get the test file into repository
00150     Registry registry;
00151     PluginManager::self manager;
00152     auto_ptr<Importer> importer(manager->importer("tlb"));
00153     utilmm::config_set config;
00154     BOOST_REQUIRE_NO_THROW( importer->load(TEST_DATA_PATH("test_cimport.tlb"), config, registry) );
00155 
00156     StdCollections offset_discovery;
00157     uint8_t* base_ptr     = reinterpret_cast<uint8_t*>(&offset_discovery);
00158     size_t off_dbl_vector = reinterpret_cast<uint8_t*>(&offset_discovery.dbl_vector) - base_ptr;
00159     size_t off_v8         = reinterpret_cast<uint8_t*>(&offset_discovery.v8) - base_ptr;
00160     size_t off_v_of_v     = reinterpret_cast<uint8_t*>(&offset_discovery.v_of_v) - base_ptr;
00161 
00162     {
00163         StdCollections data;
00164         data.iv = 10;
00165         data.dbl_vector.resize(5);
00166         for (int i = 0; i < 5; ++i)
00167             data.dbl_vector[i] = 0.01 * i;
00168         data.v8  = -106;
00169         data.v_of_v.resize(5);
00170         for (int i = 0; i < 5; ++i)
00171         {
00172             data.v_of_v[i].resize(3);
00173             for (int j = 0; j < 3; ++j)
00174                 data.v_of_v[i][j] = i * 10 + j;
00175         }
00176         data.v16 = 5235;
00177         data.v64 = 5230971546LL;
00178 
00179         Type const& type       = *registry.get("/StdCollections");
00180         vector<uint8_t> buffer = dump(Value(&data, type));
00181 
00182         size_t size_without_trailing_padding = 
00183             reinterpret_cast<uint8_t const*>(&data.padding) + sizeof(data.padding) - reinterpret_cast<uint8_t const*>(&data)
00184                 - sizeof(std::vector<double>) - sizeof (std::vector< std::vector<double> >)
00185                 + sizeof(double) * 20 // elements
00186                 + 7 * sizeof(uint64_t);
00187 
00188         BOOST_REQUIRE_EQUAL( buffer.size(), size_without_trailing_padding );
00189 
00190         CHECK_SIMPLE_VALUE(buffer, 0, data.iv);
00191         size_t pos = CHECK_VECTOR_VALUE(buffer, off_dbl_vector, data.dbl_vector);
00192         CHECK_SIMPLE_VALUE(buffer, pos, data.v8);
00193 
00194         pos = CHECK_SIMPLE_VALUE(buffer, pos + off_v_of_v - off_v8, static_cast<uint64_t>(data.v_of_v.size()));
00195         for (int i = 0; i < 5; ++i)
00196             pos = CHECK_VECTOR_VALUE(buffer, pos, data.v_of_v[i]);
00197 
00198         StdCollections reloaded;
00199         load(Value(&reloaded, type), buffer);
00200         BOOST_REQUIRE( data.iv         == reloaded.iv );
00201         BOOST_REQUIRE( data.dbl_vector == reloaded.dbl_vector );
00202         BOOST_REQUIRE( data.v8         == reloaded.v8 );
00203         BOOST_REQUIRE( data.v16        == reloaded.v16 );
00204         BOOST_REQUIRE( data.v64        == reloaded.v64 );
00205         BOOST_REQUIRE( data.padding        == reloaded.padding );
00206 
00207         // Now, add the trailing bytes back. The load method should be OK with
00208         // it
00209         size_t size_with_trailing_padding =
00210             sizeof(StdCollections)
00211                 - sizeof(std::vector<double>) - sizeof (std::vector< std::vector<double> >)
00212                 + sizeof(double) * 20 // elements
00213                 + 7 * sizeof(uint64_t); // element counts
00214 
00215         buffer.insert(buffer.end(), size_with_trailing_padding - size_without_trailing_padding, 0);
00216         {
00217             StdCollections reloaded;
00218             load(Value(&reloaded, type), buffer);
00219             BOOST_REQUIRE( data.iv         == reloaded.iv );
00220             BOOST_REQUIRE( data.dbl_vector == reloaded.dbl_vector );
00221             BOOST_REQUIRE( data.v8         == reloaded.v8 );
00222             BOOST_REQUIRE( data.v16        == reloaded.v16 );
00223             BOOST_REQUIRE( data.v64        == reloaded.v64 );
00224             BOOST_REQUIRE( data.padding        == reloaded.padding );
00225         }
00226     }
00227 
00228     {
00229         StdCollections data;
00230         
00231         data.iv = 0;
00232         data.v8 = 1;
00233         data.v_of_v.resize(5);
00234         data.v16 = 2;
00235         data.v64 = 3;
00236 
00237         Type const& type       = *registry.get("/StdCollections");
00238         vector<uint8_t> buffer = dump(Value(&data, type));
00239         size_t size_without_trailing_padding = 
00240             reinterpret_cast<uint8_t const*>(&data.padding) + sizeof(data.padding) - reinterpret_cast<uint8_t const*>(&data);
00241         BOOST_REQUIRE_EQUAL( buffer.size(),
00242                 size_without_trailing_padding - sizeof(std::vector<double>) - sizeof (std::vector< std::vector<double> >)
00243                 + 7 * sizeof(uint64_t)); // element counts
00244 
00245         CHECK_SIMPLE_VALUE(buffer, 0, data.iv);
00246         size_t pos = CHECK_VECTOR_VALUE(buffer, off_dbl_vector, data.dbl_vector);
00247         CHECK_SIMPLE_VALUE(buffer, pos, data.v8);
00248 
00249         pos = CHECK_SIMPLE_VALUE(buffer, pos + off_v_of_v - off_v8, static_cast<uint64_t>(data.v_of_v.size()));
00250         for (int i = 0; i < 5; ++i)
00251             pos = CHECK_VECTOR_VALUE(buffer, pos, data.v_of_v[i]);
00252     }
00253 }
00254 


typelib
Author(s): Sylvain Joyeux/sylvain.joyeux@m4x.org
autogenerated on Sat Jun 8 2019 18:49:22