-// Copyright (C) 2007
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// $Id$
+//
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/** \file
- \brief Packet.test unit tests */
+ \brief Packet unit tests */
//#include "Packet.test.hh"
//#include "Packet.test.ih"
// Custom includes
#include <sstream>
-#include "PacketType.hh"
-#include "PacketRegistry.hh"
-#include "Packet.hh"
-#include "ParseInt.hh"
-#include "PacketParser.hh"
-#include "DataPacket.hh"
-
-#include <boost/test/auto_unit_test.hpp>
+#include <boost/static_assert.hpp>
+#include "Packets.hh"
+
+#include "../Utils/auto_unit_test.hh"
#include <boost/test/test_tools.hpp>
#define prefix_
using senf::PacketTypeMixin<FooPacketType>::nextPacketRange;
using senf::PacketTypeMixin<FooPacketType>::initSize;
using senf::PacketTypeMixin<FooPacketType>::init;
- typedef senf::PacketInterpreter<FooPacketType> interpreter;
- static interpreter::size_type initSize()
+ static size_type initSize()
{ return 4u; }
+
+ // We need to implement initHeadSize() to force the mixin to switch into 'fixed-size'
+ // mode. Otherwise, mixin::nextPacketRange() would query the parser for it's size to find
+ // the header size. Since the parser is VoidPacketParser, the header size would therefore be
+ // 0
+ static size_type initHeadSize()
+ { return initSize(); }
};
typedef senf::ConcretePacket<FooPacketType> FooPacket;
struct BarPacketParser : public senf::PacketParserBase
{
- SENF_PACKET_PARSER_INIT(BarPacketParser);
+# include SENF_FIXED_PARSER()
- typedef senf::Parse_UInt16 Parse_Type;
- typedef senf::Parse_Int32 Parse_Length;
- typedef senf::Parse_UInt16 Parse_Reserved;
+ SENF_PARSER_FIELD( type, senf::UInt16Parser );
+ SENF_PARSER_FIELD( length, senf::Int32Parser );
+ SENF_PARSER_FIELD( reserved, senf::UInt16Parser );
- Parse_Type type() const { return parse<Parse_Type> (i()); }
- Parse_Length length() const { return parse<Parse_Length> (i()+2); }
- Parse_Reserved reserved() const { return parse<Parse_Reserved> (i()+6); }
+ SENF_PARSER_INIT() {
+ reserved() << 0xA0A0u;
+ }
+
+ SENF_PARSER_FINALIZE(BarPacketParser);
};
struct BarPacketType
using mixin::nextPacketType;
using mixin::initSize;
using mixin::init;
- static size_type initSize()
- { return 8u; }
- static void init(packet p) {
- p->reserved() = 0xA0A0u;
- }
static void dump(packet p, std::ostream & os) {
os << "BarPacket:\n"
<< "type: " << p->type() << "\n"
<< "length: " << p->length() << "\n";
}
static void finalize(packet p) {
- if (p.next())
+ if (p.next(senf::nothrow))
p->type() = senf::PacketRegistry<RegTag>::key(p.next());
else
p->type() = -1;
}
- static registry_key_t nextPacketKey(packet p) {
+ static key_t nextPacketKey(packet p) {
return p->type();
}
};
typedef BarPacketType::packet BarPacket;
namespace reg {
- senf::PacketRegistry<RegTag>::RegistrationProxy<FooPacketType> registerFoo(1u);
- senf::PacketRegistry<RegTag>::RegistrationProxy<BarPacketType> registerBar(2u);
+ senf::PacketRegistry<RegTag>::RegistrationProxy<FooPacket> registerFoo(1u);
+ senf::PacketRegistry<RegTag>::RegistrationProxy<BarPacket> registerBar(2u);
}
+ struct IntAnnotation {
+ unsigned value;
+ };
+
+ struct LargeAnnotation {
+ char value[32];
+ };
+
+ struct ComplexAnnotation : senf::ComplexAnnotation
+ {
+ std::string s;
+ int i;
+ };
+
+ struct ComplexEmptyAnnotation : senf::ComplexAnnotation
+ {};
+
+ struct InvalidAnnotation
+ {
+ std::string value;
+ };
+
}
BOOST_AUTO_UNIT_TEST(packet)
{
- senf::Packet packet (FooPacket::create());
+ senf::Packet packet (FooPacket::create());
BarPacket::createAfter(packet);
BOOST_REQUIRE( packet );
BOOST_CHECK( packet.next() );
- BOOST_CHECK( ! packet.next().next() );
- BOOST_CHECK( ! packet.prev() );
+ BOOST_CHECK( ! packet.next().next(senf::nothrow) );
+ BOOST_CHECK( ! packet.prev(senf::nothrow) );
BOOST_CHECK( packet.next().prev() == packet );
BOOST_CHECK( packet.next() != packet );
+ BOOST_CHECK_EQUAL( std::distance(packet.data().begin(), packet.next().data().begin()), 4 );
+ BOOST_CHECK_EQUAL( std::distance(packet.data().begin(), packet.data().end()), 12 );
+ BOOST_CHECK_EQUAL( std::distance(packet.next().data().begin(), packet.next().data().end()), 8 );
+ BOOST_CHECK( packet.data().end() == packet.next().data().end() );
BOOST_CHECK_EQUAL( packet.size(), 12u );
BOOST_CHECK_EQUAL( packet.next().size(), 8u );
BOOST_CHECK( packet.is<FooPacket>() );
packet.dump(s);
BOOST_CHECK_EQUAL( s.str(), "BarPacket:\ntype: 0\nlength: 0\n" );
- packet.finalize();
+ packet.finalizeAll();
BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
- BarPacket::type::parser::Parse_Type::value_type(-1) );
+ BarPacket::Parser::type_t::value_type(-1) );
packet.last().append(FooPacket::create());
- packet.finalize();
- BOOST_CHECK_EQUAL( packet.next<BarPacket>()->type(), 1u );
+ packet.finalizeThis();
+ packet.finalizeTo<BarPacket>();
+ packet.finalizeTo(packet.find<BarPacket>());
+ packet.finalizeAll();
+ BOOST_CHECK_EQUAL( packet.find<BarPacket>()->type(), 1u );
BOOST_CHECK( packet.factory() == FooPacket::factory() );
senf::PacketData::byte data[] = { 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x81, 0x82, 0x83 };
- BarPacket::createAfter(packet,data);
+ BarPacket::createAfter(packet, data);
BOOST_REQUIRE( packet.next() );
BOOST_REQUIRE( packet.next().is<BarPacket>() );
BOOST_CHECK( packet.last().is<FooPacket>() );
- BOOST_CHECK_EQUAL( packet.last<BarPacket>()->type(), 1u );
+ BOOST_CHECK_EQUAL( packet.last().rfind<BarPacket>()->type(), 1u );
BOOST_CHECK_EQUAL( packet.next().size(), 11u );
BOOST_REQUIRE( packet.next().next() );
BOOST_CHECK( packet.next().next().is<FooPacket>() );
- BOOST_CHECK( ! packet.next().next().next() );
+ BOOST_CHECK( ! packet.next().next().next(senf::nothrow) );
BOOST_CHECK_EQUAL( packet.next().next().data()[0], 0x81u );
- BOOST_CHECK( packet.first<FooPacket>() == packet );
- BOOST_CHECK( packet.first<FooPacket>(senf::nothrow) == packet );
- BOOST_CHECK( packet.last<BarPacket>() == packet.last().prev() );
- BOOST_CHECK( packet.last<BarPacket>(senf::nothrow) == packet.last().prev() );
- BOOST_CHECK( packet.findNext<FooPacket>() == packet );
- BOOST_CHECK( packet.findNext<FooPacket>(senf::nothrow) == packet );
- BOOST_CHECK( packet.last().findPrev<FooPacket>() == packet.last() );
- BOOST_CHECK( packet.last().findPrev<FooPacket>(senf::nothrow) == packet.last() );
+ BOOST_CHECK( packet.first().find<FooPacket>() == packet );
+ BOOST_CHECK( packet.last().rfind<BarPacket>() == packet.last().prev() );
+ BOOST_CHECK( packet.find<FooPacket>() == packet );
+ BOOST_CHECK( packet.last().rfind<FooPacket>() == packet.last() );
BOOST_CHECK( packet.next<BarPacket>() == packet.next() );
- BOOST_CHECK( packet.next<BarPacket>(senf::nothrow) == packet.next() );
- BOOST_CHECK( packet.last().prev<FooPacket>() == packet );
- BOOST_CHECK( packet.last().prev<FooPacket>(senf::nothrow) == packet );
+ BOOST_CHECK( packet.last().prev().prev<FooPacket>() == packet );
+
+ senf::DataPacket::createAfter(packet);
+ BOOST_CHECK_THROW( packet.next().next().next().parseNextAs<BarPacket>(),
+ senf::InvalidPacketChainException );
}
BOOST_AUTO_UNIT_TEST(concretePacket)
senf::PacketData::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
BOOST_CHECK_EQUAL( FooPacket::create().size(), 4u );
- BOOST_CHECK_EQUAL( FooPacket::create(FooPacket::noinit).size(), 0u );
+ BOOST_CHECK_EQUAL( FooPacket::create(senf::noinit).size(), 0u );
BOOST_CHECK_THROW( FooPacket::create(2u), senf::TruncatedPacketException );
- BOOST_CHECK_EQUAL( FooPacket::create(10u).size(), 10u );
- BOOST_CHECK_EQUAL( FooPacket::create(2u,FooPacket::noinit).size(), 2u );
+ // No 'u' suffix here to check, that the disable_if works ...
+ BOOST_CHECK_EQUAL( FooPacket::create(10).size(), 10u );
+ BOOST_CHECK_EQUAL( FooPacket::create(2u,senf::noinit).size(), 2u );
BOOST_CHECK_EQUAL( FooPacket::create(data).size(), 6u );
senf::Packet packet (FooPacket::create());
BOOST_CHECK_EQUAL( FooPacket::createAfter(packet).size(), 4u );
BOOST_CHECK_EQUAL( packet.size(), 8u );
- BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,FooPacket::noinit).size(), 0u );
+ BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,senf::noinit).size(), 0u );
BOOST_CHECK_EQUAL( packet.size(), 4u );
BOOST_CHECK_THROW( FooPacket::createAfter(packet,2u), senf::TruncatedPacketException );
- BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,10u).size(), 10u );
+ // No 'u' suffix here to check, that the disable_if works ...
+ BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,10).size(), 10u );
BOOST_CHECK_EQUAL( packet.size(), 14u );
- BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,2u,FooPacket::noinit).size(), 2u );
+ BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,2u,senf::noinit).size(), 2u );
BOOST_CHECK_EQUAL( packet.size(), 6u );
BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,data).size(), 6u );
BOOST_CHECK_EQUAL( FooPacket::createBefore(packet).size(), 14u );
BOOST_CHECK_EQUAL( packet.size(), 10u );
- BOOST_CHECK_EQUAL( FooPacket::createBefore(packet,FooPacket::noinit).size(), 10u );
+ BOOST_CHECK_EQUAL( FooPacket::createBefore(packet,senf::noinit).size(), 10u );
BOOST_CHECK_EQUAL( packet.size(), 10u );
BOOST_CHECK( packet.clone() != packet );
BOOST_CHECK_EQUAL( BarPacket::create()->reserved(), 0xA0A0u );
}
+BOOST_AUTO_UNIT_TEST(packetAssign)
+{
+ BarPacket bar1 (BarPacket::create());
+ BarPacket bar2 (BarPacket::create());
+
+ bar2->type() << 0x2A2Bu;
+ bar1.parser() << bar2;
+
+ BOOST_CHECK_EQUAL( bar1->type(), 0x2A2Bu );
+}
+
+BOOST_AUTO_UNIT_TEST(packetAnnotation)
+{
+ senf::Packet packet (FooPacket::create());
+ BarPacket::createAfter(packet);
+
+ ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
+ ca.s = "dead beef";
+ ca.i = 0x12345678;
+ SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
+
+ senf::Packet p2 (packet.next());
+
+ BOOST_CHECK_EQUAL( p2.annotation<IntAnnotation>().value, 0xDEADBEEFu );
+ BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "dead beef" );
+ BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, 0x12345678 );
+
+ BOOST_CHECK( senf::detail::AnnotationIndexer<IntAnnotation>::Small );
+ BOOST_CHECK( ! senf::detail::AnnotationIndexer<LargeAnnotation>::Small );
+ BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexAnnotation>::Small );
+ BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexEmptyAnnotation>::Small );
+}
+
+#ifdef COMPILE_CHECK
+
+COMPILE_FAIL(invalidAnnotation)
+{
+#if 0 // The traits check fails for user defined but trivial constructors so ...
+# ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
+
+ senf::Packet packet (FooPacket::create());
+ (void) packet.annotation<InvalidAnnotation>();
+
+# else
+# endif
+#endif
+
+ invalid_annotation_check_disabled();
+
+}
+
+#endif
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_