4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief Packet unit tests */
31 //#include "Packet.test.hh"
32 //#include "Packet.test.ih"
36 #include <boost/static_assert.hpp>
37 #include <boost/cstdint.hpp>
40 #include <senf/Utils/auto_unit_test.hh>
41 #include <boost/test/test_tools.hpp>
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
49 typedef unsigned key_t;
53 : public senf::PacketTypeBase,
54 public senf::PacketTypeMixin<FooPacketType>
56 using senf::PacketTypeMixin<FooPacketType>::nextPacketRange;
57 using senf::PacketTypeMixin<FooPacketType>::initSize;
58 using senf::PacketTypeMixin<FooPacketType>::init;
59 static size_type initSize()
62 // We need to implement initHeadSize() to force the mixin to switch into 'fixed-size'
63 // mode. Otherwise, mixin::nextPacketRange() would query the parser for it's size to find
64 // the header size. Since the parser is VoidPacketParser, the header size would therefore be
66 static size_type initHeadSize()
67 { return initSize(); }
69 typedef senf::ConcretePacket<FooPacketType> FooPacket;
71 struct BarPacketParser : public senf::PacketParserBase
73 # include SENF_FIXED_PARSER()
75 SENF_PARSER_FIELD( type, senf::UInt16Parser );
76 SENF_PARSER_FIELD( length, senf::Int32Parser );
77 SENF_PARSER_FIELD( reserved, senf::UInt16Parser );
80 reserved() << 0xA0A0u;
83 SENF_PARSER_FINALIZE(BarPacketParser);
87 : public senf::PacketTypeBase,
88 public senf::PacketTypeMixin<BarPacketType,RegTag>
90 typedef senf::PacketTypeMixin<BarPacketType,RegTag> mixin;
91 typedef senf::ConcretePacket<BarPacketType> packet;
92 typedef BarPacketParser parser;
93 using mixin::nextPacketRange;
94 using mixin::nextPacketType;
95 using mixin::initSize;
97 static void dump(packet p, std::ostream & os) {
99 << senf::fieldName("type") << p->type() << "\n"
100 << senf::fieldName("length") << p->length() << "\n";
102 static void finalize(packet p) {
103 if (p.next(senf::nothrow))
104 p->type() = senf::PacketRegistry<RegTag>::key(p.next());
108 static key_t nextPacketKey(packet p) {
112 typedef BarPacketType::packet BarPacket;
115 senf::PacketRegistry<RegTag>::ScopedRegistrationProxy<FooPacket> registerFoo(1u);
116 senf::PacketRegistry<RegTag>::ScopedRegistrationProxy<BarPacket> registerBar(2u);
119 struct IntAnnotation {
120 boost::uint32_t value;
123 std::ostream & operator<<(std::ostream & os, IntAnnotation const & v)
124 { os << v.value; return os; }
126 struct LargeAnnotation {
130 std::ostream & operator<<(std::ostream & os, LargeAnnotation const & v)
131 { os << v.value; return os; }
133 struct ComplexAnnotation : senf::ComplexAnnotation
135 ComplexAnnotation() : s("empty"), i(-1) {}
138 // padding so the size does not depend on the platform ...
139 struct _ {std::string s;boost::int32_t i;};
140 char __ [32-sizeof(_)];
143 std::ostream & operator<<(std::ostream & os, ComplexAnnotation const & v)
144 { os << "('" << v.s << "' " << v.i << ')'; return os; }
146 struct ComplexEmptyAnnotation : senf::ComplexAnnotation
149 std::ostream & operator<<(std::ostream & os, ComplexEmptyAnnotation const & v)
150 { os << "(empty)"; return os; }
152 struct InvalidAnnotation
157 std::ostream & operator<<(std::ostream & os, InvalidAnnotation const & v)
158 { os << v.value; return os; }
162 SENF_AUTO_UNIT_TEST(packet)
164 BOOST_CHECK(! senf::Packet().is<BarPacket>() );
165 senf::Packet packet (FooPacket::create());
166 BarPacket::createAfter(packet);
168 BOOST_CHECK_THROW( senf::Packet().as<BarPacket>(), senf::WrapException<std::bad_cast> );
169 BOOST_CHECK_THROW( packet.as<BarPacket>(), senf::WrapException<std::bad_cast> );
171 BOOST_REQUIRE( packet );
172 BOOST_CHECK( packet.next() );
173 BOOST_CHECK( ! packet.next().next(senf::nothrow) );
174 BOOST_CHECK( ! packet.next().next(senf::nothrow).is<BarPacket>() );
175 BOOST_CHECK( ! packet.prev(senf::nothrow) );
176 BOOST_CHECK( packet.next().prev() == packet );
177 SENF_CHECK_NOT_EQUAL( packet.next(), packet );
178 BOOST_CHECK_EQUAL( std::distance(packet.data().begin(), packet.next().data().begin()), 4 );
179 BOOST_CHECK_EQUAL( std::distance(packet.data().begin(), packet.data().end()), 12 );
180 BOOST_CHECK_EQUAL( std::distance(packet.next().data().begin(), packet.next().data().end()), 8 );
181 BOOST_CHECK( packet.data().end() == packet.next().data().end() );
182 BOOST_CHECK_EQUAL( packet.size(), 12u );
183 BOOST_CHECK_EQUAL( packet.next().size(), 8u );
184 BOOST_CHECK( packet.is<FooPacket>() );
185 BOOST_CHECK( packet.next().is<BarPacket>() );
186 BOOST_CHECK( packet.first() == packet );
187 BOOST_CHECK( packet.last() == packet.next() );
189 BOOST_CHECK( ! packet.is_shared() );
191 senf::Packet p2 (packet);
192 BOOST_CHECK( packet.is_shared() );
193 BOOST_CHECK( p2.is_shared() );
195 BOOST_CHECK( ! packet.is_shared() );
197 senf::Packet p2 (packet.next());
199 BOOST_CHECK( packet.is_shared() );
200 BOOST_CHECK( p2.is_shared() );
201 packet.parseNextAs<FooPacket>();
202 BOOST_CHECK_EQUAL( packet.size(), 12u );
203 BOOST_CHECK_EQUAL( packet.next().size(), 8u );
204 BOOST_CHECK( packet.next().is<FooPacket>() );
206 BOOST_CHECK( packet.next().as<FooPacket>() );
208 p2 = packet.next().clone();
209 BOOST_CHECK( ! packet.is_shared() );
211 packet.next().append( p2 );
212 BOOST_REQUIRE( packet.next().next() );
213 BOOST_CHECK( packet.next().next().next() );
214 BOOST_CHECK( packet.next().next().next().is<senf::DataPacket>() );
215 BOOST_CHECK_EQUAL( packet.size(), 16u );
217 // This calls and checks typeId()
218 BOOST_CHECK_EQUAL( senf::PacketRegistry<RegTag>::key(packet), 1u );
219 packet.next().parseNextAs( senf::PacketRegistry<RegTag>::lookup(2u).factory() );
220 BOOST_CHECK( packet.next().next().is<BarPacket>() );
224 BOOST_CHECK_EQUAL( s.str(),
226 " (anonymous namespace)::IntAnnotation : 0\n"
231 packet.finalizeAll();
232 BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
233 BarPacket::Parser::type_t::value_type(-1) );
234 packet.last().append(FooPacket::create());
235 packet.finalizeThis();
236 packet.finalizeTo<BarPacket>();
237 packet.finalizeTo(packet.find<BarPacket>());
238 packet.finalizeAll();
239 BOOST_CHECK_EQUAL( packet.find<BarPacket>()->type(), 1u );
241 BOOST_CHECK( packet.factory() == FooPacket::factory() );
243 senf::PacketData::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 BarPacket::createAfter(packet, data);
247 BOOST_REQUIRE( packet.next() );
248 BOOST_REQUIRE( packet.next().is<BarPacket>() );
249 BOOST_CHECK( packet.last().is<FooPacket>() );
250 BOOST_CHECK_EQUAL( packet.last().rfind<BarPacket>()->type(), 1u );
251 BOOST_CHECK_EQUAL( packet.next().size(), 11u );
252 BOOST_REQUIRE( packet.next().next() );
253 BOOST_CHECK( packet.next().next().is<FooPacket>() );
254 BOOST_CHECK( ! packet.next().next().next(senf::nothrow) );
255 BOOST_CHECK_EQUAL( packet.next().next().data()[0], 0x81u );
257 BOOST_CHECK( packet.first().find<FooPacket>() == packet );
258 BOOST_CHECK( packet.last().rfind<BarPacket>() == packet.last().prev() );
259 BOOST_CHECK( packet.find<FooPacket>() == packet );
260 BOOST_CHECK( packet.last().rfind<FooPacket>() == packet.last() );
261 BOOST_CHECK( packet.next<BarPacket>() == packet.next() );
262 BOOST_CHECK( packet.last().prev().prev<FooPacket>() == packet );
264 senf::DataPacket::createAfter(packet);
265 BOOST_CHECK_THROW( packet.next().next().next().parseNextAs<BarPacket>(),
266 senf::InvalidPacketChainException );
268 SENF_CHECK_NO_THROW( BarPacket::create(senf::noinit).dump(s));
271 SENF_AUTO_UNIT_TEST(concretePacket)
273 senf::PacketData::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
275 BOOST_CHECK_EQUAL( FooPacket::create().size(), 4u );
276 BOOST_CHECK_EQUAL( FooPacket::create(senf::noinit).size(), 0u );
277 BOOST_CHECK_THROW( FooPacket::create(2u), senf::TruncatedPacketException );
278 // No 'u' suffix here to check, that the disable_if works ...
279 BOOST_CHECK_EQUAL( FooPacket::create(10).size(), 10u );
280 BOOST_CHECK_EQUAL( FooPacket::create(2u,senf::noinit).size(), 2u );
281 BOOST_CHECK_EQUAL( FooPacket::create(data).size(), 6u );
283 senf::Packet packet (FooPacket::create());
285 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet).size(), 4u );
286 BOOST_CHECK_EQUAL( packet.size(), 8u );
288 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,senf::noinit).size(), 0u );
289 BOOST_CHECK_EQUAL( packet.size(), 4u );
291 BOOST_CHECK_THROW( FooPacket::createAfter(packet,2u), senf::TruncatedPacketException );
292 // No 'u' suffix here to check, that the disable_if works ...
293 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,10).size(), 10u );
294 BOOST_CHECK_EQUAL( packet.size(), 14u );
296 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,2u,senf::noinit).size(), 2u );
297 BOOST_CHECK_EQUAL( packet.size(), 6u );
299 BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,data).size(), 6u );
300 BOOST_CHECK_EQUAL( packet.size(), 10u );
302 BOOST_CHECK_EQUAL( FooPacket::createBefore(packet).size(), 14u );
303 BOOST_CHECK_EQUAL( packet.size(), 10u );
305 BOOST_CHECK_EQUAL( FooPacket::createBefore(packet,senf::noinit).size(), 10u );
306 BOOST_CHECK_EQUAL( packet.size(), 10u );
308 BOOST_CHECK_EQUAL( FooPacket::createInsertBefore(packet).size(), 14u );
309 BOOST_CHECK_EQUAL( packet.size(), 10u );
310 BOOST_REQUIRE( packet.prev() );
311 BOOST_CHECK_EQUAL( packet.prev().size(), 14u );
312 BOOST_REQUIRE( packet.prev().prev() );
313 BOOST_CHECK_EQUAL( packet.prev().prev().size(), 14u );
315 BOOST_CHECK_EQUAL( FooPacket::createInsertBefore(packet,senf::noinit).size(), 10u );
316 BOOST_CHECK_EQUAL( packet.size(), 10u );
317 BOOST_REQUIRE_NO_THROW( packet.prev().prev().prev() );
318 BOOST_CHECK_THROW( packet.prev().prev().prev().prev(), senf::InvalidPacketChainException );
319 BOOST_CHECK_EQUAL( packet.prev().size(), 10u );
320 BOOST_CHECK_EQUAL( packet.prev().prev().size(), 14u );
321 BOOST_CHECK_EQUAL( packet.prev().prev().prev().size(), 14u );
323 SENF_CHECK_NOT_EQUAL( packet.clone(), packet );
324 BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
327 SENF_AUTO_UNIT_TEST(packetAssign)
329 BarPacket bar1 (BarPacket::create());
330 BarPacket bar2 (BarPacket::create());
332 bar2->type() << 0x2A2Bu;
333 bar1.parser() << bar2;
335 BOOST_CHECK_EQUAL( bar1->type(), 0x2A2Bu );
338 SENF_AUTO_UNIT_TEST(packetAnnotation)
340 typedef senf::detail::AnnotationRegistry Reg;
342 senf::Packet packet (FooPacket::create());
343 BarPacket::createAfter(packet);
345 ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
347 BOOST_CHECK_EQUAL( ca.s, "empty" );
348 BOOST_CHECK_EQUAL( ca.i, -1 );
352 SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
354 senf::Packet p2 (packet.next());
356 BOOST_CHECK_EQUAL( p2.annotation<IntAnnotation>().value, 0xDEADBEEFu );
357 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "dead beef" );
358 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, 0x12345678 );
360 senf::Packet pClone (packet.clone());
362 p2.clearAnnotations();
363 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "empty" );
364 BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, -1 );
365 BOOST_CHECK_EQUAL( p2.annotation<IntAnnotation>().value, 0 );
367 BOOST_CHECK_EQUAL( pClone.annotation<IntAnnotation>().value, 0xDEADBEEFu );
368 BOOST_CHECK_EQUAL( pClone.annotation<ComplexAnnotation>().s, "dead beef" );
369 BOOST_CHECK_EQUAL( pClone.annotation<ComplexAnnotation>().i, 0x12345678 );
371 BOOST_CHECK( Reg::lookup<IntAnnotation>() >= 0 );
372 BOOST_CHECK( Reg::lookup<LargeAnnotation>() < 0 );
373 BOOST_CHECK( Reg::lookup<ComplexAnnotation>() < 0 );
374 BOOST_CHECK( Reg::lookup<ComplexEmptyAnnotation>() < 0 );
376 std::stringstream ss;
377 senf::dumpPacketAnnotationRegistry(ss);
380 "SENF_PACKET_ANNOTATION_SLOTS = 8\n"
381 "SENF_PACKET_ANNOTATION_SLOTSIZE = 16\n"
382 "TYPE FAST COMPLEX SIZE\n"
383 "(anonymous namespace)::ComplexAnnotation no yes 32\n"
384 "(anonymous namespace)::ComplexEmptyAnnotation no yes 1\n"
385 "(anonymous namespace)::IntAnnotation yes no 4\n"
386 "(anonymous namespace)::LargeAnnotation no no 32\n" );
391 COMPILE_FAIL(invalidAnnotation)
393 #if 0 // The traits check fails for user defined but trivial constructors so ...
394 # ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
396 senf::Packet packet (FooPacket::create());
397 senf::IGNORE( packet.annotation<InvalidAnnotation>() );
403 invalid_annotation_check_disabled();
409 //-/////////////////////////////////////////////////////////////////////////////////////////////////
416 // c-file-style: "senf"
417 // indent-tabs-mode: nil
418 // ispell-local-dictionary: "american"
419 // compile-command: "scons -u test"
420 // comment-column: 40