Update SENF to compile using g++ 4.3.2 (Ubuntu 8.10)
[senf.git] / Packets / Packet.test.cc
index bc565de..e61d67a 100644 (file)
@@ -1,9 +1,9 @@
 // $Id$
 //
-// Copyright (C) 2006
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
-//     Stefan Bund <stefan.bund@fokus.fraunhofer.de>
+// 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
 // it under the terms of the GNU General Public License as published by
 // Free Software Foundation, Inc.,
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
-// Unit tests
+/** \file
+    \brief Packet.test unit tests */
 
 //#include "Packet.test.hh"
 //#include "Packet.test.ih"
 
 // Custom includes
-#include "Packet.hh"
-#include "DataPacket.hh"
-#include "GenericPacket.hh"
+#include <sstream>
+#include <boost/static_assert.hpp>
+#include "Packets.hh"
 
-#include <boost/test/auto_unit_test.hpp>
+#include "../Utils/auto_unit_test.hh"
 #include <boost/test/test_tools.hpp>
 
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-using namespace senf;
-
-// Since Packet is abstract, we can only test the Packet interface using
-// a simple implementation: DataPacket and GenericPacket.
-
 namespace {
 
-    Packet::byte data[] = {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
-                            10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
+    struct RegTag {
+        typedef unsigned key_t;
+    };
 
-    bool compare(Packet::iterator b, Packet::iterator e, unsigned o=0)
+    struct FooPacketType 
+        : public senf::PacketTypeBase,
+          public senf::PacketTypeMixin<FooPacketType>
+    {
+        using senf::PacketTypeMixin<FooPacketType>::nextPacketRange;
+        using senf::PacketTypeMixin<FooPacketType>::initSize;
+        using senf::PacketTypeMixin<FooPacketType>::init;
+        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
+    {
+#       include SENF_FIXED_PARSER()
+        
+        SENF_PARSER_FIELD( type,     senf::UInt16Parser );
+        SENF_PARSER_FIELD( length,   senf::Int32Parser  );
+        SENF_PARSER_FIELD( reserved, senf::UInt16Parser );
+
+        SENF_PARSER_INIT() {
+            reserved() << 0xA0A0u;
+        }
+
+        SENF_PARSER_FINALIZE(BarPacketParser);
+    };
+
+    struct BarPacketType 
+        : public senf::PacketTypeBase,
+          public senf::PacketTypeMixin<BarPacketType,RegTag>
     {
-        unsigned i (o);
-        for (; b!=e; ++b, ++i)
-            if (i>=sizeof(data) || *b != data[i])
-                return false;
-        return true;
+        typedef senf::PacketTypeMixin<BarPacketType,RegTag> mixin;
+        typedef senf::ConcretePacket<BarPacketType> packet;
+        typedef BarPacketParser parser;
+        using mixin::nextPacketRange;
+        using mixin::nextPacketType;
+        using mixin::initSize;
+        using mixin::init;
+        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(senf::nothrow))
+                p->type() = senf::PacketRegistry<RegTag>::key(p.next());
+            else
+                p->type() = -1;
+        }
+        static key_t nextPacketKey(packet p) {
+            return p->type();
+        }
+    };
+    typedef BarPacketType::packet BarPacket;
+
+    namespace reg {
+        senf::PacketRegistry<RegTag>::RegistrationProxy<FooPacket> registerFoo(1u);
+        senf::PacketRegistry<RegTag>::RegistrationProxy<BarPacket> registerBar(2u);
     }
 
-}
-
-BOOST_AUTO_UNIT_TEST(Packet_DataPacket)
-{
-    Packet::ptr p (Packet::create<DataPacket>(data, data+sizeof(data)));
+    struct IntAnnotation {
+        unsigned value;
+    };
+    
+    struct LargeAnnotation {
+        char value[32];
+    };
 
-    BOOST_REQUIRE( p );
-    BOOST_CHECK_EQUAL( p->size(), sizeof(data) );
-    BOOST_CHECK( compare(p->begin(), p->end()) );
+    struct ComplexAnnotation : senf::ComplexAnnotation
+    {
+        std::string s;
+        int i;
+    };
 
-    *p->begin() = 20;
-    BOOST_CHECK( !compare(p->begin(), p->end()) );
-    BOOST_CHECK_EQUAL( *p->begin(), 20 );
+    struct ComplexEmptyAnnotation : senf::ComplexAnnotation
+    {};
 
-    BOOST_CHECK( !p->next() );
-    BOOST_CHECK( !p->prev() );
-    BOOST_CHECK_EQUAL( p->head(), p );
-    BOOST_CHECK_EQUAL( p->last(), p );
+    struct InvalidAnnotation
+    {
+        std::string value;
+    };
 
-    BOOST_CHECK( p->is<DataPacket>() );
-    BOOST_CHECK( p->as<DataPacket>() );
 }
 
