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