Packets: Add parse helper SENF_PARSER_SKIP_BITS
[senf.git] / Packets / Packet.test.cc
1 // Copyright (C) 2007 
2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 //     Stefan Bund <g0dil@berlios.de>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 /** \file
22     \brief Packet.test unit tests */
23
24 //#include "Packet.test.hh"
25 //#include "Packet.test.ih"
26
27 // Custom includes
28 #include <sstream>
29 #include "Packets.hh"
30
31 #include <boost/test/auto_unit_test.hpp>
32 #include <boost/test/test_tools.hpp>
33
34 #define prefix_
35 ///////////////////////////////cc.p////////////////////////////////////////
36
37 namespace {
38
39     struct RegTag {
40         typedef unsigned key_t;
41     };
42
43     struct FooPacketType 
44         : public senf::PacketTypeBase,
45           public senf::PacketTypeMixin<FooPacketType>
46     {
47         using senf::PacketTypeMixin<FooPacketType>::nextPacketRange;
48         using senf::PacketTypeMixin<FooPacketType>::initSize;
49         using senf::PacketTypeMixin<FooPacketType>::init;
50         typedef senf::PacketInterpreter<FooPacketType> interpreter;
51         static interpreter::size_type initSize()
52             { return 4u; }
53     };
54     typedef senf::ConcretePacket<FooPacketType> FooPacket;
55
56     struct BarPacketParser : public senf::PacketParserBase
57     {
58 #       include SENF_FIXED_PARSER()
59         
60         SENF_PARSER_FIELD( type,     senf::Parse_UInt16 );
61         SENF_PARSER_FIELD( length,   senf::Parse_Int32  );
62         SENF_PARSER_FIELD( reserved, senf::Parse_UInt16 );
63
64         SENF_PARSER_FINALIZE(BarPacketParser);
65     };
66
67     struct BarPacketType 
68         : public senf::PacketTypeBase,
69           public senf::PacketTypeMixin<BarPacketType,RegTag>
70     {
71         typedef senf::PacketTypeMixin<BarPacketType,RegTag> mixin;
72         typedef senf::ConcretePacket<BarPacketType> packet;
73         typedef BarPacketParser parser;
74         using mixin::nextPacketRange;
75         using mixin::nextPacketType;
76         using mixin::initSize;
77         using mixin::init;
78         static size_type initSize() 
79             { return 8u; }
80         static void init(packet p) {
81             p->reserved() = 0xA0A0u;
82         }
83         static void dump(packet p, std::ostream & os) {
84             os << "BarPacket:\n"
85                << "type: " << p->type() << "\n"
86                << "length: " << p->length() << "\n";
87         }
88         static void finalize(packet p) {
89             if (p.next())
90                 p->type() = senf::PacketRegistry<RegTag>::key(p.next());
91             else
92                 p->type() = -1;
93         }
94         static registry_key_t nextPacketKey(packet p) {
95             return p->type();
96         }
97     };
98     typedef BarPacketType::packet BarPacket;
99
100     namespace reg {
101         senf::PacketRegistry<RegTag>::RegistrationProxy<FooPacket> registerFoo(1u);
102         senf::PacketRegistry<RegTag>::RegistrationProxy<BarPacket> registerBar(2u);
103     }
104
105 }
106
107 BOOST_AUTO_UNIT_TEST(packet)
108 {
109     senf::Packet packet (FooPacket::create());
110     BarPacket::createAfter(packet);
111
112     BOOST_REQUIRE( packet );
113     BOOST_CHECK( packet.next() );
114     BOOST_CHECK( ! packet.next().next() );
115     BOOST_CHECK( ! packet.prev() );
116     BOOST_CHECK( packet.next().prev() == packet );
117     BOOST_CHECK( packet.next() != packet );
118     BOOST_CHECK_EQUAL( packet.size(), 12u );
119     BOOST_CHECK_EQUAL( packet.next().size(), 8u );
120     BOOST_CHECK( packet.is<FooPacket>() );
121     BOOST_CHECK( packet.next().is<BarPacket>() );
122     BOOST_CHECK( packet.first() == packet );
123     BOOST_CHECK( packet.last() == packet.next() );
124     
125     senf::Packet p2 (packet.next());
126     BOOST_CHECK( p2 );
127     packet.parseNextAs<FooPacket>();
128     BOOST_CHECK_EQUAL( packet.size(), 12u );
129     BOOST_CHECK_EQUAL( packet.next().size(), 8u );
130     BOOST_CHECK( packet.next().is<FooPacket>() );
131     BOOST_CHECK( ! p2 );
132     BOOST_CHECK( packet.next().as<FooPacket>() );
133     
134     p2 = packet.next().clone();
135     BOOST_REQUIRE( p2 );
136     packet.next().append( p2 );
137     BOOST_REQUIRE( packet.next().next() );
138     BOOST_CHECK( packet.next().next().next() );
139     BOOST_CHECK( packet.next().next().next().is<senf::DataPacket>() );
140     BOOST_CHECK_EQUAL( packet.size(), 16u );
141
142     // This calls and checks typeId()
143     BOOST_CHECK_EQUAL( senf::PacketRegistry<RegTag>::key(packet), 1u );
144     packet.next().parseNextAs( senf::PacketRegistry<RegTag>::lookup(2u).factory() );
145     BOOST_CHECK( packet.next().next().is<BarPacket>() );
146     
147     std::stringstream s;
148     packet.dump(s);
149     BOOST_CHECK_EQUAL( s.str(), "BarPacket:\ntype: 0\nlength: 0\n" );
150     
151     packet.finalize();
152     BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(), 
153                        BarPacket::type::parser::type_t::value_type(-1) );
154     packet.last().append(FooPacket::create());
155     packet.finalize();
156     BOOST_CHECK_EQUAL( packet.next<BarPacket>()->type(), 1u );
157
158     BOOST_CHECK( packet.factory() == FooPacket::factory() );
159
160     senf::PacketData::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161                                       0x81, 0x82, 0x83 };
162
163     BarPacket::createAfter(packet,data);
164     BOOST_REQUIRE( packet.next() );
165     BOOST_REQUIRE( packet.next().is<BarPacket>() );
166     BOOST_CHECK( packet.last().is<FooPacket>() );
167     BOOST_CHECK_EQUAL( packet.last<BarPacket>()->type(), 1u );
168     BOOST_CHECK_EQUAL( packet.next().size(), 11u );
169     BOOST_REQUIRE( packet.next().next() );
170     BOOST_CHECK( packet.next().next().is<FooPacket>() );
171     BOOST_CHECK( ! packet.next().next().next() );
172     BOOST_CHECK_EQUAL( packet.next().next().data()[0], 0x81u );
173
174     BOOST_CHECK( packet.first<FooPacket>() == packet );
175     BOOST_CHECK( packet.first<FooPacket>(senf::nothrow) == packet );
176     BOOST_CHECK( packet.last<BarPacket>() == packet.last().prev() );
177     BOOST_CHECK( packet.last<BarPacket>(senf::nothrow) == packet.last().prev() );
178     BOOST_CHECK( packet.findNext<FooPacket>() == packet );
179     BOOST_CHECK( packet.findNext<FooPacket>(senf::nothrow) == packet );
180     BOOST_CHECK( packet.last().findPrev<FooPacket>() == packet.last() );
181     BOOST_CHECK( packet.last().findPrev<FooPacket>(senf::nothrow) == packet.last() );
182     BOOST_CHECK( packet.next<BarPacket>() == packet.next() );
183     BOOST_CHECK( packet.next<BarPacket>(senf::nothrow) == packet.next() );
184     BOOST_CHECK( packet.last().prev<FooPacket>() == packet );
185     BOOST_CHECK( packet.last().prev<FooPacket>(senf::nothrow) == packet );
186 }
187
188 BOOST_AUTO_UNIT_TEST(concretePacket)
189 {
190     senf::PacketData::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
191
192     BOOST_CHECK_EQUAL( FooPacket::create().size(), 4u );
193     BOOST_CHECK_EQUAL( FooPacket::create(FooPacket::noinit).size(), 0u );
194     BOOST_CHECK_THROW( FooPacket::create(2u), senf::TruncatedPacketException );
195     BOOST_CHECK_EQUAL( FooPacket::create(10u).size(), 10u );
196     BOOST_CHECK_EQUAL( FooPacket::create(2u,FooPacket::noinit).size(), 2u );
197     BOOST_CHECK_EQUAL( FooPacket::create(data).size(), 6u );
198
199     senf::Packet packet (FooPacket::create());
200
201     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet).size(), 4u );
202     BOOST_CHECK_EQUAL( packet.size(), 8u );
203
204     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,FooPacket::noinit).size(), 0u );
205     BOOST_CHECK_EQUAL( packet.size(), 4u );
206
207     BOOST_CHECK_THROW( FooPacket::createAfter(packet,2u), senf::TruncatedPacketException );
208     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,10u).size(), 10u );
209     BOOST_CHECK_EQUAL( packet.size(), 14u );
210     
211     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,2u,FooPacket::noinit).size(), 2u );
212     BOOST_CHECK_EQUAL( packet.size(), 6u );
213     
214     BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,data).size(), 6u );
215     BOOST_CHECK_EQUAL( packet.size(), 10u );
216     
217     BOOST_CHECK_EQUAL( FooPacket::createBefore(packet).size(), 14u );
218     BOOST_CHECK_EQUAL( packet.size(), 10u );
219
220     BOOST_CHECK_EQUAL( FooPacket::createBefore(packet,FooPacket::noinit).size(), 10u );
221     BOOST_CHECK_EQUAL( packet.size(), 10u );
222
223     BOOST_CHECK( packet.clone() != packet );
224     BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
225 }
226
227 ///////////////////////////////cc.e////////////////////////////////////////
228 #undef prefix_
229
230 \f
231 // Local Variables:
232 // mode: c++
233 // fill-column: 100
234 // c-file-style: "senf"
235 // indent-tabs-mode: nil
236 // ispell-local-dictionary: "american"
237 // compile-command: "scons -u test"
238 // comment-column: 40
239 // End: