You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kg...@apache.org on 2020/08/31 18:44:41 UTC

[qpid-dispatch] branch master updated: DISPATCH-1765: add streaming links to offered-capabilities

This is an automated email from the ASF dual-hosted git repository.

kgiusti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git


The following commit(s) were added to refs/heads/master by this push:
     new c5928aa  DISPATCH-1765: add streaming links to offered-capabilities
c5928aa is described below

commit c5928aadc4ab70d209042727514147e9e7c928d6
Author: Kenneth Giusti <kg...@redhat.com>
AuthorDate: Fri Aug 28 08:55:30 2020 -0400

    DISPATCH-1765: add streaming links to offered-capabilities
    
    This closes #829
---
 include/qpid/dispatch/amqp.h          |   1 +
 include/qpid/dispatch/router_core.h   |  28 +------
 src/amqp.c                            |   1 +
 src/router_core/connections.c         |  12 +--
 src/router_core/forwarder.c           |  20 +----
 src/router_core/router_core_private.h |   5 +-
 src/router_node.c                     |  50 +++++++-----
 src/server.c                          |  27 ++++++-
 tests/CMakeLists.txt                  |   1 -
 tests/run_unit_tests.c                |   1 -
 tests/system_tests_edge_router.py     |  46 +----------
 tests/system_tests_one_router.py      |  62 ++++++++++++++-
 tests/version_test.c                  | 146 ----------------------------------
 13 files changed, 131 insertions(+), 269 deletions(-)

diff --git a/include/qpid/dispatch/amqp.h b/include/qpid/dispatch/amqp.h
index 541b16b..aca440c 100644
--- a/include/qpid/dispatch/amqp.h
+++ b/include/qpid/dispatch/amqp.h
@@ -128,6 +128,7 @@ extern const int          QD_MA_FILTER_LEN;   ///< size of annotation filter buf
 /** @name Container Capabilities */
 /// @{
 extern const char * const QD_CAPABILITY_ANONYMOUS_RELAY;
+extern const char * const QD_CAPABILITY_STREAMING_LINKS;
 /// @}
 
 /** @name Link Terminus Capabilities */
diff --git a/include/qpid/dispatch/router_core.h b/include/qpid/dispatch/router_core.h
index 14336d6..a6dd54d 100644
--- a/include/qpid/dispatch/router_core.h
+++ b/include/qpid/dispatch/router_core.h
@@ -870,30 +870,6 @@ void qdr_query_free(qdr_query_t *query);
 typedef void (*qdr_manage_response_t) (void *context, const qd_amqp_error_t *status, bool more);
 void qdr_manage_handler(qdr_core_t *core, qdr_manage_response_t response_handler);
 
-typedef struct {
-    uint16_t major;
-    uint16_t minor;
-    uint16_t patch;
-    uint16_t flags;
-#define QDR_ROUTER_VERSION_SNAPSHOT 0x0100
-#define QDR_ROUTER_VERSION_RC       0x0200  // lower byte == RC #
-#define QDR_ROUTER_VERSION_RC_MASK  0x00FF
-} qdr_router_version_t;
-
-// version >= (Major, Minor, Patch)
-#define QDR_ROUTER_VERSION_AT_LEAST(V, MAJOR, MINOR, PATCH)                       \
-    ((V).major > (MAJOR) || ((V).major == (MAJOR)                                 \
-                             && ((V).minor > (MINOR) || ((V).minor == (MINOR)     \
-                                                         && (V).patch >= (PATCH)) \
-                             )                                                    \
-                        )                                                         \
-    )
-
-// version < (Major, Minor, Patch)
-#define QDR_ROUTER_VERSION_LESS_THAN(V, MAJOR, MINOR, PATCH)    \
-    (!QDR_ROUTER_VERSION_AT_LEAST(V, MAJOR, MINOR, PATCH))
-
-
 qdr_connection_info_t *qdr_connection_info(bool             is_encrypted,
                                            bool             is_authenticated,
                                            bool             opened,
@@ -907,8 +883,8 @@ qdr_connection_info_t *qdr_connection_info(bool             is_encrypted,
                                            pn_data_t       *connection_properties,
                                            int              ssl_ssf,
                                            bool             ssl,
-                                           // set if remote is a qdrouter
-                                           const qdr_router_version_t *version);
+                                           const char      *version_str,  // if remote is a router
+                                           bool             streaming_links);
 
 
 typedef struct {
diff --git a/src/amqp.c b/src/amqp.c
index 97aec78..0dab017 100644
--- a/src/amqp.c
+++ b/src/amqp.c
@@ -49,6 +49,7 @@ const char * const QD_CAPABILITY_WAYPOINT8        = "qd.waypoint.8";
 const char * const QD_CAPABILITY_WAYPOINT9        = "qd.waypoint.9";
 const char * const QD_CAPABILITY_FALLBACK         = "qd.fallback";
 const char * const QD_CAPABILITY_ANONYMOUS_RELAY  = "ANONYMOUS-RELAY";
+const char * const QD_CAPABILITY_STREAMING_LINKS  = "qd.streaming-links";
 
 const char * const QD_DYNAMIC_NODE_PROPERTY_ADDRESS = "x-opt-qd.address";
 
diff --git a/src/router_core/connections.c b/src/router_core/connections.c
index 850fcbd..d88b7c1 100644
--- a/src/router_core/connections.c
+++ b/src/router_core/connections.c
@@ -163,7 +163,8 @@ qdr_connection_info_t *qdr_connection_info(bool             is_encrypted,
                                            pn_data_t       *connection_properties,
                                            int              ssl_ssf,
                                            bool             ssl,
-                                           const qdr_router_version_t *version)
+                                           const char      *version,
+                                           bool             streaming_links)
 {
     qdr_connection_info_t *connection_info = new_qdr_connection_info_t();
     ZERO(connection_info);
@@ -184,6 +185,8 @@ qdr_connection_info_t *qdr_connection_info(bool             is_encrypted,
         connection_info->ssl_cipher = strdup(ssl_cipher);
     if (user)
         connection_info->user = strdup(user);
+    if (version)
+        connection_info->version = strdup(version);
 
     pn_data_t *qdr_conn_properties = pn_data(0);
     pn_data_copy(qdr_conn_properties, connection_properties);
@@ -191,11 +194,7 @@ qdr_connection_info_t *qdr_connection_info(bool             is_encrypted,
     connection_info->connection_properties = qdr_conn_properties;
     connection_info->ssl_ssf = ssl_ssf;
     connection_info->ssl     = ssl;
-
-    if (version) {  // only if peer is a router
-        connection_info->version = *version;
-    }
-
+    connection_info->streaming_links = streaming_links;
     return connection_info;
 }
 
@@ -208,6 +207,7 @@ static void qdr_connection_info_free(qdr_connection_info_t *ci)
     free(ci->ssl_proto);
     free(ci->ssl_cipher);
     free(ci->user);
+    free(ci->version);
     pn_data_free(ci->connection_properties);
     free_qdr_connection_info_t(ci);
 }
diff --git a/src/router_core/forwarder.c b/src/router_core/forwarder.c
index 0dcc086..37cb442 100644
--- a/src/router_core/forwarder.c
+++ b/src/router_core/forwarder.c
@@ -66,20 +66,6 @@ static inline qdr_link_t *peer_router_data_link(qdr_core_t *core,
 }
 
 
-// Returns true if the peer router can support this router opening additional incoming links dedicated for streaming messages
-//
-static inline bool next_hop_supports_streaming_links(const qdr_connection_t *conn)
-{
-    if (conn->role == QDR_ROLE_EDGE_CONNECTION)
-        return true;
-    if (conn->role == QDR_ROLE_INTER_ROUTER) {
-        return QDR_ROUTER_VERSION_AT_LEAST(conn->connection_info->version,
-                                           1, 13, 0);
-    }
-    return false;
-}
-
-
 // Get an idle anonymous link for a streaming message. This link will come from
 // either the connections free link pool or it will be dynamically created on
 // the given connection.
@@ -431,7 +417,7 @@ int qdr_forward_multicast_CT(qdr_core_t      *core,
             //
             if (!qdr_forward_edge_echo_CT(in_delivery, out_link)) {
 
-                if (!receive_complete && next_hop_supports_streaming_links(out_link->conn)) {
+                if (!receive_complete && out_link->conn->connection_info->streaming_links) {
                     out_link = get_outgoing_streaming_link(core, out_link->conn);
                 }
 
@@ -620,7 +606,7 @@ int qdr_forward_closest_CT(qdr_core_t      *core,
     if (link_ref) {
         qdr_link_t *out_link = link_ref->link;
 
-        if (!receive_complete && next_hop_supports_streaming_links(out_link->conn)) {
+        if (!receive_complete && out_link->conn->connection_info->streaming_links) {
             out_link = get_outgoing_streaming_link(core, out_link->conn);
         }
 
@@ -844,7 +830,7 @@ int qdr_forward_balanced_CT(qdr_core_t      *core,
 
         // DISPATCH-1545 (head of line blocking): if the message is streaming,
         // see if the allows us to open a dedicated link for streaming
-        if (!qd_message_receive_complete(msg) && next_hop_supports_streaming_links(chosen_link->conn)) {
+        if (!qd_message_receive_complete(msg) && chosen_link->conn->connection_info->streaming_links) {
             chosen_link = get_outgoing_streaming_link(core, chosen_link->conn);
             if (!chosen_link)
                 return 0;
diff --git a/src/router_core/router_core_private.h b/src/router_core/router_core_private.h
index 707d5f2..21638d0 100644
--- a/src/router_core/router_core_private.h
+++ b/src/router_core/router_core_private.h
@@ -623,18 +623,19 @@ struct qdr_connection_info_t {
     char                       *container;
     char                       *sasl_mechanisms;
     char                       *host;
-    bool                        is_encrypted;
     char                       *ssl_proto;
     char                       *ssl_cipher;
     char                       *user;
     bool                        is_authenticated;
+    bool                        is_encrypted;
     bool                        opened;
+    bool                        streaming_links;  // will allow streaming links
     qd_direction_t              dir;
     qdr_connection_role_t       role;
     pn_data_t                  *connection_properties;
     bool                        ssl;
     int                         ssl_ssf; //ssl strength factor
-    qdr_router_version_t        version; // if role is router or edge
+    char                       *version; // if role is router or edge
 };
 
 ALLOC_DECLARE(qdr_connection_info_t);
diff --git a/src/router_node.c b/src/router_node.c
index 4fdf3ad..2cfb3fb 100644
--- a/src/router_node.c
+++ b/src/router_node.c
@@ -1050,9 +1050,9 @@ static void AMQP_opened_handler(qd_router_t *router, qd_connection_t *conn, bool
     int                    link_capacity = 1;
     const char            *name = 0;
     bool                   multi_tenant = false;
+    bool                   streaming_links = false;
     const char            *vhost = 0;
-    qdr_router_version_t   rversion = {0};
-    bool                   rversion_found = false;
+    char                   rversion[128];
     uint64_t               connection_id = qd_connection_connection_id(conn);
     pn_connection_t       *pn_conn = qd_connection_pn(conn);
     pn_transport_t *tport = 0;
@@ -1061,6 +1061,8 @@ static void AMQP_opened_handler(qd_router_t *router, qd_connection_t *conn, bool
     const char     *mech  = 0;
     const char     *user  = 0;
     const char *container = conn->pn_conn ? pn_connection_remote_container(conn->pn_conn) : 0;
+
+    rversion[0] = 0;
     conn->strip_annotations_in  = false;
     conn->strip_annotations_out = false;
     if (conn->pn_conn) {
@@ -1093,6 +1095,27 @@ static void AMQP_opened_handler(qd_router_t *router, qd_connection_t *conn, bool
     qd_router_connection_get_config(conn, &role, &cost, &name, &multi_tenant,
                                     &conn->strip_annotations_in, &conn->strip_annotations_out, &link_capacity);
 
+    // check offered capabilities for streaming link support
+    //
+    pn_data_t *ocaps = pn_connection_remote_offered_capabilities(pn_conn);
+    if (ocaps) {
+        size_t sl_len = strlen(QD_CAPABILITY_STREAMING_LINKS);
+        pn_data_rewind(ocaps);
+        if (pn_data_next(ocaps)) {
+            if (pn_data_type(ocaps) == PN_ARRAY) {
+                pn_data_enter(ocaps);
+                pn_data_next(ocaps);
+            }
+            do {
+                if (pn_data_type(ocaps) == PN_SYMBOL) {
+                    pn_bytes_t s = pn_data_get_symbol(ocaps);
+                    streaming_links = (s.size == sl_len
+                                       && strncmp(s.start, QD_CAPABILITY_STREAMING_LINKS, sl_len) == 0);
+                }
+            } while (pn_data_next(ocaps) && !streaming_links);
+        }
+    }
+
     // if connection properties are present parse out any important data
     //
     pn_data_t *props = pn_conn ? pn_connection_remote_properties(pn_conn) : 0;
@@ -1132,23 +1155,9 @@ static void AMQP_opened_handler(qd_router_t *router, qd_connection_t *conn, bool
                     if (!pn_data_next(props)) break;
                     if (is_router) {
                         pn_bytes_t vdata = pn_data_get_string(props);
-                        if (vdata.size < 64) {  // > strlen("u16.u16.u16-SNAPSHOT")
-                            char vstr[64];
-                            memcpy(vstr, vdata.start, vdata.size);
-                            vstr[vdata.size] = 0;
-                            int rc = sscanf(vstr, "%"SCNu16".%"SCNu16".%"SCNu16,
-                                            &rversion.major,
-                                            &rversion.minor,
-                                            &rversion.patch);
-                            if (strstr(vstr, "SNAPSHOT")) {
-                                rversion.flags = QDR_ROUTER_VERSION_SNAPSHOT;
-                            }
-                            rversion_found = rc == 3;
-                            if (rversion_found) {
-                                qd_log(router->log_source, QD_LOG_DEBUG, "[C%"PRIu64"] Peer router version: %u.%u.%u%s",
-                                       connection_id, rversion.major, rversion.minor, rversion.patch, (rversion.flags) ? "-SNAPSHOT" : "");
-                            }
-                        }
+                        size_t vlen = MIN(sizeof(rversion) - 1, vdata.size);
+                        strncpy(rversion, vdata.start, vlen);
+                        rversion[vlen] = 0;
                     }
 
                 } else {
@@ -1197,7 +1206,8 @@ static void AMQP_opened_handler(qd_router_t *router, qd_connection_t *conn, bool
                                                                  props,
                                                                  ssl_ssf,
                                                                  is_ssl,
-                                                                 (rversion_found) ? &rversion : 0);
+                                                                 rversion,
+                                                                 streaming_links);
 
     qdr_connection_opened(router->router_core, inbound, role, cost, connection_id, name,
                           pn_connection_remote_container(pn_conn),
diff --git a/src/server.c b/src/server.c
index 27505b7..0eee2b5 100644
--- a/src/server.c
+++ b/src/server.c
@@ -433,17 +433,36 @@ static qd_error_t listener_setup_ssl(qd_connection_t *ctx, const qd_server_confi
 
 static void decorate_connection(qd_server_t *qd_server, pn_connection_t *conn, const qd_server_config_t *config)
 {
-    size_t clen = strlen(QD_CAPABILITY_ANONYMOUS_RELAY);
-
     //
     // Set the container name
     //
     pn_connection_set_container(conn, qd_server->container_name);
 
     //
-    // Offer ANONYMOUS_RELAY capability
+    // Advertise our container capabilities.
     //
-    pn_data_put_symbol(pn_connection_offered_capabilities(conn), pn_bytes(clen, (char*) QD_CAPABILITY_ANONYMOUS_RELAY));
+    {
+        // offered: extension capabilities this router supports
+        pn_data_t *ocaps = pn_connection_offered_capabilities(conn);
+        pn_data_put_array(ocaps, false, PN_SYMBOL);
+        pn_data_enter(ocaps);
+        pn_data_put_symbol(ocaps, pn_bytes(strlen(QD_CAPABILITY_ANONYMOUS_RELAY), (char*) QD_CAPABILITY_ANONYMOUS_RELAY));
+        pn_data_put_symbol(ocaps, pn_bytes(strlen(QD_CAPABILITY_STREAMING_LINKS), (char*) QD_CAPABILITY_STREAMING_LINKS));
+        pn_data_exit(ocaps);
+
+        // The desired-capability list defines which extension capabilities the
+        // sender MAY use if the receiver offers them (i.e., they are in the
+        // offered-capabilities list received by the sender of the
+        // desired-capabilities). The sender MUST NOT attempt to use any
+        // capabilities it did not declare in the desired-capabilities
+        // field.
+        ocaps = pn_connection_desired_capabilities(conn);
+        pn_data_put_array(ocaps, false, PN_SYMBOL);
+        pn_data_enter(ocaps);
+        pn_data_put_symbol(ocaps, pn_bytes(strlen(QD_CAPABILITY_ANONYMOUS_RELAY), (char*) QD_CAPABILITY_ANONYMOUS_RELAY));
+        pn_data_put_symbol(ocaps, pn_bytes(strlen(QD_CAPABILITY_STREAMING_LINKS), (char*) QD_CAPABILITY_STREAMING_LINKS));
+        pn_data_exit(ocaps);
+    }
 
     //
     // Create the connection properties map
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index e00ed84..2f0f4b7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -36,7 +36,6 @@ set(unit_test_SOURCES
     parse_tree_tests.c
     proton_utils_tests.c
     alloc_test.c
-    version_test.c
     hash_test.c
     thread_test.c
     )
diff --git a/tests/run_unit_tests.c b/tests/run_unit_tests.c
index be4c1b7..dfe72c1 100644
--- a/tests/run_unit_tests.c
+++ b/tests/run_unit_tests.c
@@ -67,7 +67,6 @@ int main(int argc, char** argv)
     result += parse_tree_tests();
     result += proton_utils_tests();
     result += core_timer_tests();
-    result += version_tests();
     result += hash_tests();
     result += thread_tests();
 
diff --git a/tests/system_tests_edge_router.py b/tests/system_tests_edge_router.py
index 212d3ef..2ee7111 100644
--- a/tests/system_tests_edge_router.py
+++ b/tests/system_tests_edge_router.py
@@ -1643,51 +1643,6 @@ class LinkRouteProxyTest(TestCase):
             tr.queue.get(timeout=TIMEOUT)
         tr.stop()
 
-    def test_000_check_peer_version_info(self):
-        """
-        Not a link proxy test - ensure router correctly parses peer version
-        numbers advertised in the incoming @open frame
-        """
-        lines = None
-        with open(os.path.join(self.INT_A.outdir, "INT.A.log")) as inta_log:
-            lines = [l for l in inta_log.read().split("\n")
-                     if "] Connection Opened: " in l
-                     or "] Peer router version: " in l]
-
-        self.assertTrue(lines is not None)
-
-        for peer in ['INT.B', 'EA1']:
-
-            conn_id = None
-            open_version = None
-            parsed_version = None
-
-            # extract the version string from the incoming @open
-            for l in lines:
-                ls = l.split()
-                if "container_id=%s" % peer in ls:
-                    conn_id = ls[5]
-                    for f in ls:
-                        index = f.find(':version=')
-                        if index >= 0:
-                            open_version = f[index + len(':version='):].strip("\",")
-                            break;
-                    break;
-
-            self.assertTrue(conn_id is not None)
-            self.assertTrue(open_version is not None)
-
-            # find the debug log message where the router logs the parsed peers
-            # version on the given connection
-            for l in lines:
-                ls = l.split()
-                if ls[5] == conn_id and "version:" in ls:
-                    parsed_version = ls[9]
-                    break;
-
-            self.assertTrue(parsed_version is not None)
-            self.assertEqual(open_version, parsed_version)
-
     def test_01_immedate_detach_reattach(self):
         if self.skip [ 'test_01' ] :
             self.skipTest ( "Test skipped during development." )
@@ -3419,5 +3374,6 @@ class StreamingMessageTest(TestCase):
         self._wait_address_gone(self.INT_A,  "balanced/test-address")
         self._wait_address_gone(self.INT_B,  "balanced/test-address")
 
+
 if __name__== '__main__':
     unittest.main(main_module())
diff --git a/tests/system_tests_one_router.py b/tests/system_tests_one_router.py
index e349918..ee1980c 100644
--- a/tests/system_tests_one_router.py
+++ b/tests/system_tests_one_router.py
@@ -29,7 +29,7 @@ from proton.reactor import Container, AtMostOnce, AtLeastOnce
 from proton.utils import BlockingConnection, SyncRequestResponse
 from proton import VERSION as PROTON_VERSION
 from proton import Terminus
-from proton import Data
+from proton import Data, symbol
 from qpid_dispatch.management.client import Node, BadRequestStatus
 import os, json
 from subprocess import PIPE, STDOUT
@@ -734,6 +734,31 @@ class OneRouterTest(TestCase):
         test.run()
         self.assertEqual(None, test.error)
 
+    def test_50_extension_capabilities(self):
+        """
+        Test clients sending different offered capability values.  Verify the
+        expected offered and desired capabilities sent by the router
+        """
+        client_caps = [symbol("single"),
+                       ["A", "B", "C"],
+                       [9, 10, 11],
+                       [],
+                       None]
+
+        for cc in client_caps:
+            test = ExtensionCapabilitiesTest(self.address, cc)
+            test.run()
+            self.assertEqual(None, test.error)
+
+            # check the caps sent by router.
+            self.assertTrue(test.remote_offered is not None)
+            self.assertTrue(test.remote_desired is not None)
+            ro = [c for c in test.remote_offered]
+            rd = [c for c in test.remote_desired]
+            for rc in [ro, rd]:
+                self.assertTrue(symbol('ANONYMOUS-RELAY') in rc)
+                self.assertTrue(symbol('qd.streaming-links') in rc)
+
 
 class Entity(object):
     def __init__(self, status_code, status_description, attrs):
@@ -787,6 +812,41 @@ class ReleasedChecker(object):
     def on_timer_task(self, event):
         self.parent.released_check_timeout()
 
+
+class ExtensionCapabilitiesTest(MessagingHandler):
+    def __init__(self, address, capabilities):
+        """
+        capabilities: sent by this client to the router
+        """
+        super(ExtensionCapabilitiesTest, self).__init__()
+        self._addr = address
+        self._caps = capabilities
+        self._timer = None
+        self._conn = None
+        self.remote_offered = None
+        self.remote_desired = None
+        self.error = None
+
+    def on_start(self, event):
+        self._timer = event.reactor.schedule(TIMEOUT, TestTimeout(self))
+        self._conn = event.container.connect(self._addr,
+                                             offered_capabilities=self._caps,
+                                             desired_capabilities=self._caps)
+    def timeout(self):
+        self.error = "Timeout Expired: connection failed"
+        if self._conn:
+            self._conn.close()
+
+    def on_connection_opened(self, event):
+        self.remote_offered = event.connection.remote_offered_capabilities
+        self.remote_desired = event.connection.remote_desired_capabilities
+        self._timer.cancel()
+        self._conn.close()
+
+    def run(self):
+        Container(self).run()
+
+
 class UnexpectedReleaseTest(MessagingHandler):
     def __init__(self, address):
         super(UnexpectedReleaseTest, self).__init__(auto_accept=False)
diff --git a/tests/version_test.c b/tests/version_test.c
deleted file mode 100644
index 494c411..0000000
--- a/tests/version_test.c
+++ /dev/null
@@ -1,146 +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 <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include "test_case.h"
-#include <qpid/dispatch/router_core.h>
-
-typedef struct {
-    qdr_router_version_t version;
-    uint16_t major;
-    uint16_t minor;
-    uint16_t patch;
-    bool   expected;
-} test_data_t;
-
-static const test_data_t data[] = {
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 10,
-        .minor = 11,
-        .patch = 12,
-        .expected = true,
-    },
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 10,
-        .minor = 11,
-        .patch = 13,
-        .expected = false,
-    },
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 10,
-        .minor = 12,
-        .patch = 0,
-        .expected = false,
-    },
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 11,
-        .minor = 0,
-        .patch = 0,
-        .expected = false,
-    },
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 10,
-        .minor = 11,
-        .patch = 11,
-        .expected = true,
-    },
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 10,
-        .minor = 10,
-        .patch = 13,
-        .expected = true,
-    },
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 9,
-        .minor = 12,
-        .patch = 13,
-        .expected = true,
-    },
-    {
-        .version = {.major = 10,
-                    .minor = 11,
-                    .patch = 12},
-        .major = 0,
-        .minor = 0,
-        .patch = 0,
-        .expected = true,
-    },
-};
-const int data_count = (sizeof(data)/sizeof(data[0]));
-
-static char buffer[100];
-
-static char *test_version_compare(void *context)
-{
-
-    const test_data_t *p = data;
-    for (int i = 0; i < data_count; ++i) {
-
-        if (QDR_ROUTER_VERSION_AT_LEAST(p->version, p->major, p->minor, p->patch) != p->expected) {
-            snprintf(buffer, sizeof(buffer), "At least failed: %u.%u.%u / %u.%u.%u e=%s\n",
-                     p->version.major, p->version.minor, p->version.patch,
-                     p->major, p->minor, p->patch, p->expected ? "true" : "false");
-            return buffer;
-        }
-        if (QDR_ROUTER_VERSION_LESS_THAN(p->version, p->major, p->minor, p->patch) == p->expected) {
-            snprintf(buffer, sizeof(buffer), "Less than failed: %u.%u.%u / %u.%u.%u e=%s\n",
-                     p->version.major, p->version.minor, p->version.patch,
-                     p->major, p->minor, p->patch, p->expected ? "true" : "false");
-            return buffer;
-        }
-        ++p;
-    }
-
-    return 0;
-}
-
-
-int version_tests()
-{
-    int result = 0;
-    char *test_group = "version_tests";
-
-    TEST_CASE(test_version_compare, 0);
-
-    return result;
-}
-


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