4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief Packet unit tests */
26 //#include "Packet.test.hh"
27 //#include "Packet.test.ih"
31 #include <boost/static_assert.hpp>
32 #include <boost/cstdint.hpp>
35 #include <senf/Utils/auto_unit_test.hh>
36 #include <boost/test/test_tools.hpp>
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
44 typedef unsigned key_t;
48 : public senf::PacketTypeBase,
49 public senf::PacketTypeMixin<FooPacketType>
51 using senf::PacketTypeMixin<FooPacketType>::nextPacketRange;
52 using senf::PacketTypeMixin<FooPacketType>::initSize;
53 using senf::PacketTypeMixin<FooPacketType>::init;
54 static size_type initSize()
57 // We need to implement initHeadSize() to force the mixin to switch into 'fixed-size'
58 // mode. Otherwise, mixin::nextPacketRange() would query the parser for it's size to find
59 // the header size. Since the parser is VoidPacketParser, the header size would therefore be
61 static size_type initHeadSize()
62 { return initSize(); }
64 typedef senf::ConcretePacket<FooPacketType> FooPacket;
66 struct BarPacketParser : public senf::PacketParserBase
68 # include SENF_FIXED_PARSER()
70 SENF_PARSER_FIELD( type, senf::UInt16Parser );
71 SENF_PARSER_FIELD( length, senf::Int32Parser );
72 SENF_PARSER_FIELD( reserved, senf::UInt16Parser );
75 reserved() << 0xA0A0u;
78 SENF_PARSER_FINALIZE(BarPacketParser);
82 : public senf::PacketTypeBase,
83 public senf::PacketTypeMixin<BarPacketType,RegTag>
85 typedef senf::PacketTypeMixin<BarPacketType,RegTag> mixin;
86 typedef senf::ConcretePacket<BarPacketType> packet;
87 typedef BarPacketParser parser;
88 using mixin::nextPacketRange;
89 using mixin::nextPacketType;
90 using mixin::initSize;
92 static void dump(packet p, std::ostream & os) {
94 << senf::fieldName("type") << p->type() << "\n"
95 << senf::fieldName("length") << p->length() << "\n";
97 static void finalize(packet p) {
98 if (p.next(senf::nothrow))
99 p->type() = senf::PacketRegistry<RegTag>::key(p.next());
103 static key_t nextPacketKey(packet p) {
107 typedef BarPacketType::packet BarPacket;
110 senf::PacketRegistry<RegTag>::ScopedRegistrationProxy<FooPacket> registerFoo(1u);
111 senf::PacketRegistry<RegTag>::ScopedRegistrationProxy<BarPacket> registerBar(2u);
114 struct IntAnnotation {
115 boost::uint32_t value;
118 std::ostream & operator<<(std::ostream & os, IntAnnotation const & v)
119 { os << v.value; return os; }
121 struct LargeAnnotation {
125 std::ostream & operator<<(std::ostream & os, LargeAnnotation const & v)
126 { os << v.value; return os; }
128 struct ComplexAnnotation : senf::ComplexAnnotation
130 ComplexAnnotation() : s("empty"), i(-1) {}
133 // padding so the size does not depend on the platform ...
134 struct _ {std::string s;boost::int32_t i;};
135 char __ [32-sizeof(_)];
138 std::ostream & operator<<(std::ostream & os, ComplexAnnotation const & v)
139 { os << "('" << v.s << "' " << v.i << ')'; return os; }
141 struct ComplexEmptyAnnotation : senf::ComplexAnnotation
144 std::ostream & operator<<(std::ostream & os, ComplexEmptyAnnotation const & v)
145 { os << "(empty)"; return os; }
147 struct InvalidAnnotation
152 std::ostream & operator<<(std::ostream & os, InvalidAnnotation const & v)
153 { os << v.value; return os; }
157 SENF_AUTO_UNIT_TEST(packet)
159 BOOST_CHECK(! senf::Packet().is<BarPacket>() );
160 senf::Packet packet (FooPacket::create());
161 BarPacket::createAfter(packet);
163 BOOST_CHECK_THROW( senf::Packet().as<BarPacket>(), senf::WrapException<std::bad_cast> );
164 BOOST_CHECK_THROW( packet.as<BarPacket>(), senf::WrapException<std::bad_cast> );
166 BOOST_REQUIRE( packet );
167 BOOST_CHECK( packet.next() );
168 BOOST_CHECK( ! packet.next().next(senf::nothrow) );
169 BOOST_CHECK( ! packet.next().next(senf::nothrow).is<BarPacket>() );
170 BOOST_CHECK( ! packet.prev(senf::nothrow) );
171 BOOST_CHECK( packet.next().prev() == packet );
172 SENF_CHECK_NOT_EQUAL( packet.next(), packet );
173 BOOST_CHECK_EQUAL( std::distance(packet.data().begin(), packet.next().data().begin()), 4 );
174 BOOST_CHECK_EQUAL( std::distance(packet.data().begin(), packet.data().end()), 12 );
175 BOOST_CHECK_EQUAL( std::distance(packet.next().data().begin(), packet.next().data().end()), 8 );
176 BOOST_CHECK( packet.data().end() == packet.next().data().end() );
177 BOOST_CHECK_EQUAL( packet.size(), 12u );
178 BOOST_CHECK_EQUAL( packet.next().size(), 8u );
179 BOOST_CHECK( packet.is<FooPacket>() );
180 BOOST_CHECK( packet.next().is<BarPacket>() );
181 BOOST_CHECK( packet.first() == packet );
182 BOOST_CHECK( packet.last() == packet.next() );
184 BOOST_CHECK( ! packet.is_shared() );
186 senf::Packet p2 (packet);
187 BOOST_CHECK( packet.is_shared() );
188 BOOST_CHECK( p2.is_shared() );
190 BOOST_CHECK( ! packet.is_shared() );
192 senf::Packet p2 (packet.next());
194 BOOST_CHECK( packet.is_shared() );
195 BOOST_CHECK( p2.is_shared() );
196 packet.parseNextAs<FooPacket>();
197 BOOST_CHECK_EQUAL( packet.size(), 12u );
198 BOOST_CHECK_EQUAL( packet.next().size(), 8u );
199 BOOST_CHECK( packet.next().is<FooPacket>() );
201 BOOST_CHECK( packet.next().as<FooPacket>() );
203 p2 = packet.next().clone();
204 BOOST_CHECK( ! packet.is_shared() );
206 packet.next().append( p2 );
207 BOOST_REQUIRE( packet.next().next() );
208 BOOST_CHECK( packet.next().next().next() );
209 BOOST_CHECK( packet.next().next().next().is<senf::DataPacket>() );
210 BOOST_CHECK_EQUAL( packet.size(), 16u );
212 // This calls and checks typeId()
213 BOOST_CHECK_EQUAL( senf::PacketRegistry<RegTag>::key(packet), 1u );
214 packet.next().parseNextAs( senf::PacketRegistry<RegTag>::lookup(2u).factory() );
215 BOOST_CHECK( packet.next().next().is<BarPacket>() );
219 BOOST_CHECK_EQUAL( s.str(),
221 " (anonymous namespace)::IntAnnotation : 0\n"
226 packet.finalizeAll();
227 BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
228 BarPacket::Parser::type_t::value_type(-1) );
229 packet.last().append(FooPacket::create());
230 packet.finalizeThis();
231 packet.finalizeTo<BarPacket>();
232 packet.finalizeTo(packet.find<BarPacket>());
233 packet.finalizeAll();
234 BOOST_CHECK_EQUAL( packet.find<BarPacket>()->type(), 1u );
236 BOOST_CHECK( packet.factory() == FooPacket::factory() );
238 senf::PacketData::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 BarPacket::createAfter(packet, data);
242 BOOST_REQUIRE( packet.next() );
243 BOOST_REQUIRE( packet.next().is<BarPacket>() );
244 BOOST_CHECK( packet.last().is<FooPacket>() );
245 BOOST_CHECK_EQUAL( packet.last().rfind<BarPacket>()->type(), 1u );
246 BOOST_CHECK_EQUAL( packet.next().size(), 11u );
247 BOOST_REQUIRE( packet.next().next() );
248 BOOST_CHECK( packet.next().next().is<FooPacket>() );
249 BOOST_CHECK( ! packet.next().next().next(senf::nothrow) );
250 BOOST_CHECK_EQUAL( packet.next().next().data()[0], 0x81u );
252 BOOST_CHECK( packet.first().find<FooPacket>() == packet );
253 BOOST_CHECK( packet.last().rfind<BarPacket>() == packet.last().prev() );
254 BOOST_CHECK( packet.find<FooPacket>() == packet );
255 BOOST_CHECK( packet.last().rfind<FooPacket>() == packet.last() );
256 BOOST_CHECK( packet.next<BarPacket>() == packet.next() );
257 BOOST_CHECK( packet.last().prev().prev<FooPacket>() == packet );
259 senf::DataPacket::createAfter(packet);
260 BOOST_CHECK_THROW( packet.next().next().next().parseNextAs<BarPacket>(),
261 senf::InvalidPacketChainException );
263 SENF_CHECK_NO_THROW( BarPacket::create(senf::noinit).dump(s));
266 SENF_AUTO_UNIT_TEST(concretePacket)
268 senf::PacketData::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
270 BOOST_CHECK_EQUAL( FooPacket::create().size(), 4u );
271 BOOST_CHECK_EQUAL( FooPacket::create(senf::noinit).size(), 0u );
272 BOOST_CHECK_THROW( FooPacket::create(2u), senf::TruncatedPacketException );
273 // No 'u' suffix here to check, that the disable_if works ...
274 BOOST_CHECK_EQUAL( FooPacket::create(10).size(), 10u );
275 BOOST_CHECK_EQUAL( FooPacket::create(2u,senf::noinit).size(), 2u );
276 BOOST_CHECK_EQUAL( FooPacket::create(data).size(), 6u );
278 senf::Packet packet (FooPacket::create());
280 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet).size(), 4u );
281 BOOST_CHECK_EQUAL( packet.size(), 8u );
283 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,senf::noinit).size(), 0u );
284 BOOST_CHECK_EQUAL( packet.size(), 4u );
286 BOOST_CHECK_THROW( FooPacket::createAfter(packet,2u), senf::TruncatedPacketException );
287 // No 'u' suffix here to check, that the disable_if works ...
288 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,10).size(), 10u );
289 BOOST_CHECK_EQUAL( packet.size(), 14u );
291 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,2u,senf::noinit).size(), 2u );
292 BOOST_CHECK_EQUAL( packet.size(), 6u );
294 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,data).size(), 6u );
295 BOOST_CHECK_EQUAL( packet.size(), 10u );
297 BOOST_CHECK_EQUAL( FooPacket::createBefore(packet).size(), 14u );
298 BOOST_CHECK_EQUAL( packet.size(), 10u );
300 BOOST_CHECK_EQUAL( FooPacket::createBefore(packet,senf::noinit).size(), 10u );
301 BOOST_CHECK_EQUAL( packet.size(), 10u );
303 BOOST_CHECK_EQUAL( FooPacket::createInsertBefore(packet).size(), 14u );
304 BOOST_CHECK_EQUAL( packet.size(), 10u );
305 BOOST_REQUIRE( packet.prev() );
306 BOOST_CHECK_EQUAL( packet.prev().size(), 14u );
307 BOOST_REQUIRE( packet.prev().prev() );
308 BOOST_CHECK_EQUAL( packet.prev().prev().size(), 14u );
310 BOOST_CHECK_EQUAL( FooPacket::createInsertBefore(packet,senf::noinit).size(), 10u );
311 BOOST_CHECK_EQUAL( packet.size(), 10u );
312 BOOST_REQUIRE_NO_THROW( packet.prev().prev().prev() );
313 BOOST_CHECK_THROW( packet.prev().prev().prev().prev(), senf::InvalidPacketChainException );
314 BOOST_CHECK_EQUAL( packet.prev().size(), 10u );
315 BOOST_CHECK_EQUAL( packet.prev().prev().size(), 14u );
316 BOOST_CHECK_EQUAL( packet.prev().prev().prev().size(), 14u );
318 SENF_CHECK_NOT_EQUAL( packet.clone(), packet );
319 BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
322 SENF_AUTO_UNIT_TEST(packetAssign)
324 BarPacket bar1 (BarPacket::create());
325 BarPacket bar2 (BarPacket::create());
327 bar2->type() << 0x2A2Bu;
328 bar1.parser() << bar2;
330 BOOST_CHECK_EQUAL( bar1->type(), 0x2A2Bu );
333 SENF_AUTO_UNIT_TEST(packetAnnotation)
335 typedef senf::detail::AnnotationRegistry Reg;
337 senf::Packet packet (FooPacket::create());
338 BarPacket::createAfter(packet);
340 ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
342 BOOST_CHECK_EQUAL( ca.s, "empty" );
343 BOOST_CHECK_EQUAL( ca.i, -1 );
347 SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
349 senf::Packet p2 (packet.next());
351 BOOST_CHECK_EQUAL( p2.annotation<IntAnnotation>().value, 0xDEADBEEFu );
352 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "dead beef" );
353 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, 0x12345678 );
355 senf::Packet pClone (packet.clone());
357 p2.clearAnnotations();
358 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "empty" );
359 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, -1 );
360 BOOST_CHECK_EQUAL( p2.annotation<IntAnnotation>().value, 0 );
362 BOOST_CHECK_EQUAL( pClone.annotation<IntAnnotation>().value, 0xDEADBEEFu );
363 BOOST_CHECK_EQUAL( pClone.annotation<ComplexAnnotation>().s, "dead beef" );
364 BOOST_CHECK_EQUAL( pClone.annotation<ComplexAnnotation>().i, 0x12345678 );
366 BOOST_CHECK( Reg::lookup<IntAnnotation>() >= 0 );
367 BOOST_CHECK( Reg::lookup<LargeAnnotation>() < 0 );
368 BOOST_CHECK( Reg::lookup<ComplexAnnotation>() < 0 );
369 BOOST_CHECK( Reg::lookup<ComplexEmptyAnnotation>() < 0 );
371 std::stringstream ss;
372 senf::dumpPacketAnnotationRegistry(ss);
375 "SENF_PACKET_ANNOTATION_SLOTS = 8\n"
376 "SENF_PACKET_ANNOTATION_SLOTSIZE = 16\n"
377 "TYPE FAST COMPLEX SIZE\n"
378 "(anonymous namespace)::ComplexAnnotation no yes 32\n"
379 "(anonymous namespace)::ComplexEmptyAnnotation no yes 1\n"
380 "(anonymous namespace)::IntAnnotation yes no 4\n"
381 "(anonymous namespace)::LargeAnnotation no no 32\n" );
386 COMPILE_FAIL(invalidAnnotation)
388 #if 0 // The traits check fails for user defined but trivial constructors so ...
389 # ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
391 senf::Packet packet (FooPacket::create());
392 senf::IGNORE( packet.annotation<InvalidAnnotation>() );
398 invalid_annotation_check_disabled();
404 //-/////////////////////////////////////////////////////////////////////////////////////////////////
411 // c-file-style: "senf"
412 // indent-tabs-mode: nil
413 // ispell-local-dictionary: "american"
414 // compile-command: "scons -u test"
415 // comment-column: 40