From 920ebd038170238ab4e77d25a77cf2c6730ba97b Mon Sep 17 00:00:00 2001 From: Alan Conway Date: Tue, 4 Mar 2008 16:34:01 +0000 Subject: Completed holders, visitors and serialization for 0-10 commands and controls. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@633533 13f79535-47bb-0310-9956-ffa450edef68 --- qpid/cpp/src/Makefile.am | 5 +- qpid/cpp/src/qpid/Serializer.h | 43 ++++++++++---- qpid/cpp/src/qpid/amqp_0_10/Codec.h | 42 ++++++++------ qpid/cpp/src/qpid/amqp_0_10/Holder.h | 62 ++++++++++++++++++++ qpid/cpp/src/qpid/amqp_0_10/apply.h | 29 +++++++--- qpid/cpp/src/qpid/amqp_0_10/built_in_types.h | 33 +++++++---- qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp | 65 +++++++++++++++++++++ qpid/cpp/src/qpid/amqp_0_10/complex_types.h | 79 ++++++++++++++++++++++++++ qpid/cpp/src/qpid/amqp_0_10/helpers.cpp | 33 ----------- qpid/cpp/src/qpid/amqp_0_10/helpers.h | 81 --------------------------- qpid/cpp/src/qpid/framing/AMQBody.h | 3 +- qpid/cpp/src/tests/apply.cpp | 11 +++- qpid/cpp/src/tests/serialize.cpp | 56 ++++++++++++++++-- 13 files changed, 374 insertions(+), 168 deletions(-) create mode 100644 qpid/cpp/src/qpid/amqp_0_10/Holder.h create mode 100644 qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp create mode 100644 qpid/cpp/src/qpid/amqp_0_10/complex_types.h delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/helpers.cpp delete mode 100644 qpid/cpp/src/qpid/amqp_0_10/helpers.h (limited to 'qpid/cpp/src') diff --git a/qpid/cpp/src/Makefile.am b/qpid/cpp/src/Makefile.am index 080260be02..f15f8d7a91 100644 --- a/qpid/cpp/src/Makefile.am +++ b/qpid/cpp/src/Makefile.am @@ -103,8 +103,10 @@ libqpidcommon_la_LIBADD = \ libqpidcommon_la_SOURCES = \ $(rgen_common_cpp) \ $(platform_src) \ - qpid/amqp_0_10/helpers.cpp \ qpid/amqp_0_10/built_in_types.h \ + qpid/amqp_0_10/complex_types.h \ + qpid/amqp_0_10/complex_types.cpp \ + qpid/amqp_0_10/Holder.h \ qpid/amqp_0_10/Codec.h \ qpid/amqp_0_10/Decimal.h \ qpid/Serializer.h \ @@ -254,7 +256,6 @@ 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 \ diff --git a/qpid/cpp/src/qpid/Serializer.h b/qpid/cpp/src/qpid/Serializer.h index a7194c5095..34b95d3ffd 100644 --- a/qpid/cpp/src/qpid/Serializer.h +++ b/qpid/cpp/src/qpid/Serializer.h @@ -22,37 +22,60 @@ * */ -#include #include -#include +#include #include -#include #include namespace qpid { -/** - * Base class for serializers. - */ +// FIXME aconway 2008-03-03: Doc - esp decoding template class Serializer { public: + typedef Serializer result_type; // unary functor requirement. + + static const bool IS_DECODER=false; + + /** Generic handler for class objects, call serialize() */ template typename boost::enable_if, Derived&>::type operator()(T& t) { - // const_cast so we don't need 2 serialize() members for every class. - const_cast::type&>(t).serialize(self()); + t.serialize(self()); return self(); } - template Derived& iterate(Iter begin, Iter end) { - std::for_each(begin, end, self()); + /** Generic handler for const class objects, call serialize() */ + template + typename boost::enable_if, Derived&>::type + operator()(const T& t) { + assert(!Derived::IS_DECODER); // We won't modify the value. + // const_cast so we don't need 2 serialize() members for every class. + const_cast(t).serialize(self()); return self(); } + template struct Split { + Split(Derived& s, T& t) { t.encode(s); } + }; + + template struct Split { + Split(Derived& s, T& t) { t.decode(s); } + }; + /** + * Called by classes that want to receive separate + * encode()/decode() calls. + */ + template + void split(T& t) { Split(self(),t); } + private: Derived& self() { return *static_cast(this); } }; + + + + } // namespace qpid #endif /*!QPID_SERIALIZER_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/Codec.h b/qpid/cpp/src/qpid/amqp_0_10/Codec.h index acfc1e9c81..a36004753a 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/Codec.h +++ b/qpid/cpp/src/qpid/amqp_0_10/Codec.h @@ -28,15 +28,14 @@ #include #include #include -#include namespace qpid { namespace amqp_0_10 { /** * AMQP 0-10 encoding and decoding. */ -class Codec { - public: +struct Codec { // FIXME aconway 2008-02-29: drop this wrapper? + /** Encode to an output byte iterator */ template class Encode : public Serializer > { @@ -58,6 +57,11 @@ class Codec { typename boost::enable_if, Encode&>::type operator()(const T& x) { raw(&x, sizeof(x)); return *this; } + template Encode& operator()(Iter begin, Iter end) { + std::for_each(begin, end, *this); + return *this; + } + void raw(const void* p, size_t n) { std::copy((const char*)p, (const char*)p+n, out); } @@ -70,6 +74,8 @@ class Codec { class Decode : public Serializer > { public: Decode(InIter i) : in(i) {} + + static const bool IS_DECODER=true; using Serializer >::operator(); @@ -94,6 +100,11 @@ class Codec { return *this; } + template Decode& operator()(Iter begin, Iter end) { + std::for_each(begin, end, *this); + 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? @@ -124,30 +135,27 @@ class Codec { return *this; } + template + Size& operator()(const Iter& a, const Iter& b) { + size += (b-a)*sizeof(*a); + return *this; + } + void raw(const void*, size_t n){ size += n; } private: size_t size; }; - template - static void encode(Out o, const T& x) { - Encode encode(o); - encode(x); + template static Decode decode(const OutIter &i) { + return Decode(i); } - template - static void decode(In i, T& x) { - Decode decode(i); - decode(x); + template static Encode encode(InIter i) { + return Encode(i); } - template - static size_t size(const T& x) { - Size sz; - sz(x); - return sz; - } + template static size_t size(const T& x) { return Size()(x); } private: template static inline void endianize(T& value) { diff --git a/qpid/cpp/src/qpid/amqp_0_10/Holder.h b/qpid/cpp/src/qpid/amqp_0_10/Holder.h new file mode 100644 index 0000000000..76f8aa52de --- /dev/null +++ b/qpid/cpp/src/qpid/amqp_0_10/Holder.h @@ -0,0 +1,62 @@ +#ifndef QPID_AMQP_0_10_HOLDER_H +#define QPID_AMQP_0_10_HOLDER_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 "qpid/framing/Blob.h" +#include "apply.h" + +namespace qpid { +namespace amqp_0_10 { + +template +struct Holder : public framing::Blob { + + typedef framing::Blob Base; + + Holder() {} + template Holder(const T& value) : Base(value) {} + + using Base::operator=; + + uint8_t getCode() const { return this->get()->getCode(); } + uint8_t getClassCode() const { return this->get()->getClassCode(); } + + template void encode(S& s) { + s(getClassCode())(getCode()); + } + + template void decode(S& s) { + uint8_t code, classCode; + s(classCode)(code); + static_cast(this)->set(classCode, code); + } + + template void serialize(S& s) { + s.split(*this); + apply(s, *this->get()); + } +}; + + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_HOLDER_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/apply.h b/qpid/cpp/src/qpid/amqp_0_10/apply.h index e1bd9c3aa6..05b7669322 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/apply.h +++ b/qpid/cpp/src/qpid/amqp_0_10/apply.h @@ -31,7 +31,8 @@ template struct FunctionAndResult { boost::optional result; FunctionAndResult() : functor(0) {} - template void invoke(T t) { result=(*functor)(t); } + template void invoke(T& t) { result=(*functor)(t); } + template void invoke(const T& t) { result=(*functor)(t); } R getResult() { return *result; } }; @@ -40,17 +41,23 @@ template struct FunctionAndResult { F* functor; FunctionAndResult() : functor(0) {} - template void invoke(T t) { (*functor)(t); } + template void invoke(T& t) { (*functor)(t); } void getResult() {} }; -template -struct ApplyVisitorBase : public V, public FunctionAndResult { - using V::visit; +// Metafunction returning correct abstract visitor for Visitable type. +template struct VisitorType { + typedef typename Visitable::Visitor type; }; +template struct VisitorType { + typedef typename Visitable::ConstVisitor type; +}; + +template +struct ApplyVisitorBase : public Visitor, public FunctionAndResult {}; // Specialize for each visitor type -template struct ApplyVisitor; +template struct ApplyVisitor; /** Apply a functor to a visitable object. * The functor can have operator() overloads for each visitable type @@ -58,7 +65,7 @@ template struct ApplyVisitor; */ template typename F::result_type apply(F& functor, Visitable& visitable) { - ApplyVisitor visitor; + ApplyVisitor::type, F> visitor; visitor.functor=&functor; visitable.accept(visitor); return visitor.getResult(); @@ -66,12 +73,18 @@ typename F::result_type apply(F& functor, Visitable& visitable) { template typename F::result_type apply(const F& functor, Visitable& visitable) { - ApplyVisitor visitor; + ApplyVisitor::type, const F> visitor; visitor.functor=&functor; visitable.accept(visitor); return visitor.getResult(); } +template struct ApplyFunctor { + typedef R result_type; + static const bool IS_CONST=Const; +}; +template struct ConstApplyFunctor : public ApplyFunctor {}; + }} // namespace qpid::amqp_0_10 #endif /*!QPID_AMQP_0_10_APPLY_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h b/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h index 13bcdf862e..6188e259f0 100644 --- a/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h +++ b/qpid/cpp/src/qpid/amqp_0_10/built_in_types.h @@ -82,7 +82,7 @@ template struct SerializableString : public std::basic_string { using std::basic_string::operator=; template void serialize(S& s) { - s(SizeType(this->size())).iterate(this->begin(), this->end()); + s(SizeType(this->size()))(this->begin(), this->end()); } }; @@ -107,16 +107,29 @@ typedef SerializableString Str16Utf16; typedef SerializableString Vbin32; // FIXME aconway 2008-02-26: Unimplemented types: -template struct Array : public std::vector {}; -struct ByteRanges {}; -struct SequenceSet {}; -struct Map {}; -struct List {}; -struct Struct32 {}; +template struct Array : public std::vector { template void serialize(S&) {} }; +struct ByteRanges { template void serialize(S&) {} }; +struct SequenceSet { template void serialize(S&) {} }; +struct Map { template void serialize(S&) {} }; +struct List { template void serialize(S&) {} }; +struct Struct32 { template void serialize(S&) {} }; + +// Serializable enum support +template struct Enum { + Store value; + Enum() {} + Enum(E v) : value(v) {} + Enum(Store v) : value(v) {} + Enum& operator=(E v) { value=v; return *this; } + Enum& operator=(Store v) { value=v; return *this; } + operator E() const { return value; } + operator Store() const { return value; } + template void serialize(S& s) { s(value); } +}; -// Top level enum definitions. -enum SegmentType { CONTROL, COMMAND, HEADER, BODY }; +enum SegmentTypeEnum { CONTROL, COMMAND, HEADER, BODY }; +typedef Enum SegmentType; }} // namespace qpid::amqp_0_10 -#endif /*!QPID_AMQP_0_10_BUILT_IN_TYPES_H*/ +#endif diff --git a/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp b/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp new file mode 100644 index 0000000000..0960db469d --- /dev/null +++ b/qpid/cpp/src/qpid/amqp_0_10/complex_types.cpp @@ -0,0 +1,65 @@ +/* + * + * 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 "qpid/amqp_0_10/ApplyCommand.h" +#include "qpid/amqp_0_10/ApplyControl.h" +// FIXME aconway 2008-03-04: #include "qpid/amqp_0_10/ApplyStruct.h" +#include "qpid/amqp_0_10/apply.h" + +namespace qpid { +namespace amqp_0_10 { +// Functors for getting static values from a visitable base type. + +#define QPID_STATIC_VALUE_GETTER(NAME, TYPE, VALUE) \ + struct NAME : public ConstApplyFunctor { \ + template TYPE operator()(const T&) const { return T::VALUE; }\ + } + +QPID_STATIC_VALUE_GETTER(GetCode, uint8_t, CODE); +QPID_STATIC_VALUE_GETTER(GetSize, uint8_t, SIZE); +QPID_STATIC_VALUE_GETTER(GetPack, uint8_t, PACK); +QPID_STATIC_VALUE_GETTER(GetClassCode, uint8_t, CLASS_CODE); +QPID_STATIC_VALUE_GETTER(GetName, const char*, NAME); +QPID_STATIC_VALUE_GETTER(GetClassName, const char*, CLASS_NAME); + + +uint8_t Command::getCode() const { return apply(GetCode(), *this); } +uint8_t Command::getClassCode() const { return apply(GetClassCode(), *this); } +const char* Command::getName() const { return apply(GetName(), *this); } +const char* Command::getClassName() const { return apply(GetClassName(), *this); } + +uint8_t Control::getCode() const { return apply(GetCode(), *this); } +uint8_t Control::getClassCode() const { return apply(GetClassCode(), *this); } +const char* Control::getName() const { return apply(GetName(), *this); } +const char* Control::getClassName() const { return apply(GetClassName(), *this); } + +// FIXME aconway 2008-03-04: Struct visitors +// uint8_t Struct::getCode() const { return apply(GetCode(), *this); } +// uint8_t Struct::getPack() const { return apply(GetPack(), *this); } +// uint8_t Struct::getSize() const { return apply(GetSize(), *this); } +// uint8_t Struct::getClassCode() const { return apply(GetClassCode(), *this); } +uint8_t Struct::getCode() const { assert(0); return 0; } +uint8_t Struct::getPack() const { assert(0); return 0; } +uint8_t Struct::getSize() const { assert(0); return 0; } +uint8_t Struct::getClassCode() const { assert(0); return 0; } + +}} // namespace qpid::amqp_0_10 + diff --git a/qpid/cpp/src/qpid/amqp_0_10/complex_types.h b/qpid/cpp/src/qpid/amqp_0_10/complex_types.h new file mode 100644 index 0000000000..f4810ba2d7 --- /dev/null +++ b/qpid/cpp/src/qpid/amqp_0_10/complex_types.h @@ -0,0 +1,79 @@ +#ifndef QPID_AMQP_0_10_COMPLEX_TYPES_H +#define QPID_AMQP_0_10_COMPLEX_TYPES_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. + * + */ + +namespace qpid { +namespace amqp_0_10 { + +// Base classes for complex types. + +template struct Visitable { + typedef V Visitor; + typedef CV ConstVisitor; + typedef H Holder; + + virtual ~Visitable() {} + virtual void accept(Visitor&) = 0; + virtual void accept(ConstVisitor&) const = 0; +}; + +struct CommandVisitor; +struct ConstCommandVisitor; +struct CommandHolder; +struct Command + : public Visitable +{ + uint8_t getCode() const; + uint8_t getClassCode() const; + const char* getName() const; + const char* getClassName() const; +}; + +struct ControlVisitor; +struct ConstControlVisitor; +struct ControlHolder; +struct Control + : public Visitable +{ + uint8_t getCode() const; + uint8_t getClassCode() const; + const char* getName() const; + const char* getClassName() const; +}; + +struct StructVisitor; +struct ConstStructVisitor; +struct StructHolder; +struct Struct + : public Visitable +{ + uint8_t getCode() const; + uint8_t getPack() const; + uint8_t getSize() const; + uint8_t getClassCode() const; +}; + + +}} // namespace qpid::amqp_0_10 + +#endif /*!QPID_AMQP_0_10_COMPLEX_TYPES_H*/ diff --git a/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp b/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp deleted file mode 100644 index 457abe2d5f..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/helpers.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * 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 "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 { - -Control::~Control() {} -Command::~Command() {} -Struct::~Struct() {} - -}} // namespace qpid::amqp_0_10 diff --git a/qpid/cpp/src/qpid/amqp_0_10/helpers.h b/qpid/cpp/src/qpid/amqp_0_10/helpers.h deleted file mode 100644 index b5150cd10f..0000000000 --- a/qpid/cpp/src/qpid/amqp_0_10/helpers.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef QPID_AMQP_0_10_HELPERS_H -#define QPID_AMQP_0_10_HELPERS_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 -n * "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 "qpid/amqp_0_10/built_in_types.h" -#include - -namespace qpid { -namespace amqp_0_10 { - -// Look up names by code -const char* getClassName(uint8_t code); -const char* getCommandName(uint8_t classCode, uint8_t code); -const char* getControlName(uint8_t classCode, uint8_t code); -const char* getStructName(uint8_t classCode, uint8_t code); - -struct Command { - static const int SEGMENT_TYPE=COMMAND; - virtual ~Command(); - struct Visitor; - virtual void accept(Visitor&) const = 0; -}; - -struct Control { - static const int SEGMENT_TYPE=CONTROL; - virtual ~Control(); - struct Visitor; - virtual void accept(Visitor&) const = 0; -}; - -// Struct -struct Struct { - virtual ~Struct(); - struct Visitor; - virtual void accept(Visitor&) const = 0; -}; - -template -struct SerializableStruct : public Struct { - static const uint8_t SIZE=sizeof(SizeType); - static const bool CODED=Coded; - static const uint8_t CODE=Code; - static const uint8_t PACK; - // TODO aconway 2008-02-29: handle common encoding/decoding/size - // for structs. Support for packing. -}; - - -/** Base class for generated enum domains. - * Enums map to classes for type safety and to provide separate namespaces - * for clashing values. - */ -struct Enum { - int value; - Enum(int v=0) : value(v) {} - operator int() const { return value; } - template void serialize(S &s) { s(value); } -}; - -}} // namespace qpid::amqp_0_10 - -#endif /*!QPID_AMQP_0_10_HELPERS_H*/ diff --git a/qpid/cpp/src/qpid/framing/AMQBody.h b/qpid/cpp/src/qpid/framing/AMQBody.h index 73c462a427..925f4c46ac 100644 --- a/qpid/cpp/src/qpid/framing/AMQBody.h +++ b/qpid/cpp/src/qpid/framing/AMQBody.h @@ -22,7 +22,8 @@ * */ #include "qpid/framing/amqp_types.h" -#include "qpid/amqp_0_10/helpers.h" +#include "qpid/amqp_0_10/built_in_types.h" +#include "qpid/amqp_0_10/complex_types.h" #include diff --git a/qpid/cpp/src/tests/apply.cpp b/qpid/cpp/src/tests/apply.cpp index 553026a35c..1b66d8e3b4 100644 --- a/qpid/cpp/src/tests/apply.cpp +++ b/qpid/cpp/src/tests/apply.cpp @@ -26,11 +26,15 @@ QPID_AUTO_TEST_SUITE(VisitorTestSuite) using namespace qpid::amqp_0_10; -struct GetCode { - typedef uint8_t result_type; +struct GetCode : public ConstApplyFunctor { template uint8_t operator()(const T&) const { return T::CODE; } }; +struct SetChannelMax : ApplyFunctor { + template void operator()(T&) const { BOOST_FAIL(""); } + void operator()(connection::Tune& t) const { t.channelMax=42; } +}; + struct TestFunctor { typedef bool result_type; bool operator()(const connection::Tune& tune) { @@ -57,6 +61,9 @@ BOOST_AUTO_TEST_CASE(testApply) { connection::Start start; p = &start; BOOST_CHECK(!apply(tf, *p)); + + apply(SetChannelMax(), tune); + BOOST_CHECK_EQUAL(tune.channelMax, 42); } struct VoidTestFunctor { diff --git a/qpid/cpp/src/tests/serialize.cpp b/qpid/cpp/src/tests/serialize.cpp index 8de2d4ca58..9eaf78ab78 100644 --- a/qpid/cpp/src/tests/serialize.cpp +++ b/qpid/cpp/src/tests/serialize.cpp @@ -22,6 +22,9 @@ #include "unit_test.h" #include "qpid/amqp_0_10/built_in_types.h" #include "qpid/amqp_0_10/Codec.h" +#include "qpid/amqp_0_10/specification.h" +#include "qpid/amqp_0_10/ControlHolder.h" + #include #include #include @@ -62,6 +65,7 @@ QPID_AUTO_TEST_SUITE(SerializeTestSuite) using namespace std; namespace mpl=boost::mpl; using namespace qpid::amqp_0_10; +using qpid::framing::in_place; template struct concat2 { typedef typename mpl::copy >::type type; }; template struct concat3 { typedef typename concat2::type>::type type; }; @@ -82,14 +86,14 @@ BOOST_AUTO_TEST_CASE(testNetworkByteOrder) { string data; uint32_t l = 0x11223344; - Codec::encode(std::back_inserter(data), l); + Codec::encode(std::back_inserter(data))(l); uint32_t enc=reinterpret_cast(*data.data()); uint32_t l2 = ntohl(enc); BOOST_CHECK_EQUAL(l, l2); data.clear(); uint16_t s = 0x1122; - Codec::encode(std::back_inserter(data), s); + Codec::encode(std::back_inserter(data))(s); uint32_t s2 = ntohs(*reinterpret_cast(data.data())); BOOST_CHECK_EQUAL(s, s2); } @@ -116,14 +120,58 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, AllTypes) string data; T t; testValue(t); - Codec::encode(std::back_inserter(data), t); + Codec::encode(std::back_inserter(data))(t); BOOST_CHECK_EQUAL(Codec::size(t), data.size()); T t2; - Codec::decode(data.begin(), t2); + Codec::decode(data.begin())(t2); BOOST_CHECK_EQUAL(t,t2); } +struct TestMe { + bool encoded, decoded; + char value; + TestMe(char v) : encoded(), decoded(), value(v) {} + template void encode(S& s) { encoded=true; s(value); } + template void decode(S& s) { decoded=true; s(value); } + template void serialize(S& s) { s.split(*this); } +}; + +BOOST_AUTO_TEST_CASE(testSplit) { + string data; + TestMe t1('x'); + Codec::encode(std::back_inserter(data))(t1); + BOOST_CHECK(t1.encoded); + BOOST_CHECK(!t1.decoded); + BOOST_CHECK_EQUAL(data, "x"); + + TestMe t2('y'); + Codec::decode(data.begin())(t2); + BOOST_CHECK(!t2.encoded); + BOOST_CHECK(t2.decoded); + BOOST_CHECK_EQUAL(t2.value, 'x'); +} + +BOOST_AUTO_TEST_CASE(testControlEncodeDecode) { + string data; + Control::Holder h(in_place(1,2,3,4)); + Codec::encode(std::back_inserter(data))(h); + + BOOST_CHECK_EQUAL(data.size(), Codec::size(h)); + + Codec::Decode decode(data.begin()); + Control::Holder h2; + decode(h2); + + BOOST_REQUIRE(h2.get()); + BOOST_CHECK_EQUAL(h2.get()->getClassCode(), connection::CODE); + BOOST_CHECK_EQUAL(h2.get()->getCode(), uint8_t(connection::Tune::CODE)); + connection::Tune& tune=static_cast(*h2.get()); + BOOST_CHECK_EQUAL(tune.channelMax, 1u); + BOOST_CHECK_EQUAL(tune.maxFrameSize, 2u); + BOOST_CHECK_EQUAL(tune.heartbeatMin, 3u); + BOOST_CHECK_EQUAL(tune.heartbeatMax, 4u); +} QPID_AUTO_TEST_SUITE_END() -- cgit v1.2.1