/* * * 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/built_in_types.h" #include "qpid/amqp_0_10/Codec.h" #include "qpid/amqp_0_10/PackedCodec.h" #include "qpid/amqp_0_10/specification.h" #include "qpid/amqp_0_10/ControlHolder.h" #include "qpid/amqp_0_10/Frame.h" #include "qpid/amqp_0_10/Map.h" #include #include #include #include #include #include #include #include #include #include #include // Missing operators needed for tests. namespace boost { template std::ostream& operator<<(std::ostream& out, const array& a) { std::ostream_iterator o(out, " "); std::copy(a.begin(), a.end(), o); return out; } } // boost namespace qpid { namespace sys { std::ostream& operator<<(std::ostream& out, const AbsTime& t) { return out << t.timeValue(); } } } // qpid 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; }; template struct concat4 { typedef typename concat2::type>::type type; }; typedef mpl::vector::type IntegralTypes; typedef mpl::vector::type BinTypes; typedef mpl::vector::type FloatTypes; typedef mpl::vector FixedSizeClassTypes; typedef mpl::vector VariableSizeTypes; typedef concat4::type FixedSizeTypes; typedef concat2::type AllTypes; // TODO aconway 2008-02-20: should test 64 bit integrals for order also. BOOST_AUTO_TEST_CASE(testNetworkByteOrder) { string data; uint32_t l = 0x11223344; 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); uint32_t s2 = ntohs(*reinterpret_cast(data.data())); BOOST_CHECK_EQUAL(s, s2); } BOOST_AUTO_TEST_CASE(testSetLimit) { typedef Codec::Encoder > Encoder; string data; Encoder encode(back_inserter(data), 3); encode('1')('2')('3'); try { encode('4'); BOOST_FAIL("Expected exception"); } catch (...) {} // FIXME aconway 2008-04-03: catch proper exception BOOST_CHECK_EQUAL(data, "123"); } BOOST_AUTO_TEST_CASE(testScopedLimit) { typedef Codec::Encoder > Encoder; string data; Encoder encode(back_inserter(data), 10); encode(Str8("123")); // 4 bytes { Encoder::ScopedLimit l(encode, 3); encode('a')('b')('c'); try { encode('d'); BOOST_FAIL("Expected exception"); } catch(...) {} // FIXME aconway 2008-04-03: catch proper exception } BOOST_CHECK_EQUAL(data, "\003123abc"); encode('x')('y')('z'); try { encode('!'); BOOST_FAIL("Expected exception"); } catch(...) {} // FIXME aconway 2008-04-03: catch proper exception BOOST_CHECK_EQUAL(data.size(), 10u); } // Assign test values to the various types. void testValue(bool& b) { b = true; } void testValue(Bit&) { } template typename boost::enable_if >::type testValue(T& n) { n=42; } void testValue(CharUtf32& c) { c = 43; } void testValue(long long& l) { l = 0x012345; } void testValue(Datetime& dt) { dt = qpid::sys::now(); } void testValue(Uuid& uuid) { uuid=Uuid(true); } template void testValue(Decimal& d) { d.exponent=2; d.mantissa=0x1122; } void testValue(SequenceNo& s) { s = 42; } template void testValue(Bin& a) { a.assign(42); } template void testValue(SerializableString& 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"; } void testValue(Map& m) { m["s"] = Str8("foobar"); m["b"] = true; m["c"] = uint16_t(42); } //typedef mpl::vector::type TestTypes; BOOST_AUTO_TEST_CASE_TEMPLATE(testEncodeDecode, T, AllTypes) { string data; T t; testValue(t); Codec::encode(std::back_inserter(data))(t); BOOST_CHECK_EQUAL(Codec::size(t), data.size()); T 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) const { const_cast(this)->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::Decoder 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); } BOOST_AUTO_TEST_CASE(testFrameEncodeDecode) { static const int overhead=12; string data; Frame r, c; char d1[]="abcdefg"; r.refer(d1, d1+sizeof(d1)); r.setFlags(Frame::FIRST_FRAME); r.setType(CONTROL); r.setChannel(32); r.setTrack(1); char d2[]="01234567"; c.copy(d2, d2+sizeof(d2)); BOOST_CHECK_EQUAL(overhead+sizeof(d1), Codec::size(r)); BOOST_CHECK_EQUAL(overhead+sizeof(d2), Codec::size(c)); Codec::encode(std::back_inserter(data))(r)(c); BOOST_CHECK_EQUAL(data.size(), Codec::size(r)+Codec::size(c)); FrameHeader fh; std::string::iterator i = Codec::decode(data.begin())(fh).pos(); size_t s = fh.size(); BOOST_CHECK_EQUAL(s, sizeof(d1)); BOOST_CHECK_EQUAL(std::string(i, i+s), std::string(d1, d1+s)); Frame f1, f2; Codec::decode(data.begin())(f1)(f2); BOOST_CHECK_EQUAL(f1.size(), sizeof(d1)); BOOST_CHECK_EQUAL(std::string(f1.begin(), f1.size()), std::string(d1, sizeof(d1))); BOOST_CHECK_EQUAL(f1.size(), r.size()); BOOST_CHECK_EQUAL(f1.getFlags(), Frame::FIRST_FRAME); BOOST_CHECK_EQUAL(f1.getType(), CONTROL); BOOST_CHECK_EQUAL(f1.getChannel(), 32); BOOST_CHECK_EQUAL(f1.getTrack(), 1); BOOST_CHECK_EQUAL(f2.size(), c.size()); BOOST_CHECK_EQUAL(std::string(f2.begin(), f2.end()), std::string(d2, d2+sizeof(d2))); } BOOST_AUTO_TEST_CASE(testPackedCodec) { int i=-1, j=-1, k=-1, l=-1; std::string data; Codec::encode(std::back_inserter(data))(1)(3); PackedCodec::decode(0x5, Codec::decode(data.begin()))(i)(j)(k)(l); BOOST_CHECK_EQUAL(i, 1); BOOST_CHECK_EQUAL(j, 0); BOOST_CHECK_EQUAL(k, 3); BOOST_CHECK_EQUAL(l, 0); } QPID_AUTO_TEST_SUITE_END()