Utils: Implement Tags.hh and move 'senf::noinit' and 'senf::nothrow' there
[senf.git] / 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.test unit tests */
25
26 //#include "PacketInterpreter.test.hh"
27 //#include "PacketInterpreter.test.ih"
28
29 // Custom includes
30 #include "Packets.hh"
31
32 #include "../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         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 BOOST_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(), 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 BOOST_AUTO_UNIT_TEST(packetInterpreter)
107 {
108     {
109         BOOST_CHECK_THROW( senf::PacketInterpreter<OtherPacket>::create(4u), 
110                            senf::TruncatedPacketException );
111         senf::PacketInterpreter<OtherPacket>::ptr p
112             (senf::PacketInterpreter<OtherPacket>::create(12u));
113         
114         BOOST_CHECK_EQUAL( p->data().size(), 12u );
115         BOOST_CHECK_EQUAL( std::distance(p->data().begin(),p->data().end()), 12 );
116         BOOST_CHECK_EQUAL( p->data()[0], 0x01u );
117         
118         senf::PacketInterpreter<VoidPacket>::ptr p2
119             (p->parseNextAs<VoidPacket>());
120         BOOST_CHECK_EQUAL( p2->data().size(), 4u );
121         BOOST_CHECK_EQUAL( std::distance(p->data().begin(),p2->data().begin()), 6 );
122
123         senf::PacketInterpreter<OtherPacket>::ptr pc
124             (p->clone());
125         BOOST_CHECK_EQUAL( p->data().size(), 12u );
126         BOOST_CHECK( p->next() );
127         BOOST_CHECK( ! p->next()->next() );
128     }
129
130     {
131         BOOST_CHECK_NO_THROW( 
132             senf::PacketInterpreter<OtherPacket>::create(4u,senf::noinit));
133         senf::PacketInterpreter<OtherPacket>::ptr p
134             (senf::PacketInterpreter<OtherPacket>::create(senf::noinit));
135         BOOST_CHECK_EQUAL( p->data().size(), 0u );
136     }
137
138     {
139         senf::PacketInterpreter<VoidPacket>::byte data[] = { 0x01, 0x02, 0x03, 0x04 };
140         senf::PacketInterpreter<VoidPacket>::ptr p
141             (senf::PacketInterpreter<VoidPacket>::create(data));
142
143         BOOST_CHECK_EQUAL( p->data().size(), 4u );
144         BOOST_CHECK_EQUAL( std::distance(p->data().begin(),p->data().end()), 4 );
145         BOOST_CHECK( std::equal(p->data().begin(), p->data().end(), data) );
146     }
147
148     {
149         senf::PacketInterpreter<OtherPacket>::ptr p
150             (senf::PacketInterpreter<OtherPacket>::create(12u));
151         senf::PacketInterpreter<VoidPacket>::ptr p2
152             (senf::PacketInterpreter<VoidPacket>::createAfter(p));
153         BOOST_CHECK_EQUAL( p2->data().size(), 0u );
154         BOOST_CHECK_EQUAL( p->data().size(), 8u );
155         p2->data().insert(p2->data().begin(),0x01u);
156         BOOST_CHECK_EQUAL( p->data()[6], 0x01u );
157         BOOST_CHECK_EQUAL( p->data().size(), 9u );
158     }
159
160     {
161         senf::PacketInterpreter<OtherPacket>::ptr p
162             (senf::PacketInterpreter<OtherPacket>::create(12u));
163         senf::PacketInterpreter<OtherPacket>::ptr p2
164             (senf::PacketInterpreter<OtherPacket>::createAfter(
165                 p,senf::noinit));
166         BOOST_CHECK_EQUAL( p2->data().size(), 0u );
167         BOOST_CHECK_EQUAL( p->data().size(), 8u );
168     }
169  
170     {
171         senf::PacketInterpreter<OtherPacket>::ptr p
172             (senf::PacketInterpreter<OtherPacket>::create(12u));
173         senf::PacketInterpreter<OtherPacket>::ptr p2
174             (senf::PacketInterpreter<OtherPacket>::createAfter(p,10u));
175         BOOST_CHECK_EQUAL( p2->data().size(), 10u );
176         BOOST_CHECK_EQUAL( p->data().size(), 18u );
177         BOOST_CHECK_EQUAL( p2->data()[0], 0x01u );
178         BOOST_CHECK_THROW( senf::PacketInterpreter<OtherPacket>::createAfter(p,4u),
179                            senf::TruncatedPacketException );
180         BOOST_CHECK_NO_THROW( senf::PacketInterpreter<OtherPacket>::createAfter(
181                                   p,4u,senf::noinit) );
182     }
183
184     {
185         senf::PacketInterpreter<OtherPacket>::ptr p
186             (senf::PacketInterpreter<OtherPacket>::create(10u));
187         senf::PacketInterpreter<VoidPacket>::byte data[] = { 0x01, 0x02, 0x03, 0x04 };
188         senf::PacketInterpreter<OtherPacket>::ptr p2
189             (senf::PacketInterpreter<OtherPacket>::createAfter(p,data));
190         BOOST_CHECK_EQUAL( p2->data().size(), 4u );
191         BOOST_CHECK_EQUAL( p->data().size(), 12u );
192         BOOST_CHECK_EQUAL( p2->data()[1], 0x02u );
193         BOOST_CHECK_EQUAL( p->data()[8], 0x03u );
194     }
195
196     {
197         senf::PacketInterpreter<OtherPacket>::ptr p
198             (senf::PacketInterpreter<OtherPacket>::create(10u));
199         senf::PacketInterpreter<OtherPacket>::ptr p2
200             (senf::PacketInterpreter<OtherPacket>::createBefore(p));
201
202         BOOST_CHECK_EQUAL( p2->data().size(), 18u );
203         BOOST_CHECK_EQUAL( p->data().size(), 10u );
204
205         senf::PacketInterpreter<OtherPacket>::ptr p3
206             (senf::PacketInterpreter<OtherPacket>::createBefore(
207                 p,senf::noinit));
208         
209         BOOST_CHECK_EQUAL( p3->data().size(), 10u );
210     }
211     
212 }
213
214 // fields() ist tested in DefaultBundle/EthernetPacket.test.cc
215 // initSize() and initHeadSize() are already tested indirectly above
216
217 BOOST_AUTO_UNIT_TEST(packetInterpreter_factory)
218 {
219     senf::PacketInterpreterBase::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
220     senf::PacketInterpreterBase::factory_t factory (
221         senf::PacketInterpreter<OtherPacket>::factory());
222
223     BOOST_CHECK( ! senf::PacketInterpreterBase::no_factory() );
224     BOOST_REQUIRE( factory );
225
226     BOOST_CHECK( factory->create()->is<OtherPacket>() );
227     BOOST_CHECK_EQUAL( factory->create()->data().size(), 8u );
228     BOOST_CHECK_EQUAL( factory->create(senf::noinit)->data().size(), 0u );
229     BOOST_CHECK_EQUAL( factory->create(12u)->data().size(), 12u );
230     BOOST_CHECK_EQUAL( 
231         factory->create(4u, senf::noinit)->data().size(), 4u );
232     BOOST_CHECK_EQUAL( factory->create(data)->data().size(), 6u );
233
234     {
235         senf::PacketInterpreter<VoidPacket>::ptr p
236             (senf::PacketInterpreter<VoidPacket>::create());
237
238         BOOST_CHECK_EQUAL( p->data().size(), 0u);
239         BOOST_CHECK( factory->createAfter(p)->is<OtherPacket>() );
240         BOOST_REQUIRE( p->next() );
241         BOOST_CHECK( ! p->next()->next() );
242
243         BOOST_CHECK_EQUAL( factory->createAfter(p)->data().size(), 8u );
244         BOOST_CHECK_EQUAL( p->data().size(), 8u );
245         BOOST_CHECK( ! p->next()->next() );
246
247         BOOST_CHECK_EQUAL( 
248             factory->createAfter(p, senf::noinit)->data().size(), 0u );
249         BOOST_CHECK_EQUAL( p->data().size(), 0u );
250         BOOST_CHECK( ! p->next()->next() );
251
252         BOOST_CHECK_EQUAL( factory->createAfter(p,12u)->data().size(), 12u );
253         BOOST_CHECK_EQUAL( p->data().size(), 12u );
254         BOOST_CHECK( ! p->next()->next() );
255
256         BOOST_CHECK_EQUAL( 
257             factory->createAfter(p,4u, senf::noinit)->data().size(), 4u );
258         BOOST_CHECK_EQUAL( p->data().size(), 4u );
259         BOOST_CHECK( ! p->next()->next() );
260
261         BOOST_CHECK_EQUAL( factory->createAfter(p, data)->data().size(), 6u );
262         BOOST_CHECK_EQUAL( p->data().size(), 6u );
263         BOOST_CHECK( ! p->next()->next() );
264     }
265
266     {
267         senf::PacketInterpreter<VoidPacket>::ptr p
268             (senf::PacketInterpreter<VoidPacket>::create(4u));
269         
270         BOOST_CHECK_EQUAL( factory->createBefore(p)->data().size(), 12u );
271         BOOST_REQUIRE( p->prev() );
272         BOOST_CHECK( ! p->prev()->prev() );
273         BOOST_CHECK_EQUAL( p->prev()->data().size(), 12u );
274         
275         BOOST_CHECK_EQUAL( 
276             factory->createBefore(p,senf::noinit)->data().size(), 4u );
277         BOOST_REQUIRE( p->prev() );
278         BOOST_CHECK( ! p->prev()->prev() );
279         BOOST_CHECK_EQUAL( p->prev()->data().size(), 4u );
280     }
281
282     {
283         senf::PacketInterpreter<VoidPacket>::ptr p
284             (senf::PacketInterpreter<VoidPacket>::create(12u));
285
286         senf::PacketInterpreterBase::ptr p2 (p->parseNextAs(factory));
287         BOOST_CHECK( p2->is<OtherPacket>() );
288         BOOST_CHECK( ! p2->is<VoidPacket>() );
289         BOOST_CHECK_EQUAL( boost::size(*p2->nextPacketRange()), 4u );
290     }
291
292 }
293
294 ///////////////////////////////cc.e////////////////////////////////////////
295 #undef prefix_
296
297 \f
298 // Local Variables:
299 // mode: c++
300 // fill-column: 100
301 // c-file-style: "senf"
302 // indent-tabs-mode: nil
303 // ispell-local-dictionary: "american"
304 // compile-command: "scons -u test"
305 // comment-column: 40
306 // End: