qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acon...@apache.org
Subject [2/2] qpid-proton git commit: PROTON-1882: [cpp] cannot send message properties with null values
Date Tue, 03 Jul 2018 15:01:56 GMT
PROTON-1882: [cpp] cannot send message properties with null values

The is_scalar() function was returning false for NULL_TYPE values, so extracting
a null into a proton::scalar threw a conversion_error. Fixed so NULL is now
considered a scalar type.

Also added additional tests for null values, and fixed some missing support for
the C++11 nullptr.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/9e8edc17
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/9e8edc17
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/9e8edc17

Branch: refs/heads/master
Commit: 9e8edc17d444c83175969b55aefe4620ac711fd7
Parents: 2cf4f53
Author: Alan Conway <aconway@redhat.com>
Authored: Fri Jun 29 17:42:15 2018 -0400
Committer: Alan Conway <aconway@redhat.com>
Committed: Tue Jul 3 10:00:51 2018 -0400

----------------------------------------------------------------------
 cpp/include/proton/codec/decoder.hpp        |  3 ++
 cpp/include/proton/internal/type_traits.hpp |  7 ++--
 cpp/include/proton/null.hpp                 |  7 +++-
 cpp/include/proton/scalar_base.hpp          |  7 ++++
 cpp/include/proton/type_id.hpp              | 13 ++++++-
 cpp/include/proton/value.hpp                |  5 +++
 cpp/src/codec_test.cpp                      |  1 +
 cpp/src/decoder.cpp                         |  8 +++++
 cpp/src/scalar_base.cpp                     |  9 ++++-
 cpp/src/value_test.cpp                      | 43 +++++++++++++++++++-----
 10 files changed, 88 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/include/proton/codec/decoder.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/codec/decoder.hpp b/cpp/include/proton/codec/decoder.hpp