-BOOST_AUTO_UNIT_TEST(Packet_GenericPacket)
+BOOST_AUTO_UNIT_TEST(packet)
 {
-    GenericPacket<4,6>::ptr p (Packet::create< GenericPacket<4,6> >(data, data+sizeof(data)));
-
-    // check, that the packet was constructed corretly
-    BOOST_REQUIRE( p );
-    BOOST_CHECK_EQUAL( p->size(), sizeof(data) );
-    BOOST_CHECK( compare(p->begin(), p->end()) );
-    BOOST_CHECK_EQUAL( p->header_len(), 4u );
-    BOOST_CHECK( compare(p->begin_header(), p->end_header()) );
-    BOOST_CHECK_EQUAL( p->trailer_len(), 6u );
-    BOOST_CHECK( compare(p->begin_trailer(), p->end_trailer(), sizeof(data)-6) );
-
-    // check the first packet in the interpreter chain
-    BOOST_CHECK_EQUAL( p->head(), p );
-    BOOST_CHECK( !p->prev() );
-    BOOST_CHECK(( p->is< GenericPacket<4,6> >() ));
-    BOOST_CHECK( !p->is<DataPacket>() );
-    BOOST_CHECK(( !p->is< GenericPacket<4,4> >() ));
-    BOOST_CHECK(( p->as< GenericPacket<4,6> >() ));
-    BOOST_CHECK( !p->as<DataPacket>() );
-
-    // check the next packet in the interpreter chain
-    BOOST_REQUIRE( p->next() );
-    BOOST_CHECK( p->next()->is<DataPacket>() );
-    BOOST_CHECK(( !p->next()->is< GenericPacket<4,6> >() ));
-
-    // check the contents of the second interpreter
-    BOOST_CHECK_EQUAL( p->next()->size(), sizeof(data)-10 );
-    BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 4) );
-
-    // validate, that the two interpreters share the same data
-    // container
-    *p->next()->begin() = 20;
-    BOOST_CHECK( !compare(p->next()->begin(), p->next()->end(), 4) );
-    BOOST_CHECK( *p->next()->begin() == 20 );
-    BOOST_CHECK( !compare(p->begin(), p->end()) );
-    BOOST_CHECK( *(p->begin()+4) == 20 );
-
-    // We need require here. If this fails, p->last() will probably
-    // run into an endless loop ...
-    BOOST_REQUIRE( !p->next()->next() );
-    BOOST_CHECK_EQUAL( p->next(), p->last() );
+    senf::Packet packet (FooPacket::create());
+    BarPacket::createAfter(packet);
+
+    BOOST_REQUIRE( packet );
+    BOOST_CHECK( packet.next() );
+    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>() );
+    BOOST_CHECK( packet.next().is<BarPacket>() );
+    BOOST_CHECK( packet.first() == packet );
+    BOOST_CHECK( packet.last() == packet.next() );
+    
+    senf::Packet p2 (packet.next());
+    BOOST_CHECK( p2 );
+    packet.parseNextAs<FooPacket>();
+    BOOST_CHECK_EQUAL( packet.size(), 12u );
+    BOOST_CHECK_EQUAL( packet.next().size(), 8u );
+    BOOST_CHECK( packet.next().is<FooPacket>() );
+    BOOST_CHECK( ! p2 );
+    BOOST_CHECK( packet.next().as<FooPacket>() );
+    
+    p2 = packet.next().clone();
+    BOOST_REQUIRE( p2 );
+    packet.next().append( p2 );
+    BOOST_REQUIRE( packet.next().next() );
+    BOOST_CHECK( packet.next().next().next() );
+    BOOST_CHECK( packet.next().next().next().is<senf::DataPacket>() );
+    BOOST_CHECK_EQUAL( packet.size(), 16u );
+
+    // This calls and checks typeId()
+    BOOST_CHECK_EQUAL( senf::PacketRegistry<RegTag>::key(packet), 1u );
+    packet.next().parseNextAs( senf::PacketRegistry<RegTag>::lookup(2u).factory() );
+    BOOST_CHECK( packet.next().next().is<BarPacket>() );
+    
+    std::stringstream s;
+    packet.dump(s);
+    BOOST_CHECK_EQUAL( s.str(), "BarPacket:\ntype: 0\nlength: 0\n" );
+    
+    packet.finalizeAll();
+    BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(), 
+                       BarPacket::Parser::type_t::value_type(-1) );
+    packet.last().append(FooPacket::create());
+    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);
+    BOOST_REQUIRE( packet.next() );
+    BOOST_REQUIRE( packet.next().is<BarPacket>() );
+    BOOST_CHECK( packet.last().is<FooPacket>() );
+    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(senf::nothrow) );
+    BOOST_CHECK_EQUAL( packet.next().next().data()[0], 0x81u );
+
+    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.last().prev().prev<FooPacket>() == packet );
 }
 
