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/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
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
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
00047
00048
00049
00050
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
00060 {
00061 A a;
00062 int align1 = offsetof(A, b) - sizeof(a.a);
00063 int align2 = offsetof(A, c) - sizeof(a.b) - offsetof(A, b);
00064 int align3 = offsetof(A, d) - sizeof(a.c) - offsetof(A, c);
00065 int 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_EQUAL(-1, memcmp(&a, &reloaded, sizeof(A)));
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
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
00140 offset = CHECK_SIMPLE_VALUE(buffer, offset, static_cast<uint64_t>(value.size()));
00141
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
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
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
00208
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
00213 + 7 * sizeof(uint64_t);
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));
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