index 5f587ff..243d105 100644
--- a/cpp/include/proton/codec/decoder.hpp
+++ b/cpp/include/proton/codec/decoder.hpp
@@ -113,6 +113,9 @@ class decoder : public internal::data {
     PN_CPP_EXTERN decoder& operator>>(scalar&);
     PN_CPP_EXTERN decoder& operator>>(internal::value_base&);
     PN_CPP_EXTERN decoder& operator>>(null&);
+#if PN_CPP_HAS_NULLPTR
+    PN_CPP_EXTERN decoder& operator>>(decltype(nullptr)&);
+#endif
     ///@}
 
     /// Start decoding a container type, such as an ARRAY, LIST or

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/include/proton/internal/type_traits.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/internal/type_traits.hpp b/cpp/include/proton/internal/type_traits.hpp
index 3f2a257..c8b6bd0 100644
--- a/cpp/include/proton/internal/type_traits.hpp
+++ b/cpp/include/proton/internal/type_traits.hpp
@@ -93,6 +93,10 @@ template <type_id ID, class T> struct type_id_constant {
 /// @name Metafunction returning AMQP type for scalar C++ types.
 /// @{
 template <class T> struct type_id_of;
+template<> struct type_id_of<null> : public type_id_constant<NULL_TYPE, null>
{};
+#if PN_CPP_HAS_NULLPTR
+template<> struct type_id_of<decltype(nullptr)> : public type_id_constant<NULL_TYPE,
null> {};
+#endif
 template<> struct type_id_of<bool> : public type_id_constant<BOOLEAN, bool>
{};
 template<> struct type_id_of<uint8_t> : public type_id_constant<UBYTE, uint8_t>
{};
 template<> struct type_id_of<int8_t> : public type_id_constant<BYTE, int8_t>
{};
@@ -113,9 +117,6 @@ template<> struct type_id_of<uuid> : public type_id_constant<UUID,
uuid> {};
 template<> struct type_id_of<std::string> : public type_id_constant<STRING,
std::string> {};
 template<> struct type_id_of<symbol> : public type_id_constant<SYMBOL, symbol>
{};
 template<> struct type_id_of<binary> : public type_id_constant<BINARY, binary>
{};
-#if PN_CPP_HAS_NULLPTR
-template<> struct type_id_of<decltype(nullptr)> : public type_id_constant<NULL_TYPE,
null> {};
-#endif
 /// @}
 
 /// Metafunction to test if a class has a type_id.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/include/proton/null.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/null.hpp b/cpp/include/proton/null.hpp
index 144ba33..cb39325 100644
--- a/cpp/include/proton/null.hpp
+++ b/cpp/include/proton/null.hpp
@@ -26,6 +26,7 @@
 /// @copybrief proton::null
 
 #include "./internal/config.hpp"
+#include "./internal/comparable.hpp"
 #include "./internal/export.hpp"
 
 #include <iosfwd>
@@ -35,13 +36,17 @@ namespace proton {
 /// The type of the AMQP null value
 ///
 /// @see @ref types_page
-class null {
+class null : private internal::comparable<null> {
   public:
     null() {}
 #if PN_CPP_HAS_NULLPTR
     /// Constructed from nullptr literal
     null(decltype(nullptr)) {}
 #endif
+    // null instances are always equal
+  friend bool operator==(const null&, const null&) { return true; }
+    // null instances are never unequal
+  friend bool operator<(const null&, const null&) { return false; }
 };
 
 /// Print a null value

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/include/proton/scalar_base.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/scalar_base.hpp b/cpp/include/proton/scalar_base.hpp
index c88f0a8..7e7c8d1 100644
--- a/cpp/include/proton/scalar_base.hpp
+++ b/cpp/include/proton/scalar_base.hpp
@@ -100,6 +100,9 @@ class scalar_base : private internal::comparable<scalar_base> {
     PN_CPP_EXTERN void put_(const binary&);
     PN_CPP_EXTERN void put_(const char* s); ///< Treated as an AMQP string
     PN_CPP_EXTERN void put_(const null&);
+#if PN_CPP_HAS_NULLPTR
+    PN_CPP_EXTERN void put_(decltype(nullptr));
+#endif
 
     template<class T> void put(const T& x) { putter<T>::put(*this, x); }
 
@@ -125,6 +128,10 @@ class scalar_base : private internal::comparable<scalar_base> {
     PN_CPP_EXTERN void get_(symbol&) const;
     PN_CPP_EXTERN void get_(binary&) const;
     PN_CPP_EXTERN void get_(null&) const;
+#if PN_CPP_HAS_NULLPTR
+    PN_CPP_EXTERN void get_(decltype(nullptr)&) const;
+#endif
+
 
     // use template structs, functions cannot be  partially specialized.
     template <class T, class Enable=void> struct putter {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/include/proton/type_id.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/type_id.hpp b/cpp/include/proton/type_id.hpp
index 2cca6f3..4c0e7b9 100644
--- a/cpp/include/proton/type_id.hpp
+++ b/cpp/include/proton/type_id.hpp
@@ -82,8 +82,19 @@ inline bool type_id_is_decimal(type_id t) { return t == DECIMAL32 || t
== DECIMA
 inline bool type_id_is_signed(type_id t) { return type_id_is_signed_int(t) || type_id_is_floating_point(t)
|| type_id_is_decimal(t); }
 inline bool type_id_is_string_like(type_id t) { return t == BINARY || t == STRING || t ==
SYMBOL; }
 inline bool type_id_is_container(type_id t) { return t == LIST || t == MAP || t == ARRAY
|| t == DESCRIBED; }
-inline bool type_id_is_scalar(type_id t) { return type_id_is_integral(t) || type_id_is_floating_point(t)
|| type_id_is_decimal(t) || type_id_is_string_like(t) || t == TIMESTAMP || t == UUID; }
+
 inline bool type_id_is_null(type_id t) { return t == NULL_TYPE; }
+
+inline bool type_id_is_scalar(type_id t) {
+    return type_id_is_integral(t) ||
+        type_id_is_floating_point(t) ||
+        type_id_is_decimal(t) ||
+        type_id_is_string_like(t) ||
+        type_id_is_null(t) ||
+        t == TIMESTAMP ||
+        t == UUID;
+}
+
 /// }
 
 } // proton

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/include/proton/value.hpp
----------------------------------------------------------------------
diff --git a/cpp/include/proton/value.hpp b/cpp/include/proton/value.hpp
index 979881e..ee50cbf 100644
--- a/cpp/include/proton/value.hpp
+++ b/cpp/include/proton/value.hpp
@@ -159,6 +159,11 @@ template<class T> void coerce(const value& v, T& x) {
 template<> inline void get<null>(const value& v, null&) {
     assert_type_equal(NULL_TYPE, v.type());
 }
+#if PN_CPP_HAS_NULLPTR
+template<> inline void get<decltype(nullptr)>(const value& v, decltype(nullptr)&)
{
+    assert_type_equal(NULL_TYPE, v.type());
+}
+#endif
 
 /// Return a readable string representation of x for display purposes.
 PN_CPP_EXTERN std::string to_string(const value& x);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/src/codec_test.cpp
----------------------------------------------------------------------
diff --git a/cpp/src/codec_test.cpp b/cpp/src/codec_test.cpp
index df89dc3..015a64a 100644
--- a/cpp/src/codec_test.cpp
+++ b/cpp/src/codec_test.cpp
@@ -53,6 +53,7 @@ int main(int, char**) {
     int failed = 0;
 
     // Basic AMQP types
+    RUN_TEST(failed, simple_type_test(null()));
     RUN_TEST(failed, simple_type_test(false));
     RUN_TEST(failed, simple_type_test(uint8_t(42)));
     RUN_TEST(failed, simple_type_test(int8_t(-42)));

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/src/decoder.cpp
----------------------------------------------------------------------
diff --git a/cpp/src/decoder.cpp b/cpp/src/decoder.cpp
index 9c941c8..9a5ace3 100644
--- a/cpp/src/decoder.cpp
+++ b/cpp/src/decoder.cpp
@@ -141,6 +141,14 @@ decoder& decoder::operator>>(null&) {
     return *this;
 }
 
+#if PN_CPP_HAS_NULLPTR
+decoder& decoder::operator>>(decltype(nullptr)&) {
+    internal::state_guard sg(*this);
+    assert_type_equal(NULL_TYPE, pre_get());
+    return *this;
+}
+#endif
+
 decoder& decoder::operator>>(internal::value_base& x) {
     if (*this == x.data_)
         throw conversion_error("extract into self");

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/src/scalar_base.cpp
----------------------------------------------------------------------
diff --git a/cpp/src/scalar_base.cpp b/cpp/src/scalar_base.cpp
index 0d66cdc..d18a272 100644
--- a/cpp/src/scalar_base.cpp
+++ b/cpp/src/scalar_base.cpp
@@ -84,6 +84,10 @@ void scalar_base::put_(const symbol& x) { set(binary(x), PN_SYMBOL);
}
 void scalar_base::put_(const binary& x) { set(x, PN_BINARY); }
 void scalar_base::put_(const char* x) { set(binary(std::string(x)), PN_STRING); }
 void scalar_base::put_(const null&) { atom_.type = PN_NULL; }
+#if PN_CPP_HAS_NULLPTR
+void scalar_base::put_(decltype(nullptr)) { atom_.type = PN_NULL; }
+#endif
+
 
 void scalar_base::ok(pn_type_t t) const {
     if (atom_.type != t) throw make_conversion_error(type_id(t), type());
@@ -110,6 +114,9 @@ void scalar_base::get_(std::string& x) const { ok(PN_STRING); x =
std::string(by
 void scalar_base::get_(symbol& x) const { ok(PN_SYMBOL); x = symbol(bytes_.begin(), bytes_.end());
}
 void scalar_base::get_(binary& x) const { ok(PN_BINARY); x = bytes_; }
 void scalar_base::get_(null&) const { ok(PN_NULL); }
+#if PN_CPP_HAS_NULLPTR
+void scalar_base::get_(decltype(nullptr)&) const { ok(PN_NULL); }
+#endif
 
 namespace {
 
@@ -147,7 +154,7 @@ bool operator<(const scalar_base& x, const scalar_base& y)
{
 
 std::ostream& operator<<(std::ostream& o, const scalar_base& s) {
     switch (s.type()) {
-      case NULL_TYPE: return o << "<null>";
+      case NULL_TYPE: return o << "null";
       case BYTE: return o << static_cast<int>(internal::get<int8_t>(s));
       case UBYTE: return o << static_cast<unsigned int>(internal::get<uint8_t>(s));
         // Other types printed using normal C++ operator <<

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9e8edc17/cpp/src/value_test.cpp
----------------------------------------------------------------------
diff --git a/cpp/src/value_test.cpp b/cpp/src/value_test.cpp
index 5e2fab6..5e3eefd 100644
--- a/cpp/src/value_test.cpp
+++ b/cpp/src/value_test.cpp
@@ -76,25 +76,50 @@ template <class T, class U> void map_test(const U& values, const
string& s) {
         ASSERT_EQUAL(s, to_string(v));
 }
 
-#if PN_CPP_HAS_CPP11
 void null_test() {
-    auto n = null();
-    proton::value nn = nullptr;
-    ASSERT_EQUAL(n, nn);
-    ASSERT_EQUAL("null", to_string(nn));
+    proton::null n;
     ASSERT_EQUAL("null", to_string(n));
-    std::vector<proton::value> nulls = {nullptr, null{}};
+
+    std::vector<proton::value> nulls(2, n);
     ASSERT_EQUAL("[null, null]", to_string(nulls));
 
-    std::vector<std::nullptr_t> nulls1 = {nullptr, nullptr};
+    std::vector<proton::null> nulls1(2, n);
     ASSERT_EQUAL("@PN_NULL[null, null]", to_string(nulls1));
 
-    std::vector<proton::value> vs = {nullptr, nulls, nulls1};
+    std::vector<proton::value> vs;
+    vs.push_back(n);
+    vs.push_back(nulls);
+    vs.push_back(nulls1);
     ASSERT_EQUAL("[null, [null, null], @PN_NULL[null, null]]", to_string(vs));
-}
+
+    std::map<proton::value, proton::value> vm;
+    vm[n] = 1;
+    vm[nulls1] = 2;
+    vm[nulls] = 3;
+    // FIXME aconway 2018-06-29: note different types compare by type-id,
+    // so NULL < ARRAY < LIST
+    ASSERT_EQUAL("{null=1, @PN_NULL[null, null]=2, [null, null]=3}", to_string(vm));
+
+    std::map<proton::scalar, proton::scalar> vm2;
+    vm2[n] = 1;                 // Different types compare by type-id, NULL is smallest
+    vm2[2] = n;
+    ASSERT_EQUAL("{null=1, 2=null}", to_string(vm2));
+
+#if PN_CPP_HAS_CPP11
+    proton::value nn = nullptr;
+    ASSERT(n == nn);            // Don't use ASSERT_EQUAL, it will try to print
+    ASSERT_EQUAL("null", to_string(nn));
+    std::vector<std::nullptr_t> nulls2 {nullptr, nullptr};
+    ASSERT_EQUAL("@PN_NULL[null, null]", to_string(nulls2));
+    std::map<proton::scalar, proton::scalar> m {{nullptr, nullptr}};
+    ASSERT_EQUAL("{null=null}", to_string(m));
+    std::map<proton::value, proton::value> m2 {{nullptr, nullptr}};
+    ASSERT_EQUAL("{null=null}", to_string(m2));
 #endif
 }
 
+}
+
 int main(int, char**) {
     try {
         int failed = 0;


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


Mime
View raw message