diff options
author | Alan Conway <aconway@apache.org> | 2008-02-29 22:07:40 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2008-02-29 22:07:40 +0000 |
commit | 6dd59f62185ab8547cc1eec0a57731e0ab5a8645 (patch) | |
tree | 25539ade95b792d9e8228eb5b24d5a65340bc5d6 /cpp/src | |
parent | 3fb6c758d2d7d7c1822e216e3c22db4630eb19e0 (diff) | |
download | qpid-python-6dd59f62185ab8547cc1eec0a57731e0ab5a8645.tar.gz |
Template visitors for amqp_0_10::Command, Control and Struct.
Serialization for all str/vbin types.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@632457 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Makefile.am | 3 | ||||
-rw-r--r-- | cpp/src/qpid/Serializer.h | 80 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Codec.h | 134 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/Decimal.h | 5 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/apply.h | 77 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/built_in_types.h | 60 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/helpers.cpp | 3 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/helpers.h | 7 | ||||
-rw-r--r-- | cpp/src/qpid/amqp_0_10/visitors.h | 15 | ||||
-rw-r--r-- | cpp/src/qpid/framing/Uuid.h | 2 | ||||
-rw-r--r-- | cpp/src/tests/Makefile.am | 2 | ||||
-rw-r--r-- | cpp/src/tests/apply.cpp | 92 | ||||
-rw-r--r-- | cpp/src/tests/serialize.cpp | 30 |
13 files changed, 301 insertions, 209 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am index becccb4224..a3609667d7 100644 --- a/cpp/src/Makefile.am +++ b/cpp/src/Makefile.am @@ -104,10 +104,10 @@ libqpidcommon_la_SOURCES = \ $(rgen_common_cpp) \ $(platform_src) \ qpid/amqp_0_10/helpers.cpp \ - qpid/Serializer.h \ qpid/amqp_0_10/built_in_types.h \ qpid/amqp_0_10/Codec.h \ qpid/amqp_0_10/Decimal.h \ + qpid/Serializer.h \ qpid/framing/AccumulatedAck.cpp \ qpid/framing/AMQBody.cpp \ qpid/framing/AMQMethodBody.cpp \ @@ -254,6 +254,7 @@ libqpidclient_la_SOURCES = \ nobase_include_HEADERS = \ $(platform_hdr) \ qpid/amqp_0_10/helpers.h \ + qpid/amqp_0_10/apply.h \ qpid/assert.h \ qpid/DataDir.h \ qpid/Exception.h \ diff --git a/cpp/src/qpid/Serializer.h b/cpp/src/qpid/Serializer.h index a2fbf944ae..95cc2d5875 100644 --- a/cpp/src/qpid/Serializer.h +++ b/cpp/src/qpid/Serializer.h @@ -1,5 +1,5 @@ -#ifndef QPID_SERIALIZERBASE_H -#define QPID_SERIALIZERBASE_H +#ifndef QPID_SERIALIZER_H +#define QPID_SERIALIZER_H /* * @@ -22,88 +22,36 @@ * */ -#include <boost/cast.hpp> -#include <boost/array.hpp> +#include <boost/type_traits/remove_const.hpp> #include <boost/utility/enable_if.hpp> -#include <boost/type_traits/is_class.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/type_traits/add_const.hpp> +#include <algorithm> namespace qpid { /** - * Base template for serializers, provides generic serialization for - * conmpound types and common encode/decode/size functions. - * - * Derived template must provide - * - Derived& op()(T) for primitive types. - * - Derived& raw(void*, size_t) for raw binary data - * - Derived& byte(char) for single bytes. - * - * Derived templatse may override any of the functions provided by - * this base class. - * - * This class provides templates to break down compound types - * into primitive types and delegate to the derived class. - * + * Base class for serializers. */ template <class Derived> class Serializer { public: - - /** Call T::serialize() for classes that have their own serialize function */ - template <class T> - typename boost::enable_if<boost::is_class<T>, Derived>::type - operator()(T& t) { t.serialize(self()); return self(); } - - template <class T, size_t N> - Derived& operator()(boost::array<T,N>& a) { - std::for_each(a.begin(), a.end(), self()); - return self(); - } - - Derived& operator()(char& x) { return self().byte((char&)x); } - Derived& operator()(int8_t& x) { return self().byte((char&)x); } - Derived& operator()(uint8_t& x) { return self().byte((char&)x); } - - protected: - template <class T> Derived& raw(T& t) { - return self().raw(&t, sizeof(T)); - } - - private: - Derived& self() { return *static_cast<Derived*>(this); } -}; - -/** Like Serializer but does not modify the values passed to it. */ -template <class Derived> class ConstSerializer { - public: template <class T> - typename boost::enable_if<boost::is_class<T>, Derived>::type - operator()(const T& t) { - // Const cast so we don't have to write 2 serialize() functions - // for every class. - const_cast<T&>(t).serialize(self()); + typename boost::enable_if<boost::is_class<T>, Derived&>::type + operator()(T& t) { + // const_cast so we don't need 2 serialize() members for every class. + const_cast<typename boost::remove_const<T>::type&>(t).serialize(self()); return self(); } - template <class T, size_t N> - Derived& operator()(const boost::array<T,N>& a) { - std::for_each(a.begin(), a.end(), self()); + template <class Iter> Derived& iterate(Iter begin, Iter end) { + std::for_each(begin, end, self()); return self(); } - Derived& operator()(char x) { return self().byte(x); } - Derived& operator()(int8_t x) { return self().byte(x); } - Derived& operator()(uint8_t x) { return self().byte(x); } - - protected: - template <class T> Derived& raw(const T& t) { - return self().raw(&t, sizeof(T)); - } - private: Derived& self() { return *static_cast<Derived*>(this); } }; - } // namespace qpid -#endif /*!QPID_SERIALIZERBASE_H*/ +#endif /*!QPID_SERIALIZER_H*/ diff --git a/cpp/src/qpid/amqp_0_10/Codec.h b/cpp/src/qpid/amqp_0_10/Codec.h index e7f35e9288..acfc1e9c81 100644 --- a/cpp/src/qpid/amqp_0_10/Codec.h +++ b/cpp/src/qpid/amqp_0_10/Codec.h @@ -32,70 +32,47 @@ namespace qpid { namespace amqp_0_10 { - /** * AMQP 0-10 encoding and decoding. */ -struct Codec -{ - template <class T> - static inline void endianize(T& value) { - -#ifdef BOOST_LITTLE_ENDIAN - std::reverse((char*)&value, (char*)&value+sizeof(value)); -#else - (void)value; // Avoid unused var warnings. -#endif - } - static inline void endianize(char&) {} - static inline void endianize(uint8_t&) {} - static inline void endianize(int8_t&) {} - - - template <class Out> struct Encode : public ConstSerializer<Encode<Out> > { - Out out; +class Codec { + public: + /** Encode to an output byte iterator */ + template <class OutIter> + class Encode : public Serializer<Encode<OutIter> > { + public: + Encode(OutIter o) : out(o) {} - Encode(Out o) : out(o) {} + using Serializer<Encode<OutIter> >::operator(); - using ConstSerializer<Encode<Out> >::operator(); - using ConstSerializer<Encode<Out> >::raw; - - template <class T> + template <class T> typename boost::enable_if<boost::is_integral<T>, Encode&>::type - operator()(const T& x) { T xx(x); endianize(xx); return raw(xx); } + operator()(T x) { + endianize(x); + raw(&x, sizeof(x)); + return *this; + } - // FIXME aconway 2008-02-20: correct float encoading + // FIXME aconway 2008-02-20: correct float encoading? template <class T> typename boost::enable_if<boost::is_float<T>, Encode&>::type - operator()(const T& x) { return raw(x); } - + operator()(const T& x) { raw(&x, sizeof(x)); return *this; } - template<class T, class SizeType> - Encode& operator()(const CodableString<T,SizeType>& str) { - (*this)(SizeType(str.size())); - std::for_each(str.begin(), str.end(), *this); - return *this; + void raw(const void* p, size_t n) { + std::copy((const char*)p, (const char*)p+n, out); } - + private: - friend class ConstSerializer<Encode<Out> >; - - Encode& raw(const void* vp, size_t s) { - char* p = (char*) vp; - std::copy(p, p+s, out); - return *this; - } - - Encode& byte(char x) { out++ = x; return *this; } + OutIter out; }; - template <class In> struct Decode : public Serializer<Decode<In> > { - In in; - Decode(In i) : in(i) {} - - using Serializer<Decode<In> >::operator(); - using Serializer<Decode<In> >::raw; - + template <class InIter> + class Decode : public Serializer<Decode<InIter> > { + public: + Decode(InIter i) : in(i) {} + + using Serializer<Decode<InIter> >::operator(); + template <class T> typename boost::enable_if<boost::is_integral<T>, Decode&>::type operator()(T& x) { @@ -106,10 +83,10 @@ struct Codec template <class T> typename boost::enable_if<boost::is_float<T>, Decode&>::type - operator()(T& x) { return raw(&x, sizeof(x)); } + operator()(T& x) { raw(&x, sizeof(x)); return *this; } template<class T, class SizeType> - Decode& operator()(CodableString<T,SizeType>& str) { + Decode& operator()(SerializableString<T,SizeType>& str) { SizeType n; (*this)(n); str.resize(n); @@ -117,54 +94,45 @@ struct Codec return *this; } - private: - friend class Serializer<Decode<In> >; - - Decode& raw(void* vp, size_t s) { - char* p=(char*)vp; - std::copy(in, in+s, p); - return *this; + void raw(void *p, size_t n) { + // FIXME aconway 2008-02-29: requires random access iterator, + // does this optimize to memcpy? Is there a better way? + std::copy(in, in+n, (char*)p); + in += n; } - Decode& byte(char& x) { x = *in++; return *this; } + private: + InIter in; }; - struct Size : public ConstSerializer<Size> { + + class Size : public Serializer<Size> { + public: Size() : size(0) {} - size_t size; + operator size_t() const { return size; } - using ConstSerializer<Size>::operator(); - using ConstSerializer<Size>::raw; + using Serializer<Size>::operator(); template <class T> typename boost::enable_if<boost::is_arithmetic<T>, Size&>::type operator()(const T&) { size += sizeof(T); return *this; } - template <class T, size_t N> - Size& operator()(const boost::array<T,N>&) { - size += sizeof(boost::array<T,N>); - return *this; - } - template<class T, class SizeType> - Size& operator()(const CodableString<T,SizeType>& str) { + Size& operator()(const SerializableString<T,SizeType>& str) { size += sizeof(SizeType) + str.size()*sizeof(T); return *this; } + void raw(const void*, size_t n){ size += n; } private: - friend class ConstSerializer<Size>; - - Size& raw(void*, size_t s) { size += s; return *this; } - - Size& byte(char) { ++size; return *this; } + size_t size; }; template <class Out, class T> static void encode(Out o, const T& x) { - Encode<Out>encode(o); + Encode<Out> encode(o); encode(x); } @@ -180,6 +148,18 @@ struct Codec sz(x); return sz; } + + private: + template <class T> static inline void endianize(T& value) { +#ifdef BOOST_LITTLE_ENDIAN + std::reverse((char*)&value, (char*)&value+sizeof(value)); +#else + (void)value; // Avoid unused var warnings. +#endif + } + static inline void endianize(char&) {} + static inline void endianize(uint8_t&) {} + static inline void endianize(int8_t&) {} }; }} // namespace qpid::amqp_0_10 diff --git a/cpp/src/qpid/amqp_0_10/Decimal.h b/cpp/src/qpid/amqp_0_10/Decimal.h index 75cde94559..50fc457c76 100644 --- a/cpp/src/qpid/amqp_0_10/Decimal.h +++ b/cpp/src/qpid/amqp_0_10/Decimal.h @@ -30,7 +30,7 @@ template <class E, class M> struct Decimal { E exponent; M mantissa; - Decimal() : exponent(0), mantissa(0) {} + Decimal(E exp=0, M man=0) : exponent(exp), mantissa(man) {} bool operator==(const Decimal& d) const { return exponent == d.exponent && mantissa == d.mantissa; @@ -44,8 +44,7 @@ template <class E, class M> struct Decimal { template<class E, class M> inline std::ostream& operator<<(std::ostream& o, const Decimal<E,M>& d) { - M pow10=10^d.exponent; - return o << d.mantissa/pow10 << "." << d.mantissa%pow10; + return o << "Decimal{" << d.mantissa << "/10^" << (int)d.exponent << "}"; } }} diff --git a/cpp/src/qpid/amqp_0_10/apply.h b/cpp/src/qpid/amqp_0_10/apply.h new file mode 100644 index 0000000000..e1bd9c3aa6 --- /dev/null +++ b/cpp/src/qpid/amqp_0_10/apply.h @@ -0,0 +1,77 @@ +#ifndef QPID_AMQP_0_10_APPLY_H +#define QPID_AMQP_0_10_APPLY_H + +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include <boost/optional.hpp> + +namespace qpid { +namespace amqp_0_10 { + +template <class F, class R=typename F::result_type> struct FunctionAndResult { + F* functor; + boost::optional<R> result; + + FunctionAndResult() : functor(0) {} + template <class T> void invoke(T t) { result=(*functor)(t); } + R getResult() { return *result; } +}; + +// void result is special case. +template <class F> struct FunctionAndResult<F, void> { + F* functor; + + FunctionAndResult() : functor(0) {} + template <class T> void invoke(T t) { (*functor)(t); } + void getResult() {} +}; + +template <class V, class F> +struct ApplyVisitorBase : public V, public FunctionAndResult<F> { + using V::visit; +}; + +// Specialize for each visitor type +template <class V, class F> struct ApplyVisitor; + +/** Apply a functor to a visitable object. + * The functor can have operator() overloads for each visitable type + * and/or templated operator(). + */ +template <class F, class Visitable> +typename F::result_type apply(F& functor, Visitable& visitable) { + ApplyVisitor<typename Visitable::Visitor, F> visitor; + visitor.functor=&functor; + visitable.accept(visitor); + return visitor.getResult(); +} + +template <class F, class Visitable> +typename F::result_type apply(const F& functor, Visitable& visitable) { + ApplyVisitor<typename Visitable::Visitor, const F> visitor; + visitor.functor=&functor; + visitable.accept(visitor); + return visitor.getResult(); +} + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_APPLY_H*/ diff --git a/cpp/src/qpid/amqp_0_10/built_in_types.h b/cpp/src/qpid/amqp_0_10/built_in_types.h index 445f07459c..13bcdf862e 100644 --- a/cpp/src/qpid/amqp_0_10/built_in_types.h +++ b/cpp/src/qpid/amqp_0_10/built_in_types.h @@ -1,6 +1,5 @@ #ifndef QPID_AMQP_0_10_BUILT_IN_TYPES_H #define QPID_AMQP_0_10_BUILT_IN_TYPES_H -// FIXME aconway 2008-02-20: separate _fwd.h from full include. /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -29,6 +28,7 @@ #include <boost/array.hpp> #include <stdint.h> #include <string> +#include <ostream> #include <vector> /**@file Mapping from built-in AMQP types to C++ types */ @@ -53,15 +53,19 @@ typedef uint64_t Uint64; typedef uint8_t Bin8; typedef uint8_t Uint8; -typedef boost::array<uint8_t,128> Bin1024; -typedef boost::array<uint8_t,16> Bin128; -typedef boost::array<uint8_t,2> Bin16; -typedef boost::array<uint8_t,32> Bin256; -typedef boost::array<uint8_t,4> Bin32; -typedef boost::array<uint8_t,5> Bin40; -typedef boost::array<uint8_t,64> Bin512; -typedef boost::array<uint8_t,8> Bin64; -typedef boost::array<uint8_t,9> Bin72; +template <size_t N> struct Bin : public boost::array<char, N> { + template <class S> void serialize(S& s) { s.raw(this->begin(), this->size()); } +}; + +typedef Bin<128> Bin1024; +typedef Bin<16> Bin128; +typedef Bin<2> Bin16; +typedef Bin<32> Bin256; +typedef Bin<4> Bin32; +typedef Bin<5> Bin40; +typedef Bin<64> Bin512; +typedef Bin<8> Bin64; +typedef Bin<9> Bin72; typedef double Double; typedef float Float; @@ -75,25 +79,35 @@ typedef Decimal<Uint8, Int64> Dec64; /** Template for length-prefixed strings/arrays. */ template <class T, class SizeType> -struct CodableString : public std::basic_string<T> {}; +struct SerializableString : public std::basic_string<T> { + using std::basic_string<T>::operator=; + template <class S> void serialize(S& s) { + s(SizeType(this->size())).iterate(this->begin(), this->end()); + } +}; + +// TODO aconway 2008-02-29: separate ostream ops +template <class T, class SizeType> +std::ostream& operator<<(std::ostream& o, const SerializableString<T,SizeType>& s) { + const std::basic_string<T> str(s); + return o << str.c_str(); // TODO aconway 2008-02-29: why doesn't o<<str work? +} // Variable width types -typedef CodableString<Uint8, Uint8> Vbin8; -typedef CodableString<char, Uint8> Str8Latin; -typedef CodableString<char, Uint8> Str8; -typedef CodableString<Uint16, Uint8> Str8Utf16; - -typedef CodableString<Uint8, Uint16> Vbin16; -typedef CodableString<char, Uint16> Str16Latin; -typedef CodableString<char, Uint16> Str16; -typedef CodableString<Uint16, Uint16> Str16Utf16; +typedef SerializableString<Uint8, Uint8> Vbin8; +typedef SerializableString<char, Uint8> Str8Latin; +typedef SerializableString<char, Uint8> Str8; +typedef SerializableString<Uint16, Uint8> Str8Utf16; -typedef CodableString<Uint8, Uint32> Vbin32; +typedef SerializableString<Uint8, Uint16> Vbin16; +typedef SerializableString<char, Uint16> Str16Latin; +typedef SerializableString<char, Uint16> Str16; +typedef SerializableString<Uint16, Uint16> Str16Utf16; -// FIXME aconway 2008-02-26: array encoding -template <class T> struct Array : public std::vector<T> {}; +typedef SerializableString<Uint8, Uint32> Vbin32; // FIXME aconway 2008-02-26: Unimplemented types: +template <class T> struct Array : public std::vector<T> {}; struct ByteRanges {}; struct SequenceSet {}; struct Map {}; diff --git a/cpp/src/qpid/amqp_0_10/helpers.cpp b/cpp/src/qpid/amqp_0_10/helpers.cpp index 4333a2cd92..457abe2d5f 100644 --- a/cpp/src/qpid/amqp_0_10/helpers.cpp +++ b/cpp/src/qpid/amqp_0_10/helpers.cpp @@ -19,6 +19,9 @@ * */ #include "helpers.h" +#include "qpid/amqp_0_10/CommandVisitor.h" +#include "qpid/amqp_0_10/ControlVisitor.h" +#include "qpid/amqp_0_10/StructVisitor.h" namespace qpid { namespace amqp_0_10 { diff --git a/cpp/src/qpid/amqp_0_10/helpers.h b/cpp/src/qpid/amqp_0_10/helpers.h index 1769d374d9..fc9a3e16a4 100644 --- a/cpp/src/qpid/amqp_0_10/helpers.h +++ b/cpp/src/qpid/amqp_0_10/helpers.h @@ -24,7 +24,6 @@ n * "License"); you may not use this file except in compliance #include <string> namespace qpid { - namespace amqp_0_10 { // Look up names by code @@ -35,19 +34,19 @@ const char* getStructName(uint8_t classCode, uint8_t code); struct Command { virtual ~Command(); - class Visitor; + struct Visitor; virtual void accept(Visitor&) const = 0; }; struct Control { virtual ~Control(); - class Visitor; + struct Visitor; virtual void accept(Visitor&) const = 0; }; struct Struct { virtual ~Struct(); - class Visitor; + struct Visitor; virtual void accept(Visitor&) const = 0; }; diff --git a/cpp/src/qpid/amqp_0_10/visitors.h b/cpp/src/qpid/amqp_0_10/visitors.h deleted file mode 100644 index 3835f37f3e..0000000000 --- a/cpp/src/qpid/amqp_0_10/visitors.h +++ /dev/null @@ -1,15 +0,0 @@ -// Visitors -template <class Base> struct Visitor; -template <class Base, class F, class R> FunctorVisitor; - -/** Template base implementation for visitables. */ -template <class Base, class Derived> -struct VisitableBase : public Base { - virtual void accept(Visitor<Derived>& v) { - v.visit(static_cast<Derived>&(*this)); - } - virtual void accept(Visitor<Derived>& v) const { - v.visit(static_cast<const Derived>&(*this)); - } -}; - diff --git a/cpp/src/qpid/framing/Uuid.h b/cpp/src/qpid/framing/Uuid.h index 278a60c439..bce18f55b3 100644 --- a/cpp/src/qpid/framing/Uuid.h +++ b/cpp/src/qpid/framing/Uuid.h @@ -67,7 +67,7 @@ struct Uuid : public boost::array<uint8_t, 16> { std::string str() const; template <class S> void serialize(S& s) { - s(static_cast<boost::array<uint8_t, 16>&>(*this)); + s.raw(begin(), size()); } }; diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am index 4a47797350..d25378a519 100644 --- a/cpp/src/tests/Makefile.am +++ b/cpp/src/tests/Makefile.am @@ -39,7 +39,7 @@ unit_test_SOURCES= unit_test.cpp unit_test.h \ ISList.cpp IList.cpp \ ClientSessionTest.cpp \ serialize.cpp \ - ProxyTemplate.cpp + ProxyTemplate.cpp apply.cpp # FIXME aconway 2008-02-20: removed RefCountedMap.cpp due to valgrind error. check_LTLIBRARIES += libshlibtest.la diff --git a/cpp/src/tests/apply.cpp b/cpp/src/tests/apply.cpp new file mode 100644 index 0000000000..553026a35c --- /dev/null +++ b/cpp/src/tests/apply.cpp @@ -0,0 +1,92 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +#include "unit_test.h" +#include "qpid/amqp_0_10/specification.h" +#include "qpid/amqp_0_10/ApplyControl.h" + +QPID_AUTO_TEST_SUITE(VisitorTestSuite) + +using namespace qpid::amqp_0_10; + +struct GetCode { + typedef uint8_t result_type; + template <class T> uint8_t operator()(const T&) const { return T::CODE; } +}; + +struct TestFunctor { + typedef bool result_type; + bool operator()(const connection::Tune& tune) { + BOOST_CHECK_EQUAL(tune.channelMax, 1u); + BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u); + BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u); + BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); + return true; + } + template <class T> + bool operator()(const T&) { return false; } +}; + +BOOST_AUTO_TEST_CASE(testApply) { + connection::Tune tune(1,2,3,4); + Control* p = &tune; + + // boost oddity - without the cast we get undefined symbol errors. + BOOST_CHECK_EQUAL(apply(GetCode(), *p), (uint8_t)connection::Tune::CODE); + + TestFunctor tf; + BOOST_CHECK(apply(tf, *p)); + + connection::Start start; + p = &start; + BOOST_CHECK(!apply(tf, *p)); +} + +struct VoidTestFunctor { + typedef void result_type; + + int code; + VoidTestFunctor() : code() {} + + void operator()(const connection::Tune& tune) { + BOOST_CHECK_EQUAL(tune.channelMax, 1u); + BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u); + BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u); + BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); + code=connection::Tune::CODE; + } + template <class T> + void operator()(const T&) { code=0xFF; } +}; + +BOOST_AUTO_TEST_CASE(testApplyVoid) { + connection::Tune tune(1,2,3,4); + Control* p = &tune; + VoidTestFunctor tf; + apply(tf, *p); + BOOST_CHECK_EQUAL(uint8_t(connection::Tune::CODE), tf.code); + + connection::Start start; + p = &start; + apply(tf, *p); + BOOST_CHECK_EQUAL(0xFF, tf.code); +} + +QPID_AUTO_TEST_SUITE_END() diff --git a/cpp/src/tests/serialize.cpp b/cpp/src/tests/serialize.cpp index a120be6458..8de2d4ca58 100644 --- a/cpp/src/tests/serialize.cpp +++ b/cpp/src/tests/serialize.cpp @@ -31,7 +31,7 @@ #include <boost/mpl/empty_sequence.hpp> #include <iterator> #include <string> -#include <ostream> +#include <iostream> #include <netinet/in.h> // Missing operators needed for tests. @@ -52,15 +52,6 @@ std::ostream& operator<<(std::ostream& out, const AbsTime& t) { } } -namespace amqp_0_10 { -template <class T, class SizeType> -std::ostream& operator<<(std::ostream& out, const CodableString<T,SizeType>& str) { - std::ostream_iterator<T> o(out, " "); - std::copy(str.begin(), str.end(), o); - return out; -} -} - } // qpid @@ -90,34 +81,37 @@ typedef concat2<FixedSizeTypes, VariableSizeTypes>::type AllTypes; BOOST_AUTO_TEST_CASE(testNetworkByteOrder) { string data; - uint32_t l = 1234567890; + uint32_t l = 0x11223344; Codec::encode(std::back_inserter(data), l); uint32_t enc=reinterpret_cast<const uint32_t&>(*data.data()); uint32_t l2 = ntohl(enc); BOOST_CHECK_EQUAL(l, l2); data.clear(); - uint16_t s = 12345; + uint16_t s = 0x1122; Codec::encode(std::back_inserter(data), s); uint32_t s2 = ntohs(*reinterpret_cast<const uint32_t*>(data.data())); BOOST_CHECK_EQUAL(s, s2); } +// Assign test values to the various types. void testValue(bool& b) { b = true; } template <class T> typename boost::enable_if<boost::is_arithmetic<T> >::type testValue(T& n) { n=42; } -void testValue(long long& l) { l = 12345; } +void testValue(long long& l) { l = 0x012345; } void testValue(Datetime& dt) { dt = qpid::sys::now(); } void testValue(Uuid& uuid) { uuid=Uuid(true); } -template <class E, class M> void testValue(Decimal<E,M>& d) { d.exponent=2; d.mantissa=1234; } +template <class E, class M> void testValue(Decimal<E,M>& d) { d.exponent=2; d.mantissa=0x1122; } void testValue(SequenceNo& s) { s = 42; } -template <class T, size_t N> void testValue(boost::array<T,N>& a) { a.assign(42); } -template <class T, class SizeType> void testValue(CodableString<T, SizeType>& s) { +template <size_t N> void testValue(Bin<N>& a) { a.assign(42); } +template <class T, class S> void testValue(SerializableString<T, S>& s) { char msg[]="foobar"; s.assign(msg, msg+sizeof(msg)); } +void testValue(Str16& s) { s = "the quick brown fox jumped over the lazy dog"; } +void testValue(Str8& s) { s = "foobar"; } -// FIXME aconway 2008-02-20: test AllTypes -BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, FixedSizeTypes) +//typedef mpl::vector<Str8, Str16>::type TestTypes; +BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, AllTypes) { string data; T t; |