-BOOST_AUTO_UNIT_TEST(Packet_Reinterpret)
+BOOST_AUTO_UNIT_TEST(concretePacket)
 {
-    Packet::ptr p (Packet::create< GenericPacket<4,4> >(data, data+sizeof(data)));
-
-    BOOST_CHECK( p->next()->is<DataPacket>() );
-    p->next()->reinterpret< GenericPacket<6> >();
-    BOOST_CHECK( p->next()->is< GenericPacket<6> >() );
-    BOOST_REQUIRE( p->next()->next() );
-    BOOST_CHECK( p->next()->next()->is<DataPacket>() );
-    BOOST_CHECK( !p->next()->next()->next() );
-
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), sizeof(data)-14 );
-    BOOST_CHECK( compare(p->next()->next()->begin(),
-                         p->next()->next()->end(), 10) );
-
-    p = p->reinterpret< GenericPacket<8,2> >();
-    BOOST_REQUIRE( p->next() );
-    BOOST_CHECK( p->next()->is<DataPacket>() );
-
-    BOOST_CHECK_EQUAL( p->next()->size(), sizeof(data)-10 );
-    BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 8) );
+    senf::PacketData::byte data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+
+    BOOST_CHECK_EQUAL( FooPacket::create().size(), 4u );
+    BOOST_CHECK_EQUAL( FooPacket::create(senf::noinit).size(), 0u );
+    BOOST_CHECK_THROW( FooPacket::create(2u), senf::TruncatedPacketException );
+    // 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,senf::noinit).size(), 0u );
+    BOOST_CHECK_EQUAL( packet.size(), 4u );
+
+    BOOST_CHECK_THROW( FooPacket::createAfter(packet,2u), senf::TruncatedPacketException );
+    // 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,senf::noinit).size(), 2u );
+    BOOST_CHECK_EQUAL( packet.size(), 6u );
+    
+    BOOST_CHECK_EQUAL( FooPacket::createAfter(packet,data).size(), 6u );
+    BOOST_CHECK_EQUAL( packet.size(), 10u );
+    
+    BOOST_CHECK_EQUAL( FooPacket::createBefore(packet).size(), 14u );
+    BOOST_CHECK_EQUAL( packet.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(Packet_InsertErase)
+BOOST_AUTO_UNIT_TEST(packetAnnotation)
 {
-    Packet::ptr p (Packet::create< GenericPacket<7,3> >(data, data+sizeof(data)));
-    p->next()->reinterpret< GenericPacket<4> >();
-
-    BOOST_CHECK_EQUAL( p->size(), 20u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 10u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u );
-
-    BOOST_CHECK_EQUAL( p->next()->next()->begin()[0], 11 );
-    BOOST_CHECK_EQUAL( p->end()[-1], 19 );
-    BOOST_CHECK_EQUAL( p->next()->end()[-1], 16 );
-    BOOST_CHECK_EQUAL( p->next()->next()->end()[-1], 16 );
+    senf::Packet packet (FooPacket::create());
+    BarPacket::createAfter(packet);
 
-    p->next()->insert(p->next()->begin()+2, data, data+6);
+    ComplexAnnotation & ca (packet.annotation<ComplexAnnotation>());
+    ca.s = "dead beef";
+    ca.i = 0x12345678;
+    SENF_CHECK_NO_THROW( packet.annotation<IntAnnotation>().value = 0xDEADBEEF );
 
-    BOOST_CHECK_EQUAL( p->size(), 26u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 16u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u );
+    senf::Packet p2 (packet.next());
 
-    BOOST_CHECK( compare(p->begin(), p->begin()+9) );
-    BOOST_CHECK( compare(p->begin()+9, p->begin()+15) );
-    BOOST_CHECK( compare(p->begin()+15, p->end(), 9) );
-    BOOST_CHECK( compare(p->next()->begin(), p->next()->begin()+2, 7) );
-    BOOST_CHECK( compare(p->next()->begin()+2, p->next()->begin()+8) );
-    BOOST_CHECK( compare(p->next()->begin()+8, p->next()->end(), 9) );
-    BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) );
+    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 );
 
-    p->next()->erase( p->next()->begin()+2, p->next()->begin()+8 );
-
-    BOOST_CHECK_EQUAL( p->size(), 20u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 10u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u );
-
-    BOOST_CHECK( compare(p->begin(), p->end()) );
-    BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 7) );
-    BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) );
-
-    p->next()->insert(p->next()->begin()+4, data, data+2);
-
-    BOOST_CHECK_EQUAL( p->size(), 22u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 12u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u );
-
-    BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) );
-
-    p->next()->erase(p->next()->begin()+4, p->next()->begin()+6);
-
-    BOOST_CHECK_EQUAL( p->size(), 20u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 10u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 6u );
-
-    BOOST_CHECK( compare(p->begin(), p->end()) );
-    BOOST_CHECK( compare(p->next()->begin(), p->next()->end(), 7) );
-    BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 11) );
-
-    p->next()->next()->insert(p->next()->begin()+5, data, data+4);
-
-    BOOST_CHECK_EQUAL( p->size(), 24u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 14u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 10u );
+    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 );
+}
 
-    BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->begin()+1, 11) );
-    BOOST_CHECK( compare(p->next()->next()->begin()+1, p->next()->next()->begin()+5) );
-    BOOST_CHECK( compare(p->next()->next()->begin()+5, p->end(), 12) );
+#ifdef COMPILE_CHECK
 
-    p->next()->erase(p->next()->begin()+3, p->next()->begin()+9);
+COMPILE_FAIL(invalidAnnotation)
+{
+#   ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
 
-    BOOST_CHECK_EQUAL( p->size(), 18u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 8u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 5u );
+    senf::Packet packet (FooPacket::create());
+    (void) packet.annotation<InvalidAnnotation>();
 
-    BOOST_CHECK( compare(p->next()->next()->begin(), p->next()->next()->end(), 12) );
-    BOOST_CHECK( compare(p->begin(), p->begin()+10) );
-    BOOST_CHECK( compare(p->begin()+10, p->end(), 12) );
+#   else
 
-    p->erase(p->begin()+5, p->end());
+    invalid_annotation_check_disabled();
 
-    BOOST_CHECK_EQUAL( p->size(), 5u );
-    BOOST_CHECK_EQUAL( p->next()->size(), 0u );
-    BOOST_CHECK_EQUAL( p->next()->next()->size(), 0u );
+#   endif
 }
 
-BOOST_AUTO_UNIT_TEST(Packet_new)
-{
-    Packet::ptr p (Packet::create< GenericPacket<10,4> >());
-    BOOST_CHECK_EQUAL(p->size(), 14u);
-    Packet::ptr p2 (Packet::create< GenericPacket<2,2> >(p));
-    BOOST_CHECK_EQUAL(p2->size(),18u);
-}
+#endif
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_