882510096ed3a37f0d3aac72295f09a7a7f61fda
[senf.git] / senf / Packets / ListBParser.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief ListBParser unit tests */
25
26 //#include "ListBParser.test.hh"
27 //#include "ListBParser.test.ih"
28
29 // Custom includes
30 #include "Packets.hh"
31
32 #include <senf/Utils/auto_unit_test.hh>
33 #include <boost/test/test_tools.hpp>
34
35 #define prefix_
36 ///////////////////////////////cc.p////////////////////////////////////////
37
38 namespace {
39     struct VoidPacket : public senf::PacketTypeBase
40     {};
41
42     struct VectorParser : public senf::PacketParserBase
43     {
44 #       include SENF_PARSER()
45
46         SENF_PARSER_PRIVATE_FIELD( size, senf::UInt8Parser );
47         SENF_PARSER_VECTOR( vec, size, senf::UInt16Parser );
48
49         SENF_PARSER_FINALIZE(VectorParser);
50
51         typedef std::vector<boost::uint16_t> value_type;
52
53         value_type value() const {
54             value_type v (vec().begin(), vec().end());
55             return v;
56         }
57         void value(value_type const & v) {
58             vec_t::container container (vec());
59             container.clear();
60             for (value_type::const_iterator i=v.begin(); i!=v.end(); ++i)
61                 container.push_back( *i);
62         }
63         operator value_type() const { return value(); }
64         VectorParser const & operator= (value_type const & other) { value(other); return *this; }
65     };
66
67     typedef senf::ListParser<
68         senf::detail::ListBParser_Policy<
69             VectorParser,
70             senf::detail::PrefixAuxParserPolicy<senf::UInt16Parser> > > MyListBParser;
71 }
72
73 SENF_AUTO_UNIT_TEST(ListBParser)
74 {
75     senf::PacketInterpreterBase::ptr pi (senf::PacketInterpreter<VoidPacket>::create(
76             MyListBParser::init_bytes));
77
78     MyListBParser p (pi->data().begin(),&pi->data());
79     p.init();
80     BOOST_CHECK_EQUAL( p.size(), 0u );
81     BOOST_CHECK_EQUAL( p.bytes(), 2u );
82     BOOST_CHECK( p.empty() );
83
84     // the mutators are really tested together with the container wrappers since they are based
85     // on the container wrapper. Here we only need one call to make the list larger ...
86
87     p.push_back_space();
88     p = MyListBParser(pi->data().begin(),&pi->data());
89     BOOST_CHECK_EQUAL( p.bytes(), 3u );
90     BOOST_CHECK_EQUAL( p.size(), 1u );
91     BOOST_CHECK( ! p.empty() );
92 }
93
94 SENF_AUTO_UNIT_TEST(ListBParser_container)
95 {
96     senf::PacketInterpreterBase::ptr pi (senf::PacketInterpreter<VoidPacket>::create(
97             MyListBParser::init_bytes));
98
99     {
100         MyListBParser::container c (MyListBParser(pi->data().begin(),&pi->data()));
101
102         BOOST_CHECK_EQUAL( c.size(), 0u );
103         BOOST_CHECK_EQUAL( c.bytes(), 2u );
104         BOOST_CHECK( c.begin() == c.end() );
105
106         c.shift(c.begin());
107         BOOST_CHECK_EQUAL( c.size(), 1u );
108         BOOST_CHECK_EQUAL( c.bytes(), 3u );
109
110         BOOST_CHECK_EQUAL( c.front().vec().size(), 0u );
111         c.front().vec().push_back(0x1234u);
112         BOOST_CHECK_EQUAL( c.bytes(), 5u );
113
114         {
115             senf::PacketInterpreterBase::ptr pi2 (senf::PacketInterpreter<VoidPacket>::create(
116                     MyListBParser::init_bytes));
117             MyListBParser::container c2 (MyListBParser(pi2->data().begin(),&pi2->data()));
118             {
119                 VectorParser::vec_t::container c2v (c2.push_back_space().vec());
120                 c2v.push_back(0x2345u);
121                 c2v.push_back(0x3456u);
122             }
123
124             BOOST_CHECK_EQUAL(c2.size(), 1u);
125             BOOST_CHECK_EQUAL(c2.bytes(), 7u);
126
127             c.insert(c.end(),c2.back());
128             BOOST_CHECK_EQUAL( c.size(), 2u );
129             BOOST_CHECK_EQUAL( c.bytes(), 10u );
130             BOOST_CHECK_EQUAL( c.back().vec()[0], 0x2345u );
131             BOOST_CHECK_EQUAL( c.back().bytes(), c2.back().bytes() );
132
133             c2.back().vec()[0] << 0x1357u;
134             c.insert(boost::next(c.begin()), 2u, c2.back());
135             BOOST_CHECK_EQUAL( c.size(), 4u );
136             BOOST_CHECK_EQUAL( c.bytes(), 20u );
137             BOOST_CHECK_EQUAL( (*boost::next(c.begin())).vec()[0], 0x1357u );
138             BOOST_CHECK_EQUAL( (*boost::next(c.begin(),2)).vec()[0], 0x1357u );
139
140             c2.back().vec()[0] << 0x2468u;
141             c.insert(c.begin(),c2.begin(),c2.end());
142             BOOST_CHECK_EQUAL( c.size(), 5u );
143             BOOST_CHECK_EQUAL( c.bytes(), 25u );
144             BOOST_CHECK_EQUAL( c.front().vec()[0], 0x2468u );
145
146             c.erase(c.begin(),2);
147             BOOST_CHECK_EQUAL( c.size(), 3u );
148             BOOST_CHECK_EQUAL( c.bytes(), 17u );
149             BOOST_CHECK_EQUAL( c.front().vec()[0],0x1357u );
150             BOOST_CHECK_EQUAL( c.back().vec()[0], 0x2345u );
151
152             c.erase((boost::next(c.begin(),2)),c.end());
153             BOOST_CHECK_EQUAL( c.size(), 2u );
154             BOOST_CHECK_EQUAL( c.bytes(), 12u );
155             BOOST_CHECK_EQUAL( c.front().vec()[0],0x1357u );
156             BOOST_CHECK_EQUAL( c.back().vec()[0], 0x1357u );
157
158             c.clear();
159             BOOST_CHECK_EQUAL( c.size(), 0u );
160             BOOST_CHECK_EQUAL( c.bytes(), 2u );
161        }
162     }
163 }
164
165 namespace {
166
167     struct TestTransform
168     {
169         typedef unsigned value_type;
170         static unsigned get(unsigned v) { return v/2; }
171         static unsigned set(unsigned v) { return 2*v; }
172     };
173
174     struct TestListParser
175         : public senf::PacketParserBase
176     {
177 #       include SENF_PARSER()
178
179         SENF_PARSER_PRIVATE_FIELD ( size1 , senf::UInt8Parser );
180         SENF_PARSER_PRIVATE_FIELD ( size2 , senf::UInt8Parser );
181         SENF_PARSER_FIELD         ( dummy , senf::UInt32Parser );
182         SENF_PARSER_LIST          ( list1  , bytes(size1) , VectorParser );
183         SENF_PARSER_LIST          ( list2  , transform(TestTransform, bytes(size2)) ,
184                                              VectorParser );
185
186         SENF_PARSER_FINALIZE(TestListParser);
187     };
188
189     struct TestListPacketType
190         : public senf::PacketTypeBase,
191           public senf::PacketTypeMixin<TestListPacketType>
192     {
193         typedef senf::PacketTypeMixin<TestListPacketType> mixin;
194         typedef senf::ConcretePacket<TestListPacketType> packet;
195         typedef TestListParser parser;
196
197         using mixin::nextPacketRange;
198         using mixin::initSize;
199         using mixin::init;
200     };
201     typedef senf::ConcretePacket<TestListPacketType> TestListPacket;
202
203 }
204
205 SENF_AUTO_UNIT_TEST(listBytesMacro)
206 {
207     unsigned char data[] = {    8,                   // size1
208                                18,                   // size2
209                              0x01, 0x02, 0x03, 0x04, // dummy
210                              0x01,                   // list1()[0].size()
211                              0x05, 0x06,             // list1().vec()[0]
212                              0x02,                   // list1()[1].size()
213                              0x07, 0x08,             // list1()[1].vec()[0]
214                              0x09, 0x0A,             // list1()[1].vec()[1]
215                              0x00,                   // list2()[0].size()
216                              0x02,                   // list2()[1].size()
217                              0x0B, 0x0C,             // list2()[1].vec()[0]
218                              0x0D, 0x0E,             // list2()[1].vec()[1]
219                              0x01,                   // list2()[2].size()
220                              0x0F, 0x10 };           // list2()[2].vec()[0]
221
222     senf::DataPacket p (senf::DataPacket::create(data));
223     TestListParser parser (p.data().begin(), &p.data());
224
225     BOOST_CHECK_EQUAL( parser.list1().size(), 2u );
226     BOOST_CHECK_EQUAL( parser.list2().size(), 3u );
227     BOOST_CHECK_EQUAL( parser.dummy(), 0x01020304u );
228
229     TestListParser::list2_t::container list2 (parser.list2());
230
231     {
232         TestListParser::list1_t::container list (parser.list1());
233         BOOST_CHECK_EQUAL( list.size(), 2u );
234
235         TestListParser::list1_t::container::iterator i (list.begin());
236         BOOST_CHECK_EQUAL( i->vec().size(), 1u );
237         BOOST_CHECK_EQUAL( i->vec()[0], 0x0506u );
238
239         ++i;
240         BOOST_CHECK_EQUAL( i->vec().size(), 2u );
241         BOOST_CHECK_EQUAL( i->vec()[0], 0x0708u );
242         BOOST_CHECK_EQUAL( i->vec()[1], 0x090Au );
243
244         ++i;
245         BOOST_CHECK( i == list.end() );
246     }
247
248     {
249         TestListParser::list2_t::container list (parser.list2());
250         BOOST_CHECK_EQUAL( list.size(), 3u );
251
252         TestListParser::list2_t::container::iterator i (list.begin());
253         BOOST_CHECK_EQUAL( i->vec().size(), 0u );
254
255         ++i;
256         BOOST_CHECK_EQUAL( i->vec().size(), 2u );
257         BOOST_CHECK_EQUAL( i->vec()[0], 0x0B0Cu );
258         BOOST_CHECK_EQUAL( i->vec()[1], 0x0D0Eu );
259
260         ++i;
261         BOOST_CHECK_EQUAL( i->vec().size(), 1u );
262         BOOST_CHECK_EQUAL( i->vec()[0], 0x0F10u );
263
264         ++i;
265         BOOST_CHECK( i == list.end() );
266     }
267
268 }
269
270 namespace {
271
272     struct TestPacketSizeList
273         : public senf::PacketParserBase
274     {
275 #       include SENF_PARSER()
276
277         SENF_PARSER_LIST ( list, packetSize(), VectorParser );
278
279         SENF_PARSER_FINALIZE(TestPacketSizeList);
280     };
281 }
282
283 SENF_AUTO_UNIT_TEST(listBytesParser_packetSize)
284 {
285     unsigned char data[] = { 0x01,                   // list()[0].vec().size()
286                              0x05, 0x06,             // list()[0].vec()[0]
287                              0x02,                   // list()[1].vec().size()
288                              0x07, 0x08,             // list()[1].vec()[0]
289                              0x09, 0x0A,             // list()[1].vec()[1]
290                              0x00,                   // list()[2].vec().size()
291                              0x02,                   // list()[3].vec().size()
292                              0x0B, 0x0C,             // list()[3].vec()[0]
293                              0x0D, 0x0E,             // list()[3].vec()[1]
294                              0x01,                   // list()[4].vec().size()
295                              0x0F, 0x10 };           // list()[4].vec()[0]
296
297     senf::DataPacket p (senf::DataPacket::create(data));
298
299     {
300         TestPacketSizeList l (p.data().begin(), &p.data());
301         BOOST_CHECK_EQUAL( l.list().size(), 5u );
302
303         TestPacketSizeList::list_t::container c (l.list());
304         TestPacketSizeList::list_t::container::iterator i (c.begin());
305
306         senf::UInt16Parser::value_type vec0[] = { 0x0506 };
307         senf::UInt16Parser::value_type vec1[] = { 0x0708, 0x090A };
308         senf::UInt16Parser::value_type vec2[] = {};
309         senf::UInt16Parser::value_type vec3[] = { 0x0B0C, 0x0D0E };
310         senf::UInt16Parser::value_type vec4[] = { 0x0F10 };
311
312         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
313                                        vec0, vec0+sizeof(vec0)/sizeof(vec0[0]) );
314         ++ i;
315         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
316                                        vec1, vec1+sizeof(vec1)/sizeof(vec1[0]) );
317         ++ i;
318         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
319                                        vec2, vec2+sizeof(vec2)/sizeof(vec2[0]) );
320         ++ i;
321         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
322                                        vec3, vec3+sizeof(vec3)/sizeof(vec3[0]) );
323
324         ++ i;
325         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
326                                        vec4, vec4+sizeof(vec4)/sizeof(vec4[0]) );
327
328         ++ i;
329         BOOST_CHECK( i == c.end() );
330
331         i = c.begin();
332         ++i;
333         TestPacketSizeList::list_t::value_type::vec_t::container v (i->vec());
334         v.push_back(0xFEFF);
335     }
336
337     {
338         TestPacketSizeList l (p.data().begin(), &p.data());
339         BOOST_CHECK_EQUAL( l.list().size(), 5u );
340         BOOST_CHECK_EQUAL( l.list().bytes(), p.data().size() );
341
342         TestPacketSizeList::list_t::container c (l.list());
343         TestPacketSizeList::list_t::container::iterator i (c.begin());
344
345         senf::UInt16Parser::value_type vec0[] = { 0x0506 };
346         senf::UInt16Parser::value_type vec1[] = { 0x0708, 0x090A, 0xFEFF };
347         senf::UInt16Parser::value_type vec2[] = {};
348         senf::UInt16Parser::value_type vec3[] = { 0x0B0C, 0x0D0E };
349         senf::UInt16Parser::value_type vec4[] = { 0x0F10 };
350
351         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
352                                        vec0, vec0+sizeof(vec0)/sizeof(vec0[0]) );
353         ++ i;
354         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
355                                        vec1, vec1+sizeof(vec1)/sizeof(vec1[0]) );
356         ++ i;
357         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
358                                        vec2, vec2+sizeof(vec2)/sizeof(vec2[0]) );
359         ++ i;
360         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
361                                        vec3, vec3+sizeof(vec3)/sizeof(vec3[0]) );
362
363         ++ i;
364         BOOST_CHECK_EQUAL_COLLECTIONS( i->vec().begin(), i->vec().end(),
365                                        vec4, vec4+sizeof(vec4)/sizeof(vec4[0]) );
366         ++ i;
367         BOOST_CHECK( i == c.end() );
368     }
369 }
370
371 SENF_AUTO_UNIT_TEST(listBytesMacro_stress)
372 {
373     TestListPacket testListPacket (TestListPacket::create());
374     for (unsigned i=0; i<12; ++i) {
375         VectorParser::value_type vec( 4, 42);
376         testListPacket->list2().push_back( vec);
377     }
378     BOOST_CHECK_EQUAL( testListPacket->list2().size(), 12u );
379
380 }
381
382 ///////////////////////////////cc.e////////////////////////////////////////
383 #undef prefix_
384
385 \f
386 // Local Variables:
387 // mode: c++
388 // fill-column: 100
389 // comment-column: 40
390 // c-file-style: "senf"
391 // indent-tabs-mode: nil
392 // ispell-local-dictionary: "american"
393 // compile-command: "scons -u test"
394 // End: