ae9a344c7d9431bb861f1ba26e658f50d4da09c2
[senf.git] / senf / Packets / PacketInterpreter.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 PacketInterpreter unit tests */
25
26 //#include "PacketInterpreter.test.hh"
27 //#include "PacketInterpreter.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 //-/////////////////////////////////////////////////////////////////////////////////////////////////
37
38 namespace {
39     struct VoidPacket : public senf::PacketTypeBase {
40         typedef senf::ConcretePacket<VoidPacket> packet;
41         static optional_range nextPacketRange(packet p)
42             { return range(p.data().begin(), p.data().end()); }
43     };
44 }
45
46 SENF_AUTO_UNIT_TEST(packetInterpreterBase)
47 {
48     {
49         senf::PacketInterpreter<VoidPacket>::ptr pi2 (senf::PacketInterpreter<VoidPacket>::create());
50         senf::PacketInterpreter<VoidPacket>::ptr pi1 (senf::PacketInterpreter<VoidPacket>::createBefore(pi2));
51
52         pi2->data().insert(pi2->data().begin(),0x02);
53         BOOST_CHECK_EQUAL( pi1->data().size(), 1u );
54         BOOST_CHECK_EQUAL( pi2->data().size(), 1u );
55
56         senf::PacketInterpreter<VoidPacket>::ptr pi3 (pi2->parseNextAs<VoidPacket>());
57         BOOST_REQUIRE( pi3 );
58         BOOST_CHECK( pi2 == pi1->next() );
59         BOOST_CHECK( pi3 == pi2->next() );
60         BOOST_CHECK( ! pi3->next() );
61         BOOST_CHECK( pi2 == pi3->prev() );
62         BOOST_CHECK( pi1 == pi2->prev() );
63         BOOST_CHECK( ! pi1->prev() );
64         BOOST_CHECK( pi2->is<VoidPacket>() );
65         BOOST_CHECK( pi2->as<VoidPacket>() == pi2 );
66         BOOST_CHECK( pi2->parseNextAs(senf::PacketInterpreter<VoidPacket>::factory()) );
67         BOOST_CHECK( pi2->typeId() == pi1->typeId() );
68
69         pi1->data().insert(pi1->data().begin(),2,0x01u);
70         BOOST_CHECK_EQUAL( pi1->data().size(), 3u );
71         BOOST_CHECK_EQUAL( pi2->data().size(), 1u );
72         BOOST_CHECK_EQUAL( pi3->data().size(), 1u );
73
74         senf::PacketInterpreter<VoidPacket>::ptr pi2b (pi2->clone());
75         BOOST_REQUIRE( pi2b->next() );
76         BOOST_CHECK( ! pi2b->next()->next() );
77         BOOST_CHECK( ! pi2b->prev() );
78
79         pi2b->data().insert(pi2b->data().begin(),0x03u);
80         BOOST_CHECK_EQUAL( pi2->data().size(), 1u );
81         BOOST_CHECK_EQUAL( pi2b->data().size(), 2u );
82
83         BOOST_CHECK_EQUAL( pi1->data().size(), unsigned(pi1->nextPacketRange()->size()) );
84         pi1->append(pi2b);
85         BOOST_CHECK_EQUAL( pi1->data().size(), 2u );
86         BOOST_REQUIRE( pi1->next() );
87         BOOST_REQUIRE( pi1->next()->next() );
88         BOOST_CHECK( ! pi1->next()->next()->next() );
89     }
90
91 }
92
93 namespace {
94     struct OtherPacket
95         : public senf::PacketTypeBase,
96           public senf::PacketTypeMixin<OtherPacket>
97     {
98         using senf::PacketTypeMixin<OtherPacket>::nextPacketRange;
99         typedef senf::ConcretePacket<OtherPacket> packet;
100         static size_type initSize()     { return 8u; }
101         static size_type initHeadSize() { return 6u; }
102         static void init(packet p)            { p.data()[0] = 0x01u; }
103     };
104 }
105
106 SENF_AUTO_UNIT_TEST(packetInterpreter)
107 {
108     typedef senf::PacketInterpreterBase::size_type size_type;
109     {
110         BOOST_CHECK_THROW( senf::PacketInterpreter<OtherPacket>::create(size_type(4u)),
111                            senf::TruncatedPacketException );
112         senf::PacketInterpreter<OtherPacket>::ptr p
113             (senf::PacketInterpreter<OtherPacket>::create(size_type(12u)));
114
115         BOOST_CHECK_EQUAL( p->data().size(), 12u );
116         BOOST_CHECK_EQUAL( std::distance(p->data().begin(),p->data().end()), 12 );
117         BOOST_CHECK_EQUAL( p->data()[0], 0x01u );
118
119         senf::PacketInterpreter<VoidPacket>::ptr p2
120             (p->parseNextAs<VoidPacket>());
121         BOOST_CHECK_EQUAL( p2->data().size(), 4u );
122         BOOST_CHECK_EQUAL( std::distance(p->data().begin(),p2->data().begin()), 6 );
123
124         senf::PacketInterpreter<OtherPacket>::ptr pc
125             (p->clone());
126         BOOST_CHECK_EQUAL( p->data().size(), 12u );
127         BOOST_CHECK( p->next() );
128         BOOST_CHECK( ! p->next()->next() );
129     }
130
131     {
132         SENF_CHECK_NO_THROW(
133             senf::PacketInterpreter<OtherPacket>::create(4u,senf::noinit));
134         senf::PacketInterpreter<OtherPacket>::ptr p
135             (senf::PacketInterpreter<OtherPacket>::create(senf::noinit));
136         BOOST_CHECK_EQUAL( p->data().size(), 0u );
137     }
138
139     {
140         senf::PacketInterpreter<VoidPacket>::byte data[] = { 0x01, 0x02, 0x03, 0x04 };
141         senf::PacketInterpreter<VoidPacket>::ptr p
142             (senf::PacketInterpreter<VoidPacket>::create(data));
143
144         BOOST_CHECK_EQUAL( p->data().size(), 4u );
145         BOOST_CHECK_EQUAL( std::distance(p->data().begin(),p->data().end()), 4 );
146         BOOST_CHECK( std::equal(p->data().begin(), p->data().end(), data) );
147     }
148
149     {
150         senf::PacketInterpreter<OtherPacket>::ptr p
151             (senf::PacketInterpreter<OtherPacket>::create(size_type(12u)));
152         senf::PacketInterpreter<VoidPacket>::ptr p2
153             (senf::PacketInterpreter<VoidPacket>::createAfter(p));
154         BOOST_CHECK_EQUAL( p2->data().size(), 0u );
155         BOOST_CHECK_EQUAL( p->data().size(), 8u );
156         p2->data().insert(p2->data().begin(),0x01u);
157         BOOST_CHECK_EQUAL( p->data()[6], 0x01u );
158         BOOST_CHECK_EQUAL( p->data().size(), 9u );
159     }
160
161     {
162         senf::PacketInterpreter<OtherPacket>::ptr p
163             (senf::PacketInterpreter<OtherPacket>::create(size_type(12u)));
164         senf::PacketInterpreter<OtherPacket>::ptr p2
165             (senf::PacketInterpreter<OtherPacket>::createAfter(
166                 p,senf::noinit));
167         BOOST_CHECK_EQUAL( p2->data().size(), 0u );
168         BOOST_CHECK_EQUAL( p->data().size(), 8u );
169     }
170
171     {
172         senf::PacketInterpreter<OtherPacket>::ptr p
173             (senf::PacketInterpreter<OtherPacket>::create(size_type(12u)));
174         senf::PacketInterpreter<OtherPacket>::ptr p2
175             (senf::PacketInterpreter<OtherPacket>::createAfter(p, size_type(10u)));
176         BOOST_CHECK_EQUAL( p2->data().size(), 10u );
177         BOOST_CHECK_EQUAL( p->data().size(), 18u );
178         BOOST_CHECK_EQUAL( p2->data()[0], 0x01u );
179         BOOST_CHECK_THROW( senf::PacketInterpreter<OtherPacket>::createAfter(p, size_type(4u)),
180                            senf::TruncatedPacketException );
181         SENF_CHECK_NO_THROW( senf::PacketInterpreter<OtherPacket>::createAfter(
182                                   p,4u,senf::noinit) );
183     }
184
185     {
186         senf::PacketInterpreter<OtherPacket>::ptr p
187             (senf::PacketInterpreter<OtherPacket>::create(size_type(10u)));
188         senf::PacketInterpreter<VoidPacket>::byte data[] = { 0x01, 0x02, 0x03, 0x04 };
189         senf::PacketInterpreter<OtherPacket>::ptr p2
190             (senf::PacketInterpreter<OtherPacket>::createAfter(p,data));
191         BOOST_CHECK_EQUAL( p2->data().size(), 4u );
192         BOOST_CHECK_EQUAL( p->data().size(), 12u );
193         BOOST_CHECK_EQUAL( p2->data()[1], 0x02u );
194         BOOST_CHECK_EQUAL( p->data()[8], 0x03u );
195     }
196
197     {
198         senf::PacketInterpreter<OtherPacket>::ptr p
199             (senf::PacketInterpreter<OtherPacket>::create(size_type(10u)));
200         senf::PacketInterpreter<OtherPacket>::ptr p2
201             (senf::PacketInterpreter<OtherPacket>::createBefore(p));
202
203         BOOST_CHECK_EQUAL( p2->data().size(), 18u );
204         BOOST_CHECK_EQUAL( p->data().size(), 10u );
205
206         senf::PacketInterpreter<OtherPacket>::ptr p3
207             (senf::PacketInterpreter<OtherPacket>::createBefore(
208                 p,senf::noinit));
209
210         BOOST_CHECK_EQUAL( p3->data().size(), 10u );
211
212         senf::PacketInterpreter<OtherPacket>::ptr p4
213             (senf::PacketInterpreter<OtherPacket>::createInsertBefore(p));
214
215         BOOST_CHECK_EQUAL( p->data().size(), 10u );
216         BOOST_CHECK_EQUAL( p4->data().size(), 18u );
217         BOOST_CHECK_EQUAL( p3->data().size(), 18u );
218     }
219
220 }
221
222 // fields() is tested in DefaultBundle/EthernetPacket.test.cc
223 // initSize() and initHeadSize() are already tested indirectly above
224
225 SENF_AUTO_UNIT_TEST(packetInterpreter_factory)
226 {
227     typedef senf::PacketInterpreterBase::size_type size_type;
228
229     senf::PacketInterpreterBase::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
230     senf::PacketInterpreterBase::factory_t factory (
231         senf::PacketInterpreter<OtherPacket>::factory());
232
233     BOOST_CHECK( ! senf::PacketInterpreterBase::no_factory() );
234     BOOST_REQUIRE( factory );
235
236     BOOST_CHECK( factory->create()->is<OtherPacket>() );
237     BOOST_CHECK_EQUAL( factory->create()->data().size(), 8u );
238     BOOST_CHECK_EQUAL( factory->create(senf::noinit)->data().size(), 0u );
239     BOOST_CHECK_EQUAL( factory->create(size_type(12u))->data().size(), 12u );
240     BOOST_CHECK_EQUAL(
241         factory->create(4u, senf::noinit)->data().size(), 4u );
242     BOOST_CHECK_EQUAL( factory->create(data)->data().size(), 6u );
243
244     {
245         senf::PacketInterpreter<VoidPacket>::ptr p
246             (senf::PacketInterpreter<VoidPacket>::create());
247
248         BOOST_CHECK_EQUAL( p->data().size(), 0u);
249         BOOST_CHECK( factory->createAfter(p)->is<OtherPacket>() );
250         BOOST_REQUIRE( p->next() );
251         BOOST_CHECK( ! p->next()->next() );
252
253         BOOST_CHECK_EQUAL( factory->createAfter(p)->data().size(), 8u );
254         BOOST_CHECK_EQUAL( p->data().size(), 8u );
255         BOOST_CHECK( ! p->next()->next() );
256
257         BOOST_CHECK_EQUAL(
258             factory->createAfter(p, senf::noinit)->data().size(), 0u );
259         BOOST_CHECK_EQUAL( p->data().size(), 0u );
260         BOOST_CHECK( ! p->next()->next() );
261
262         BOOST_CHECK_EQUAL( factory->createAfter(p, size_type(12u))->data().size(), 12u );
263         BOOST_CHECK_EQUAL( p->data().size(), 12u );
264         BOOST_CHECK( ! p->next()->next() );
265
266         BOOST_CHECK_EQUAL(
267             factory->createAfter(p,4u, senf::noinit)->data().size(), 4u );
268         BOOST_CHECK_EQUAL( p->data().size(), 4u );
269         BOOST_CHECK( ! p->next()->next() );
270
271         BOOST_CHECK_EQUAL( factory->createAfter(p, data)->data().size(), 6u );
272         BOOST_CHECK_EQUAL( p->data().size(), 6u );
273         BOOST_CHECK( ! p->next()->next() );
274     }
275
276     {
277         senf::PacketInterpreter<VoidPacket>::ptr p
278             (senf::PacketInterpreter<VoidPacket>::create(size_type(4u)));
279
280         BOOST_CHECK_EQUAL( factory->createBefore(p)->data().size(), 12u );
281         BOOST_REQUIRE( p->prev() );
282         BOOST_CHECK( ! p->prev()->prev() );
283         BOOST_CHECK_EQUAL( p->prev()->data().size(), 12u );
284
285         BOOST_CHECK_EQUAL( factory->createBefore(p,senf::noinit)->data().size(), 4u );
286         BOOST_REQUIRE( p->prev() );
287         BOOST_CHECK( ! p->prev()->prev() );
288         BOOST_CHECK_EQUAL( p->prev()->data().size(), 4u );
289
290         BOOST_CHECK_EQUAL( factory->createInsertBefore(p,senf::noinit)->data().size(), 4u );
291         BOOST_REQUIRE( p->prev() );
292         BOOST_REQUIRE( p->prev()->prev() );
293         BOOST_CHECK( ! p->prev()->prev()->prev() );
294     }
295
296     {
297         senf::PacketInterpreter<VoidPacket>::ptr p
298             (senf::PacketInterpreter<VoidPacket>::create(size_type(12u)));
299
300         senf::PacketInterpreterBase::ptr p2 (p->parseNextAs(factory));
301         BOOST_CHECK( p2->is<OtherPacket>() );
302         BOOST_CHECK( ! p2->is<VoidPacket>() );
303         BOOST_CHECK_EQUAL( unsigned(boost::size(*p2->nextPacketRange())), 4u );
304     }
305
306 }
307
308 //-/////////////////////////////////////////////////////////////////////////////////////////////////
309 #undef prefix_
310
311 \f
312 // Local Variables:
313 // mode: c++
314 // fill-column: 100
315 // c-file-style: "senf"
316 // indent-tabs-mode: nil
317 // ispell-local-dictionary: "american"
318 // compile-command: "scons -u test"
319 // comment-column: 40
320 // End: