73432f066423fe085fd866d6688ea5fdd53aeaad
[senf.git] / Packets / Packet.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
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 Packet.test unit tests */
25
26 //#include "Packet.test.hh"
27 //#include "Packet.test.ih"
28
29 // Custom includes
30 #include <sstream>
31 #include "Packets.hh"
32
33 #include "../Utils/auto_unit_test.hh"
34 #include <boost/test/test_tools.hpp>
35
36 #define prefix_
37 ///////////////////////////////cc.p////////////////////////////////////////
38
39 namespace {
40
41     struct RegTag {
42         typedef unsigned key_t;
43     };
44
45     struct FooPacketType 
46         : public senf::PacketTypeBase,
47           public senf::PacketTypeMixin<FooPacketType>
48     {
49         using senf::PacketTypeMixin<FooPacketType>::nextPacketRange;
50         using senf::PacketTypeMixin<FooPacketType>::initSize;
51         using senf::PacketTypeMixin<FooPacketType>::init;
52         typedef senf::PacketInterpreter<FooPacketType> interpreter;
53         static interpreter::size_type initSize()
54             { return 4u; }
55     };
56     typedef senf::ConcretePacket<FooPacketType> FooPacket;
57
58     struct BarPacketParser : public senf::PacketParserBase
59     {
60 #       include SENF_FIXED_PARSER()
61         
62         SENF_PARSER_FIELD( type,     senf::UInt16Parser );
63         SENF_PARSER_FIELD( length,   senf::Int32Parser  );
64         SENF_PARSER_FIELD( reserved, senf::UInt16Parser );
65
66         SENF_PARSER_FINALIZE(BarPacketParser);
67     };
68
69     struct BarPacketType 
70         : public senf::PacketTypeBase,
71           public senf::PacketTypeMixin<BarPacketType,RegTag>
72     {
73         typedef senf::PacketTypeMixin<BarPacketType,RegTag> mixin;
74         typedef senf::ConcretePacket<BarPacketType> packet;
75         typedef BarPacketParser parser;
76         using mixin::nextPacketRange;
77         using mixin::nextPacketType;
78         using mixin::initSize;
79         using mixin::init;
80         static size_type initSize() 
81             { return 8u; }
82         static void init(packet p) {
83             p->reserved() = 0xA0A0u;
84         }
85         static void dump(packet p, std::ostream & os) {
86             os << "BarPacket:\n"
87                << "type: " << p->type() << "\n"
88                << "length: " << p->length() << "\n";
89         }
90         static void finalize(packet p) {
91             if (p.next())
92                 p->type() = senf::PacketRegistry<RegTag>::key(p.next());
93             else
94                 p->type() = -1;
95         }
96         static registry_key_t nextPacketKey(packet p) {
97             return p->type();
98         }
99     };
100     typedef BarPacketType::packet BarPacket;
101
102     namespace reg {
103         senf::PacketRegistry<RegTag>::RegistrationProxy<FooPacket> registerFoo(1u);
104         senf::PacketRegistry<RegTag>::RegistrationProxy<BarPacket> registerBar(2u);
105     }
106
107 }
108
109 BOOST_AUTO_UNIT_TEST(packet)
110 {
111     senf::Packet packet (FooPacket::create());
112     BarPacket::createAfter(packet);
113
114     BOOST_REQUIRE( packet );
115     BOOST_CHECK( packet.next() );
116     BOOST_CHECK( ! packet.next().next() );
117     BOOST_CHECK( ! packet.prev() );
118     BOOST_CHECK( packet.next().prev() == packet );
119     BOOST_CHECK( packet.next() != packet );
120     BOOST_CHECK_EQUAL( packet.size(), 12u );
121     BOOST_CHECK_EQUAL( packet.next().size(), 8u );
122     BOOST_CHECK( packet.is<FooPacket>() );
123     BOOST_CHECK( packet.next().is<BarPacket>() );
124     BOOST_CHECK( packet.first() == packet );
125     BOOST_CHECK( packet.last() == packet.next() );
126     
127     senf::Packet p2 (packet.next());
128     BOOST_CHECK( p2 );
129     packet.parseNextAs<FooPacket>();
130     BOOST_CHECK_EQUAL( packet.size(), 12u );
131     BOOST_CHECK_EQUAL( packet.next().size(), 8u );
132     BOOST_CHECK( packet.next().is<FooPacket>() );
133     BOOST_CHECK( ! p2 );
134     BOOST_CHECK( packet.next().as<FooPacket>() );
135     
136     p2 = packet.next().clone();
137     BOOST_REQUIRE( p2 );
138     packet.next().append( p2 );
139     BOOST_REQUIRE( packet.next().next() );
140     BOOST_CHECK( packet.next().next().next() );
141     BOOST_CHECK( packet.next().next().next().is<senf::DataPacket>() );
142     BOOST_CHECK_EQUAL( packet.size(), 16u );
143
144     // This calls and checks typeId()
145     BOOST_CHECK_EQUAL( senf::PacketRegistry<RegTag>::key(packet), 1u );
146     packet.next().parseNextAs( senf::PacketRegistry<RegTag>::lookup(2u).factory() );
147     BOOST_CHECK( packet.next().next().is<BarPacket>() );
148     
149     std::stringstream s;
150     packet.dump(s);
151     BOOST_CHECK_EQUAL( s.str(), "BarPacket:\ntype: 0\nlength: 0\n" );
152     
153     packet.finalize();
154     BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(), 
155                        BarPacket::type::parser::type_t::value_type(-1) );
156     packet.last().append(FooPacket::create());
157     packet.finalize();
158     BOOST_CHECK_EQUAL( packet.next<BarPacket>()->type(), 1u );
159
160     BOOST_CHECK( packet.factory() == FooPacket::factory() );
161
162     senf::PacketData::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163                                       0x81, 0x82, 0x83 };
164
165     BarPacket::createAfter(packet,data);
166     BOOST_REQUIRE( packet.next() );
167     BOOST_REQUIRE( packet.next().is<BarPacket>() );
168     BOOST_CHECK( packet.last().is<FooPacket>() );
169     BOOST_CHECK_EQUAL( packet.last<BarPacket>()->type(), 1u );
170     BOOST_CHECK_EQUAL( packet.next().size(), 11u );
171     BOOST_REQUIRE( packet.next().next() );
172     BOOST_CHECK( packet.next().next().is<FooPacket>() );
173     BOOST_CHECK( ! packet.next().next().next() );
174     BOOST_CHECK_EQUAL( packet.next().next().data()[0], 0x81u );
175
176     BOOST_CHECK( packet.first<FooPacket>() == packet );
177     BOOST_CHECK( packet.first<FooPacket>(senf::nothrow) == packet );
178     BOOST_CHECK( packet.last<BarPacket>() == packet.last().prev() );
179     BOOST_CHECK( packet.last<BarPacket>(senf::nothrow) == packet.last().prev() );
180     BOOST_CHECK( packet.findNext<FooPacket>() == packet );
181     BOOST_CHECK( packet.findNext<FooPacket>(senf::nothrow) == packet );
182     BOOST_CHECK( packet.last().findPrev<FooPacket>() == packet.last() );
183     BOOST_CHECK( packet.last().findPrev<FooPacket>(senf::nothrow) == packet.last() );
184     BOOST_CHECK( packet.next<BarPacket>() == packet.next() );
185     BOOST_CHECK( packet.next<BarPacket>(senf::nothrow) == packet.next() );
186     BOOST_CHECK( packet.last().prev<FooPacket>() == packet );
187     BOOST_CHECK( packet.last().prev<FooPacket>(senf::nothrow) == packet );
188 }
189
190 BOOST_AUTO_UNIT_TEST(concretePacket)
191 {
192     senf::PacketData::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
193
194     BOOST_CHECK_EQUAL( FooPacket::create().size(), 4u );
195     BOOST_CHECK_EQUAL( FooPacket::create(FooPacket::noinit).size(), 0u );
196     BOOST_CHECK_THROW( FooPacket::create(2u), senf::TruncatedPacketException );
197     BOOST_CHECK_EQUAL( FooPacket::create(10u).size(), 10u );
198     BOOST_CHECK_EQUAL( FooPacket::create(2u,FooPacket::noinit).size(), 2u );
199     BOOST_CHECK_EQUAL( FooPacket::create(data).size(), 6u );
200
201     senf::Packet packet (FooPacket::create());
202
203     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet).size(), 4u );
204     BOOST_CHECK_EQUAL( packet.size(), 8u );
205
206     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,FooPacket::noinit).size(), 0u );
207     BOOST_CHECK_EQUAL( packet.size(), 4u );
208
209     BOOST_CHECK_THROW( FooPacket::createAfter(packet,2u), senf::TruncatedPacketException );
210     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,10u).size(), 10u );
211     BOOST_CHECK_EQUAL( packet.size(), 14u );
212     
213     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,2u,FooPacket::noinit).size(), 2u );
214     BOOST_CHECK_EQUAL( packet.size(), 6u );
215     
216     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,data).size(), 6u );
217     BOOST_CHECK_EQUAL( packet.size(), 10u );
218     
219     BOOST_CHECK_EQUAL( FooPacket::createBefore(packet).size(), 14u );
220     BOOST_CHECK_EQUAL( packet.size(), 10u );
221
222     BOOST_CHECK_EQUAL( FooPacket::createBefore(packet,FooPacket::noinit).size(), 10u );
223     BOOST_CHECK_EQUAL( packet.size(), 10u );
224
225     BOOST_CHECK( packet.clone() != packet );
226     BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
227 }
228
229 ///////////////////////////////cc.e////////////////////////////////////////
230 #undef prefix_
231
232 \f
233 // Local Variables:
234 // mode: c++
235 // fill-column: 100
236 // c-file-style: "senf"
237 // indent-tabs-mode: nil
238 // ispell-local-dictionary: "american"
239 // compile-command: "scons -u test"
240 // comment-column: 40
241 // End: