http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/reactor.c ---------------------------------------------------------------------- diff --git a/c/tests/reactor.c b/c/tests/reactor.c deleted file mode 100644 index 900d6a3..0000000 --- a/c/tests/reactor.c +++ /dev/null @@ -1,578 +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 <proton/reactor.h> -#include <proton/handlers.h> -#include <proton/event.h> -#include <proton/connection.h> -#include <proton/session.h> -#include <proton/link.h> -#include <proton/delivery.h> -#include <proton/url.h> -#include <stdlib.h> -#include <string.h> - -#define assert(E) ((E) ? 0 : (abort(), 0)) - - -static void test_reactor(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_free(reactor); -} - -static void test_reactor_free(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_reactor_free(reactor); -} - -static void test_reactor_run(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - // run should exit if there is nothing left to do - pn_reactor_run(reactor); - pn_free(reactor); -} - -static void test_reactor_run_free(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - // run should exit if there is nothing left to do - pn_reactor_run(reactor); - pn_reactor_free(reactor); -} - -typedef struct { - pn_reactor_t *reactor; - pn_list_t *events; -} pni_test_handler_t; - -pni_test_handler_t *thmem(pn_handler_t *handler) { - return (pni_test_handler_t *) pn_handler_mem(handler); -} - -void test_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { - pni_test_handler_t *th = thmem(handler); - pn_reactor_t *reactor = pn_event_reactor(event); - assert(reactor == th->reactor); - pn_list_add(th->events, (void *) type); -} - -pn_handler_t *test_handler(pn_reactor_t *reactor, pn_list_t *events) { - pn_handler_t *handler = pn_handler_new(test_dispatch, sizeof(pni_test_handler_t), NULL); - thmem(handler)->reactor = reactor; - thmem(handler)->events = events; - return handler; -} - - -void root_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { - pni_test_handler_t *th = thmem(handler); - pn_reactor_t *reactor = pn_event_reactor(event); - assert(reactor == th->reactor); - pn_list_add(th->events, pn_event_root(event)); -} - -pn_handler_t *test_root(pn_reactor_t *reactor, pn_list_t *events) { - pn_handler_t *handler = pn_handler_new(root_dispatch, sizeof(pni_test_handler_t), NULL); - thmem(handler)->reactor = reactor; - thmem(handler)->events = events; - return handler; -} - -#define END PN_EVENT_NONE - -void expect(pn_list_t *events, ...) { - va_list ap; - - va_start(ap, events); - size_t idx = 0; - while (true) { - pn_event_type_t expected = (pn_event_type_t) va_arg(ap, int); - if (expected == END) { - assert(idx == pn_list_size(events)); - break; - } - assert(idx < pn_list_size(events)); - pn_event_type_t actual = (pn_event_type_t)(size_t) pn_list_get(events, idx++); - assert(expected == actual); - } - va_end(ap); -} - -static void test_reactor_handler(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_handler_t *handler = pn_reactor_get_handler(reactor); - assert(handler); - pn_list_t *events = pn_list(PN_VOID, 0); - pn_handler_t *th = test_handler(reactor, events); - pn_handler_add(handler, th); - pn_decref(th); - pn_free(reactor); - expect(events, END); - pn_free(events); -} - -static void test_reactor_handler_free(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_handler_t *handler = pn_reactor_get_handler(reactor); - assert(handler); - pn_list_t *events = pn_list(PN_VOID, 0); - pn_handler_add(handler, test_handler(reactor, events)); - pn_reactor_free(reactor); - expect(events, END); - pn_free(events); -} - -static void test_reactor_handler_run(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_handler_t *handler = pn_reactor_get_handler(reactor); - assert(handler); - pn_list_t *events = pn_list(PN_VOID, 0); - pn_handler_t *th = test_handler(reactor, events); - pn_handler_add(handler, th); - pn_reactor_run(reactor); - expect(events, PN_REACTOR_INIT, PN_SELECTABLE_INIT, PN_SELECTABLE_UPDATED, PN_SELECTABLE_FINAL, PN_REACTOR_FINAL, END); - pn_free(reactor); - pn_free(th); - pn_free(events); -} - -static void test_reactor_handler_run_free(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_handler_t *handler = pn_reactor_get_handler(reactor); - assert(handler); - pn_list_t *events = pn_list(PN_VOID, 0); - pn_handler_add(handler, test_handler(reactor, events)); - pn_reactor_run(reactor); - expect(events, PN_REACTOR_INIT, PN_SELECTABLE_INIT, PN_SELECTABLE_UPDATED, PN_SELECTABLE_FINAL, PN_REACTOR_FINAL, END); - pn_reactor_free(reactor); - pn_free(events); -} - -static void test_reactor_event_root(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_handler_t *handler = pn_reactor_get_handler(reactor); - assert(handler); - pn_list_t *roots = pn_list(PN_VOID, 0); - pn_handler_t *th = test_root(reactor, roots); - pn_handler_add(handler, th); - pn_reactor_run(reactor); - expect(roots, handler, handler, handler, handler, handler, END); - pn_free(reactor); - pn_free(th); - pn_free(roots); -} - -static void test_reactor_connection(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_list_t *cevents = pn_list(PN_VOID, 0); - pn_handler_t *tch = test_handler(reactor, cevents); - pn_connection_t *connection = pn_reactor_connection(reactor, tch); - assert(connection); - pn_reactor_set_connection_host(reactor, connection, "127.0.0.1", "5672"); - pn_url_t *url = pn_url_parse(pn_reactor_get_connection_address(reactor, connection)); - assert(strcmp(pn_url_get_host(url), "127.0.0.1") == 0); - assert(strcmp(pn_url_get_port(url), "5672") == 0); - pn_decref(url); - pn_handler_t *root = pn_reactor_get_handler(reactor); - pn_list_t *revents = pn_list(PN_VOID, 0); - pn_handler_add(root, test_handler(reactor, revents)); - pn_reactor_run(reactor); - expect(revents, PN_REACTOR_INIT, PN_SELECTABLE_INIT, PN_SELECTABLE_UPDATED, PN_SELECTABLE_FINAL, PN_REACTOR_FINAL, - END); - expect(cevents, PN_CONNECTION_INIT, END); - pn_reactor_free(reactor); - pn_handler_free(tch); - pn_free(cevents); - pn_free(revents); -} - -static void test_reactor_connection_factory(void) -{ - pn_reactor_t *reactor = pn_reactor(); - pn_connection_t *conn; - const char *addr; - // use host as connection hostname default - conn = pn_reactor_connection_to_host(reactor, "a.test.com", "5678", NULL); - pn_connection_set_hostname(conn, "virt.host"); - addr = pn_reactor_get_connection_address(reactor, conn); - assert(addr && strcmp(addr, "a.test.com:5678") == 0); - assert(strcmp(pn_connection_get_hostname(conn), "virt.host") == 0); - // verify the host address can be changed: - pn_reactor_set_connection_host(reactor, conn, "a.different.com", "9999"); - addr = pn_reactor_get_connection_address(reactor, conn); - assert(addr && strcmp(addr, "a.different.com:9999") == 0); - assert(strcmp(pn_connection_get_hostname(conn), "virt.host") == 0); - pn_reactor_free(reactor); -} - -static void test_reactor_acceptor(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_acceptor_t *acceptor = pn_reactor_acceptor(reactor, "0.0.0.0", "5678", NULL); - assert(acceptor); - pn_reactor_free(reactor); -} - -pn_acceptor_t **tram(pn_handler_t *h) { - return (pn_acceptor_t **) pn_handler_mem(h); -} - -static void tra_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { - switch (type) { - case PN_REACTOR_INIT: - { - pn_acceptor_t *acceptor = *tram(handler); - pn_acceptor_close(acceptor); - } - break; - default: - break; - } -} - -static pn_handler_t *tra_handler(pn_acceptor_t *acceptor) { - pn_handler_t *handler = pn_handler_new(tra_dispatch, sizeof(pn_acceptor_t *), NULL); - *tram(handler) = acceptor; - return handler; -} - -static void test_reactor_acceptor_run(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_handler_t *root = pn_reactor_get_handler(reactor); - assert(root); - pn_acceptor_t *acceptor = pn_reactor_acceptor(reactor, "0.0.0.0", "5678", NULL); - assert(acceptor); - pn_handler_add(root, tra_handler(acceptor)); - pn_reactor_run(reactor); - pn_reactor_free(reactor); -} - -typedef struct { - pn_reactor_t *reactor; - pn_acceptor_t *acceptor; - pn_list_t *events; -} server_t; - -static server_t *smem(pn_handler_t *handler) { - return (server_t *) pn_handler_mem(handler); -} - -static void server_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { - server_t *srv = smem(handler); - pn_list_add(srv->events, (void *) pn_event_type(event)); - switch (type) { - case PN_CONNECTION_REMOTE_OPEN: - pn_connection_open(pn_event_connection(event)); - break; - case PN_CONNECTION_REMOTE_CLOSE: - pn_acceptor_close(srv->acceptor); - pn_connection_close(pn_event_connection(event)); - pn_connection_release(pn_event_connection(event)); - break; - default: - break; - } -} - -typedef struct { - pn_list_t *events; -} client_t; - -static client_t *cmem(pn_handler_t *handler) { - return (client_t *) pn_handler_mem(handler); -} - -static void client_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { - client_t *cli = cmem(handler); - pn_list_add(cli->events, (void *) type); - pn_connection_t *conn = pn_event_connection(event); - switch (pn_event_type(event)) { - case PN_CONNECTION_INIT: - pn_connection_set_hostname(conn, "some.org"); - pn_connection_open(conn); - break; - case PN_CONNECTION_REMOTE_OPEN: - pn_connection_close(conn); - break; - case PN_CONNECTION_REMOTE_CLOSE: - pn_connection_release(conn); - break; - default: - break; - } -} - -static void test_reactor_connect(void) { - pn_reactor_t *reactor = pn_reactor(); - pn_handler_t *sh = pn_handler_new(server_dispatch, sizeof(server_t), NULL); - server_t *srv = smem(sh); - pn_acceptor_t *acceptor = pn_reactor_acceptor(reactor, "0.0.0.0", "5678", sh); - srv->reactor = reactor; - srv->acceptor = acceptor; - srv->events = pn_list(PN_VOID, 0); - pn_handler_t *ch = pn_handler_new(client_dispatch, sizeof(client_t), NULL); - client_t *cli = cmem(ch); - cli->events = pn_list(PN_VOID, 0); - pn_connection_t *conn = pn_reactor_connection_to_host(reactor, - "127.0.0.1", - "5678", - ch); - assert(conn); - pn_url_t *url = pn_url_parse(pn_reactor_get_connection_address(reactor, conn)); - assert(strcmp(pn_url_get_host(url), "127.0.0.1") == 0); - assert(strcmp(pn_url_get_port(url), "5678") == 0); - pn_decref(url); - pn_reactor_run(reactor); - expect(srv->events, PN_CONNECTION_INIT, PN_CONNECTION_BOUND, - PN_CONNECTION_REMOTE_OPEN, - PN_CONNECTION_LOCAL_OPEN, PN_TRANSPORT, - PN_CONNECTION_REMOTE_CLOSE, PN_TRANSPORT_TAIL_CLOSED, - PN_CONNECTION_LOCAL_CLOSE, PN_TRANSPORT, - PN_TRANSPORT_HEAD_CLOSED, PN_TRANSPORT_CLOSED, - PN_CONNECTION_UNBOUND, PN_CONNECTION_FINAL, END); - pn_free(srv->events); - pn_decref(sh); - expect(cli->events, PN_CONNECTION_INIT, PN_CONNECTION_LOCAL_OPEN, - PN_CONNECTION_BOUND, - PN_CONNECTION_REMOTE_OPEN, PN_CONNECTION_LOCAL_CLOSE, - PN_TRANSPORT, PN_TRANSPORT_HEAD_CLOSED, - PN_CONNECTION_REMOTE_CLOSE, PN_TRANSPORT_TAIL_CLOSED, - PN_TRANSPORT_CLOSED, PN_CONNECTION_UNBOUND, - PN_CONNECTION_FINAL, END); - pn_free(cli->events); - pn_decref(ch); - pn_reactor_free(reactor); -} - -static void test_reactor_bad_domain(void) { - pn_reactor_t *reactor = pn_reactor(); - assert(reactor); - pn_handler_t *ch = pn_handler_new(client_dispatch, sizeof(client_t), NULL); - client_t *cli = cmem(ch); - cli->events = pn_list(PN_VOID, 0); - pn_connection_t *connection = pn_reactor_connection_to_host(reactor, "somebogusdomain", "5672", ch); - assert(connection); - pn_reactor_run(reactor); - - expect(cli->events, PN_CONNECTION_INIT, PN_CONNECTION_LOCAL_OPEN, - PN_CONNECTION_BOUND, PN_TRANSPORT_TAIL_CLOSED, - PN_TRANSPORT_ERROR, PN_TRANSPORT_HEAD_CLOSED, - PN_TRANSPORT_CLOSED, PN_CONNECTION_UNBOUND, - END); - - pn_free(cli->events); - pn_decref(ch); - pn_reactor_free(reactor); -} - -typedef struct { - int received; -} sink_t; - -static sink_t *sink(pn_handler_t *handler) { - return (sink_t *) pn_handler_mem(handler); -} - -void sink_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { - sink_t *snk = sink(handler); - pn_delivery_t *dlv = pn_event_delivery(event); - switch (type) { - case PN_DELIVERY: - if (!pn_delivery_partial(dlv)) { - pn_delivery_settle(dlv); - snk->received++; - } - break; - default: - break; - } -} - -typedef struct { - int remaining; -} source_t; - -static source_t *source(pn_handler_t *handler) { - return (source_t *) pn_handler_mem(handler); -} - - -void source_dispatch(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { - source_t *src = source(handler); - pn_connection_t *conn = pn_event_connection(event); - switch (type) { - case PN_CONNECTION_INIT: - { - pn_session_t *ssn = pn_session(conn); - pn_link_t *snd = pn_sender(ssn, "sender"); - pn_connection_open(conn); - pn_session_open(ssn); - pn_link_open(snd); - } - break; - case PN_LINK_FLOW: - { - pn_link_t *link = pn_event_link(event); - while (pn_link_credit(link) > 0 && src->remaining > 0) { - pn_delivery_t *dlv = pn_delivery(link, pn_dtag("", 0)); - assert(dlv); - pn_delivery_settle(dlv); - src->remaining--; - } - - if (!src->remaining) { - pn_connection_close(conn); - } - } - break; - case PN_CONNECTION_REMOTE_CLOSE: - pn_connection_release(conn); - break; - default: - break; - } -} - -static void test_reactor_transfer(int count, int window) { - pn_reactor_t *reactor = pn_reactor(); - - pn_handler_t *sh = pn_handler_new(server_dispatch, sizeof(server_t), NULL); - server_t *srv = smem(sh); - pn_acceptor_t *acceptor = pn_reactor_acceptor(reactor, "0.0.0.0", "5678", sh); - srv->reactor = reactor; - srv->acceptor = acceptor; - srv->events = pn_list(PN_VOID, 0); - pn_handler_add(sh, pn_handshaker()); - // XXX: a window of 1 doesn't work unless the flowcontroller is - // added after the thing that settles the delivery - pn_handler_add(sh, pn_flowcontroller(window)); - pn_handler_t *snk = pn_handler_new(sink_dispatch, sizeof(sink_t), NULL); - sink(snk)->received = 0; - pn_handler_add(sh, snk); - - pn_handler_t *ch = pn_handler_new(source_dispatch, sizeof(source_t), NULL); - source_t *src = source(ch); - src->remaining = count; - pn_connection_t *conn = NULL; - // Using the connection's hostname to set the connection address is - // deprecated. Once support is dropped the conditional code can be removed: - #if 0 - conn = pn_reactor_connection(reactor, ch); - assert(conn); - pn_reactor_connection_set_address(reactor, conn, "127.0.0.1", "5678"); - #else - // This is deprecated: - conn = pn_reactor_connection(reactor, ch); - pn_connection_set_hostname(conn, "127.0.0.1:5678"); - #endif - - pn_reactor_run(reactor); - - assert(sink(snk)->received == count); - - pn_free(srv->events); - pn_reactor_free(reactor); - pn_handler_free(sh); - pn_handler_free(ch); -} - -static void test_reactor_schedule(void) { - pn_reactor_t *reactor = pn_reactor(); - pn_handler_t *root = pn_reactor_get_handler(reactor); - pn_list_t *events = pn_list(PN_VOID, 0); - pn_handler_add(root, test_handler(reactor, events)); - pn_reactor_schedule(reactor, 0, NULL); - pn_reactor_run(reactor); - pn_reactor_free(reactor); - expect(events, PN_REACTOR_INIT, PN_SELECTABLE_INIT, PN_SELECTABLE_UPDATED, PN_REACTOR_QUIESCED, - PN_TIMER_TASK, PN_SELECTABLE_UPDATED, PN_SELECTABLE_FINAL, PN_REACTOR_FINAL, END); - pn_free(events); -} - -static void test_reactor_schedule_handler(void) { - pn_reactor_t *reactor = pn_reactor(); - pn_handler_t *root = pn_reactor_get_handler(reactor); - pn_list_t *events = pn_list(PN_VOID, 0); - pn_list_t *tevents = pn_list(PN_VOID, 0); - pn_handler_add(root, test_handler(reactor, events)); - pn_handler_t *th = test_handler(reactor, tevents); - pn_reactor_schedule(reactor, 0, th); - pn_reactor_run(reactor); - pn_reactor_free(reactor); - pn_handler_free(th); - expect(events, PN_REACTOR_INIT, PN_SELECTABLE_INIT, PN_SELECTABLE_UPDATED, PN_REACTOR_QUIESCED, PN_SELECTABLE_UPDATED, - PN_SELECTABLE_FINAL, PN_REACTOR_FINAL, END); - expect(tevents, PN_TIMER_TASK, END); - pn_free(events); - pn_free(tevents); -} - -static void test_reactor_schedule_cancel(void) { - pn_reactor_t *reactor = pn_reactor(); - pn_handler_t *root = pn_reactor_get_handler(reactor); - pn_list_t *events = pn_list(PN_VOID, 0); - pn_handler_add(root, test_handler(reactor, events)); - pn_task_t *task = pn_reactor_schedule(reactor, 0, NULL); - pn_task_cancel(task); - pn_reactor_run(reactor); - pn_reactor_free(reactor); - expect(events, PN_REACTOR_INIT, PN_SELECTABLE_INIT, PN_SELECTABLE_UPDATED, - PN_SELECTABLE_FINAL, PN_REACTOR_FINAL, END); - pn_free(events); -} - -int main(int argc, char **argv) -{ - test_reactor_event_root(); - test_reactor(); - test_reactor_free(); - test_reactor_run(); - test_reactor_run_free(); - test_reactor_handler(); - test_reactor_handler_free(); - test_reactor_handler_run(); - test_reactor_handler_run_free(); - test_reactor_connection(); - test_reactor_connection_factory(); - test_reactor_bad_domain(); - test_reactor_acceptor(); - test_reactor_acceptor_run(); - test_reactor_connect(); - for (int i = 0; i < 64; i++) { - test_reactor_transfer(i, 2); - } - test_reactor_transfer(1024, 64); - test_reactor_transfer(4*1024, 1024); - test_reactor_schedule(); - test_reactor_schedule_handler(); - test_reactor_schedule_cancel(); - return 0; -}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/refcount.c ---------------------------------------------------------------------- diff --git a/c/tests/refcount.c b/c/tests/refcount.c deleted file mode 100644 index 487f115..0000000 --- a/c/tests/refcount.c +++ /dev/null @@ -1,393 +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 <proton/connection.h> -#include <proton/event.h> -#include <proton/session.h> -#include <proton/link.h> -#include <proton/delivery.h> -#include <proton/transport.h> -#include <stdio.h> -#include <stdlib.h> - -#define assert(E) ((E) ? 0 : (abort(), 0)) - -/** - * The decref order tests validate that whenever the last pointer to a - * child object, e.g. a session or a link, is about to go away, the - * parent object takes ownership of that reference if the child object - * has not been freed, this avoids reference cycles but allows - * navigation from parents to children. - **/ - -#define SETUP_CSL \ - pn_connection_t *conn = pn_connection(); \ - pn_session_t *ssn = pn_session(conn); \ - pn_incref(ssn); \ - pn_link_t *lnk = pn_sender(ssn, "sender"); \ - pn_incref(lnk); \ - \ - assert(pn_refcount(conn) == 2); \ - assert(pn_refcount(ssn) == 2); \ - assert(pn_refcount(lnk) == 1); - -static void test_decref_order_csl(void) { - SETUP_CSL; - - pn_decref(conn); - assert(pn_refcount(conn) == 1); // session keeps alive - pn_decref(ssn); - assert(pn_refcount(ssn) == 1); // link keeps alive - pn_decref(lnk); - // all gone now (requires valgrind to validate) -} - -static void test_decref_order_cls(void) { - SETUP_CSL; - - pn_decref(conn); - assert(pn_refcount(conn) == 1); // session keeps alive - pn_decref(lnk); - assert(pn_refcount(lnk) == 1); // session takes over ownership - pn_decref(ssn); - // all gone now (requires valgrind to validate) -} - -static void test_decref_order_lcs(void) { - SETUP_CSL; - - pn_decref(lnk); - assert(pn_refcount(lnk) == 1); // session takes over ownership - pn_decref(conn); - assert(pn_refcount(conn) == 1); // session keeps alive - pn_decref(ssn); - // all gone now (requires valgrind to validate) -} - -static void test_decref_order_scl(void) { - SETUP_CSL; - - pn_decref(ssn); - assert(pn_refcount(ssn) == 1); // link keeps alive - pn_decref(conn); - assert(pn_refcount(conn) == 1); // session keeps alive - pn_decref(lnk); - // all gone now (requires valgrind to validate) -} - -static void test_decref_order_slc(void) { - SETUP_CSL; - - pn_decref(ssn); - assert(pn_refcount(ssn) == 1); // link keeps alive - pn_decref(lnk); - assert(pn_refcount(ssn) == 1); // connection takes over ownership - assert(pn_refcount(lnk) == 1); // session takes over ownership - pn_decref(conn); - // all gone now (requires valgrind to validate) -} - -static void test_decref_order_lsc(void) { - SETUP_CSL; - - pn_decref(lnk); - assert(pn_refcount(lnk) == 1); // session takes over ownership - assert(pn_refcount(ssn) == 1); - pn_decref(ssn); - assert(pn_refcount(lnk) == 1); - assert(pn_refcount(ssn) == 1); // connection takes over ownership - pn_decref(conn); - // all gone now (requires valgrind to validate) -} - -/** - * The incref order tests verify that once ownership of the last - * pointer to a child is taken over by a parent, it is reassigned when - * the child is increfed. - **/ - -#define SETUP_INCREF_ORDER \ - SETUP_CSL; \ - pn_decref(lnk); \ - pn_decref(ssn); \ - assert(pn_refcount(lnk) == 1); \ - assert(pn_refcount(ssn) == 1); \ - assert(pn_refcount(conn) == 1); - -static void test_incref_order_sl(void) { - SETUP_INCREF_ORDER; - - pn_incref(ssn); - assert(pn_refcount(conn) == 2); - assert(pn_refcount(ssn) == 1); - assert(pn_refcount(lnk) == 1); - pn_incref(lnk); - assert(pn_refcount(conn) == 2); - assert(pn_refcount(ssn) == 2); - assert(pn_refcount(lnk) == 1); - - pn_decref(conn); - pn_decref(ssn); - pn_decref(lnk); -} - -static void test_incref_order_ls(void) { - SETUP_INCREF_ORDER; - - pn_incref(lnk); - assert(pn_refcount(conn) == 2); - assert(pn_refcount(ssn) == 1); - assert(pn_refcount(lnk) == 1); - pn_incref(ssn); - assert(pn_refcount(conn) == 2); - assert(pn_refcount(ssn) == 2); - assert(pn_refcount(lnk) == 1); - - pn_decref(conn); - pn_decref(ssn); - pn_decref(lnk); -} - -static void swap(int array[], int i, int j) { - int a = array[i]; - int b = array[j]; - array[j] = a; - array[i] = b; -} - -static void setup(void **objects) { - pn_connection_t *conn = pn_connection(); - pn_session_t *ssn = pn_session(conn); - pn_incref(ssn); - pn_link_t *lnk = pn_sender(ssn, "sender"); - pn_incref(lnk); - pn_delivery_t *dlv = pn_delivery(lnk, pn_dtag("dtag", 4)); - pn_incref(dlv); - - assert(pn_refcount(conn) == 2); - assert(pn_refcount(ssn) == 2); - assert(pn_refcount(lnk) == 2); - assert(pn_refcount(dlv) == 1); - - objects[0] = conn; - objects[1] = ssn; - objects[2] = lnk; - objects[3] = dlv; -} - -static bool decreffed(int *indexes, void **objects, int step, void *object) { - for (int i = 0; i <= step; i++) { - if (object == objects[indexes[i]]) { - return true; - } - } - return false; -} - -static bool live_descendent(int *indexes, void **objects, int step, int objidx) { - for (int i = objidx + 1; i < 4; i++) { - if (!decreffed(indexes, objects, step, objects[i])) { - return true; - } - } - - return false; -} - -static void assert_refcount(void *object, int expected) { - int rc = pn_refcount(object); - //printf("pn_refcount(%s) = %d\n", pn_object_reify(object)->name, rc); - assert(rc == expected); -} - -static void test_decref_order(int *indexes, void **objects) { - setup(objects); - - //printf("-----------\n"); - for (int i = 0; i < 3; i++) { - int idx = indexes[i]; - void *obj = objects[idx]; - //printf("decreffing %s\n", pn_object_reify(obj)->name); - pn_decref(obj); - for (int j = 0; j <= i; j++) { - // everything we've decreffed already should have a refcount of - // 1 because it has been preserved by its parent - assert_refcount(objects[indexes[j]], 1); - } - for (int j = i+1; j < 4; j++) { - // everything we haven't decreffed yet should have a refcount of - // 2 unless it has a descendant that has not been decrefed (or - // it has no child) in which case it should have a refcount of 1 - int idx = indexes[j]; - void *obj = objects[idx]; - assert(!decreffed(indexes, objects, i, obj)); - if (live_descendent(indexes, objects, i, idx)) { - assert_refcount(obj, 2); - } else { - assert_refcount(obj, 1); - } - } - } - - void *last = objects[indexes[3]]; - //printf("decreffing %s\n", pn_object_reify(last)->name); - pn_decref(last); - // all should be gone now, need to run with valgrind to check -} - -static void permute(int n, int *indexes, void **objects) { - int j; - if (n == 1) { - test_decref_order(indexes, objects); - } else { - for (int i = 1; i <= n; i++) { - permute(n-1, indexes, objects); - if ((n % 2) == 1) { - j = 1; - } else { - j = i; - } - swap(indexes, j-1, n-1); - } - } -} - -static void test_decref_permutations(void) { - void *objects[4]; - int indexes[4] = {0, 1, 2, 3}; - permute(4, indexes, objects); -} - -static void test_transport(void) { - pn_transport_t *transport = pn_transport(); - assert(pn_refcount(transport) == 1); - pn_incref(transport); - assert(pn_refcount(transport) == 2); - pn_decref(transport); - assert(pn_refcount(transport) == 1); - pn_free(transport); -} - -static void test_connection_transport(void) { - pn_connection_t *connection = pn_connection(); - assert(pn_refcount(connection) == 1); - pn_transport_t *transport = pn_transport(); - assert(pn_refcount(transport) == 1); - pn_transport_bind(transport, connection); - assert(pn_refcount(connection) == 2); - pn_decref(transport); - assert(pn_refcount(transport) == 1); // preserved by the bind - assert(pn_refcount(connection) == 1); - pn_free(connection); -} - -static void test_transport_connection(void) { - pn_transport_t *transport = pn_transport(); - assert(pn_refcount(transport) == 1); - pn_connection_t *connection = pn_connection(); - assert(pn_refcount(connection) == 1); - pn_transport_bind(transport, connection); - assert(pn_refcount(connection) == 2); - pn_decref(connection); - assert(pn_refcount(connection) == 1); - assert(pn_refcount(transport) == 1); - pn_free(transport); -} - -static void drain(pn_collector_t *collector) { - while (pn_collector_next(collector)) - ; -} - -static void test_collector_connection_transport(void) { - pn_collector_t *collector = pn_collector(); - assert(pn_refcount(collector) == 1); - pn_connection_t *connection = pn_connection(); - assert(pn_refcount(connection) == 1); - pn_connection_collect(connection, collector); - assert(pn_refcount(collector) == 2); - assert(pn_refcount(connection) == 2); - drain(collector); - assert(pn_refcount(connection) == 1); - pn_transport_t *transport = pn_transport(); - assert(pn_refcount(transport) == 1); - pn_transport_bind(transport, connection); - assert(pn_refcount(transport) == 1); - assert(pn_refcount(connection) == 3); - drain(collector); - assert(pn_refcount(connection) == 2); - pn_decref(transport); - assert(pn_refcount(transport) == 1); // preserved by the bind - assert(pn_refcount(connection) == 1); - pn_free(connection); - assert(pn_refcount(transport) == 1); // events - assert(pn_refcount(connection) == 1); // events - pn_collector_free(collector); -} - -static void test_collector_transport_connection(void) { - pn_collector_t *collector = pn_collector(); - assert(pn_refcount(collector) == 1); - pn_transport_t *transport = pn_transport(); - assert(pn_refcount(transport) == 1); - pn_connection_t *connection = pn_connection(); - assert(pn_refcount(connection) == 1); - pn_connection_collect(connection, collector); - assert(pn_refcount(collector) == 2); - assert(pn_refcount(connection) == 2); - drain(collector); - assert(pn_refcount(connection) == 1); - pn_transport_bind(transport, connection); - assert(pn_refcount(connection) == 3); - assert(pn_refcount(transport) == 1); - drain(collector); - assert(pn_refcount(connection) == 2); - assert(pn_refcount(transport) == 1); - pn_decref(connection); - assert(pn_refcount(connection) == 1); - assert(pn_refcount(transport) == 1); - pn_free(transport); - assert(pn_refcount(connection) == 1); - assert(pn_refcount(transport) == 1); - pn_collector_free(collector); -} - -int main(int argc, char **argv) -{ - test_decref_order_csl(); - test_decref_order_cls(); - test_decref_order_lcs(); - test_decref_order_scl(); - test_decref_order_slc(); - test_decref_order_lsc(); - - test_incref_order_sl(); - test_incref_order_ls(); - - test_decref_permutations(); - - test_transport(); - test_connection_transport(); - test_transport_connection(); - test_collector_connection_transport(); - test_collector_transport_connection(); - return 0; -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/refcount_test.cpp ---------------------------------------------------------------------- diff --git a/c/tests/refcount_test.cpp b/c/tests/refcount_test.cpp new file mode 100644 index 0000000..2fbf42b --- /dev/null +++ b/c/tests/refcount_test.cpp @@ -0,0 +1,371 @@ +/* + * + * 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 "./pn_test.hpp" +#include "catch_extra.hpp" + +#include <proton/connection.h> +#include <proton/delivery.h> +#include <proton/event.h> +#include <proton/link.h> +#include <proton/session.h> +#include <proton/transport.h> + +/** + * The decref order tests validate that whenever the last pointer to a + * child object, e.g. a session or a link, is about to go away, the + * parent object takes ownership of that reference if the child object + * has not been freed, this avoids reference cycles but allows + * navigation from parents to children. + **/ + +#define SETUP_CSL \ + pn_connection_t *conn = pn_connection(); \ + pn_session_t *ssn = pn_session(conn); \ + pn_incref(ssn); \ + pn_link_t *lnk = pn_sender(ssn, "sender"); \ + pn_incref(lnk); \ + \ + REQUIRE(pn_refcount(conn) == 2); \ + REQUIRE(pn_refcount(ssn) == 2); \ + REQUIRE(pn_refcount(lnk) == 1); + +TEST_CASE("test_decref_order_csl") { + SETUP_CSL; + + pn_decref(conn); + REQUIRE(pn_refcount(conn) == 1); // session keeps alive + pn_decref(ssn); + REQUIRE(pn_refcount(ssn) == 1); // link keeps alive + pn_decref(lnk); + // all gone now (requires valgrind to validate) +} + +TEST_CASE("test_decref_order_cls") { + SETUP_CSL; + + pn_decref(conn); + REQUIRE(pn_refcount(conn) == 1); // session keeps alive + pn_decref(lnk); + REQUIRE(pn_refcount(lnk) == 1); // session takes over ownership + pn_decref(ssn); + // all gone now (requires valgrind to validate) +} + +TEST_CASE("test_decref_order_lcs") { + SETUP_CSL; + + pn_decref(lnk); + REQUIRE(pn_refcount(lnk) == 1); // session takes over ownership + pn_decref(conn); + REQUIRE(pn_refcount(conn) == 1); // session keeps alive + pn_decref(ssn); + // all gone now (requires valgrind to validate) +} + +TEST_CASE("test_decref_order_scl") { + SETUP_CSL; + + pn_decref(ssn); + REQUIRE(pn_refcount(ssn) == 1); // link keeps alive + pn_decref(conn); + REQUIRE(pn_refcount(conn) == 1); // session keeps alive + pn_decref(lnk); + // all gone now (requires valgrind to validate) +} + +TEST_CASE("test_decref_order_slc") { + SETUP_CSL; + + pn_decref(ssn); + REQUIRE(pn_refcount(ssn) == 1); // link keeps alive + pn_decref(lnk); + REQUIRE(pn_refcount(ssn) == 1); // connection takes over ownership + REQUIRE(pn_refcount(lnk) == 1); // session takes over ownership + pn_decref(conn); + // all gone now (requires valgrind to validate) +} + +TEST_CASE("test_decref_order_lsc") { + SETUP_CSL; + + pn_decref(lnk); + REQUIRE(pn_refcount(lnk) == 1); // session takes over ownership + REQUIRE(pn_refcount(ssn) == 1); + pn_decref(ssn); + REQUIRE(pn_refcount(lnk) == 1); + REQUIRE(pn_refcount(ssn) == 1); // connection takes over ownership + pn_decref(conn); + // all gone now (requires valgrind to validate) +} + +/** + * The incref order tests verify that once ownership of the last + * pointer to a child is taken over by a parent, it is reassigned when + * the child is increfed. + **/ + +#define SETUP_INCREF_ORDER \ + SETUP_CSL; \ + pn_decref(lnk); \ + pn_decref(ssn); \ + REQUIRE(pn_refcount(lnk) == 1); \ + REQUIRE(pn_refcount(ssn) == 1); \ + REQUIRE(pn_refcount(conn) == 1); + +TEST_CASE("test_incref_order_sl") { + SETUP_INCREF_ORDER; + + pn_incref(ssn); + REQUIRE(pn_refcount(conn) == 2); + REQUIRE(pn_refcount(ssn) == 1); + REQUIRE(pn_refcount(lnk) == 1); + pn_incref(lnk); + REQUIRE(pn_refcount(conn) == 2); + REQUIRE(pn_refcount(ssn) == 2); + REQUIRE(pn_refcount(lnk) == 1); + + pn_decref(conn); + pn_decref(ssn); + pn_decref(lnk); +} + +TEST_CASE("test_incref_order_ls") { + SETUP_INCREF_ORDER; + + pn_incref(lnk); + REQUIRE(pn_refcount(conn) == 2); + REQUIRE(pn_refcount(ssn) == 1); + REQUIRE(pn_refcount(lnk) == 1); + pn_incref(ssn); + REQUIRE(pn_refcount(conn) == 2); + REQUIRE(pn_refcount(ssn) == 2); + REQUIRE(pn_refcount(lnk) == 1); + + pn_decref(conn); + pn_decref(ssn); + pn_decref(lnk); +} + +static void swap(int array[], int i, int j) { + int a = array[i]; + int b = array[j]; + array[j] = a; + array[i] = b; +} + +static void setup(void **objects) { + pn_connection_t *conn = pn_connection(); + pn_session_t *ssn = pn_session(conn); + pn_incref(ssn); + pn_link_t *lnk = pn_sender(ssn, "sender"); + pn_incref(lnk); + pn_delivery_t *dlv = pn_delivery(lnk, pn_dtag("dtag", 4)); + pn_incref(dlv); + + REQUIRE(pn_refcount(conn) == 2); + REQUIRE(pn_refcount(ssn) == 2); + REQUIRE(pn_refcount(lnk) == 2); + REQUIRE(pn_refcount(dlv) == 1); + + objects[0] = conn; + objects[1] = ssn; + objects[2] = lnk; + objects[3] = dlv; +} + +static bool decreffed(int *indexes, void **objects, int step, void *object) { + for (int i = 0; i <= step; i++) { + if (object == objects[indexes[i]]) { + return true; + } + } + return false; +} + +static bool live_descendent(int *indexes, void **objects, int step, + int objidx) { + for (int i = objidx + 1; i < 4; i++) { + if (!decreffed(indexes, objects, step, objects[i])) { + return true; + } + } + + return false; +} + +static void assert_refcount(void *object, int expected) { + int rc = pn_refcount(object); + // printf("pn_refcount(%s) = %d\n", pn_object_reify(object)->name, rc); + REQUIRE(rc == expected); +} + +static void test_decref_order(int *indexes, void **objects) { + setup(objects); + + // printf("-----------\n"); + for (int i = 0; i < 3; i++) { + int idx = indexes[i]; + void *obj = objects[idx]; + // printf("decreffing %s\n", pn_object_reify(obj)->name); + pn_decref(obj); + for (int j = 0; j <= i; j++) { + // everything we've decreffed already should have a refcount of + // 1 because it has been preserved by its parent + assert_refcount(objects[indexes[j]], 1); + } + for (int j = i + 1; j < 4; j++) { + // everything we haven't decreffed yet should have a refcount of + // 2 unless it has a descendant that has not been decrefed (or + // it has no child) in which case it should have a refcount of 1 + int idx = indexes[j]; + void *obj = objects[idx]; + REQUIRE(!decreffed(indexes, objects, i, obj)); + if (live_descendent(indexes, objects, i, idx)) { + assert_refcount(obj, 2); + } else { + assert_refcount(obj, 1); + } + } + } + + void *last = objects[indexes[3]]; + // printf("decreffing %s\n", pn_object_reify(last)->name); + pn_decref(last); + // all should be gone now, need to run with valgrind to check +} + +static void permute(int n, int *indexes, void **objects) { + int j; + if (n == 1) { + test_decref_order(indexes, objects); + } else { + for (int i = 1; i <= n; i++) { + permute(n - 1, indexes, objects); + if ((n % 2) == 1) { + j = 1; + } else { + j = i; + } + swap(indexes, j - 1, n - 1); + } + } +} + +TEST_CASE("test_decref_permutations") { + void *objects[4]; + int indexes[4] = {0, 1, 2, 3}; + permute(4, indexes, objects); +} + +TEST_CASE("test_transport") { + pn_transport_t *transport = pn_transport(); + REQUIRE(pn_refcount(transport) == 1); + pn_incref(transport); + REQUIRE(pn_refcount(transport) == 2); + pn_decref(transport); + REQUIRE(pn_refcount(transport) == 1); + pn_free(transport); +} + +TEST_CASE("test_connection_transport") { + pn_connection_t *connection = pn_connection(); + REQUIRE(pn_refcount(connection) == 1); + pn_transport_t *transport = pn_transport(); + REQUIRE(pn_refcount(transport) == 1); + pn_transport_bind(transport, connection); + REQUIRE(pn_refcount(connection) == 2); + pn_decref(transport); + REQUIRE(pn_refcount(transport) == 1); // preserved by the bind + REQUIRE(pn_refcount(connection) == 1); + pn_free(connection); +} + +TEST_CASE("test_transport_connection") { + pn_transport_t *transport = pn_transport(); + REQUIRE(pn_refcount(transport) == 1); + pn_connection_t *connection = pn_connection(); + REQUIRE(pn_refcount(connection) == 1); + pn_transport_bind(transport, connection); + REQUIRE(pn_refcount(connection) == 2); + pn_decref(connection); + REQUIRE(pn_refcount(connection) == 1); + REQUIRE(pn_refcount(transport) == 1); + pn_free(transport); +} + +static void drain(pn_collector_t *collector) { + while (pn_collector_next(collector)) + ; +} + +TEST_CASE("test_collector_connection_transport") { + pn_collector_t *collector = pn_collector(); + REQUIRE(pn_refcount(collector) == 1); + pn_connection_t *connection = pn_connection(); + REQUIRE(pn_refcount(connection) == 1); + pn_connection_collect(connection, collector); + REQUIRE(pn_refcount(collector) == 2); + REQUIRE(pn_refcount(connection) == 2); + drain(collector); + REQUIRE(pn_refcount(connection) == 1); + pn_transport_t *transport = pn_transport(); + REQUIRE(pn_refcount(transport) == 1); + pn_transport_bind(transport, connection); + REQUIRE(pn_refcount(transport) == 1); + REQUIRE(pn_refcount(connection) == 3); + drain(collector); + REQUIRE(pn_refcount(connection) == 2); + pn_decref(transport); + REQUIRE(pn_refcount(transport) == 1); // preserved by the bind + REQUIRE(pn_refcount(connection) == 1); + pn_free(connection); + REQUIRE(pn_refcount(transport) == 1); // events + REQUIRE(pn_refcount(connection) == 1); // events + pn_collector_free(collector); +} + +TEST_CASE("test_collector_transport_connection") { + pn_collector_t *collector = pn_collector(); + REQUIRE(pn_refcount(collector) == 1); + pn_transport_t *transport = pn_transport(); + REQUIRE(pn_refcount(transport) == 1); + pn_connection_t *connection = pn_connection(); + REQUIRE(pn_refcount(connection) == 1); + pn_connection_collect(connection, collector); + REQUIRE(pn_refcount(collector) == 2); + REQUIRE(pn_refcount(connection) == 2); + drain(collector); + REQUIRE(pn_refcount(connection) == 1); + pn_transport_bind(transport, connection); + REQUIRE(pn_refcount(connection) == 3); + REQUIRE(pn_refcount(transport) == 1); + drain(collector); + REQUIRE(pn_refcount(connection) == 2); + REQUIRE(pn_refcount(transport) == 1); + pn_decref(connection); + REQUIRE(pn_refcount(connection) == 1); + REQUIRE(pn_refcount(transport) == 1); + pn_free(transport); + REQUIRE(pn_refcount(connection) == 1); + REQUIRE(pn_refcount(transport) == 1); + pn_collector_free(collector); +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/ssl.c ---------------------------------------------------------------------- diff --git a/c/tests/ssl.c b/c/tests/ssl.c deleted file mode 100644 index 9acb362..0000000 --- a/c/tests/ssl.c +++ /dev/null @@ -1,71 +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 <proton/ssl.h> - -#include "test_tools.h" - -static void test_ssl_protocols(test_t *t) -{ - pn_ssl_domain_t *sd = pn_ssl_domain(PN_SSL_MODE_CLIENT); - - // Error no protocol set - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "")==PN_ARG_ERR); - // Unknown protocol - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "blah")==PN_ARG_ERR); - // Unknown protocol with known protocl prefix - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1.x")==PN_ARG_ERR); - - // known protocols - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1")==0); - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1.1")==0); - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1.2")==0); - - // Multiple protocols - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.1 TLSv1.2")==0); - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.1")==0); - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1.1 TLSv1.2")==0); - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.2")==0); - - // Illegal separators - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1/TLSv1.1 TLSv1.2")==PN_ARG_ERR); - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1-TLSv1.1 TLSv1.2")==PN_ARG_ERR); - - // Legal separators - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1,TLSv1.1;TLSv1.2 ; ")==0); - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1;TLSv1.1 TLSv1.2,,,,")==0); - - // Known followed by unknown protocols - TEST_CHECK(t, pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.x;TLSv1_2")==PN_ARG_ERR); - - pn_ssl_domain_free(sd); -} - -int main(int argc, char **argv) { - int failed = 0; - // Don't run these tests if ssl functionality wasn't compiled - if (!pn_ssl_present()) { - fprintf(stderr, "No SSL implementation to test\n"); - return failed; - } -#if !defined(_WIN32) - RUN_ARGV_TEST(failed, t, test_ssl_protocols(&t)); -#endif - return failed; -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/ssl_test.cpp ---------------------------------------------------------------------- diff --git a/c/tests/ssl_test.cpp b/c/tests/ssl_test.cpp new file mode 100644 index 0000000..bd1e228 --- /dev/null +++ b/c/tests/ssl_test.cpp @@ -0,0 +1,60 @@ +/* + * 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 <proton/ssl.h> + +#include "./pn_test.hpp" + +TEST_CASE("ssl_protocols") { + if (!pn_ssl_present()) { + WARN("SSL not available, skipping"); + return; + } + pn_test::auto_free<pn_ssl_domain_t, pn_ssl_domain_free> sd( + pn_ssl_domain(PN_SSL_MODE_CLIENT)); + + // Error no protocol set + CHECK(pn_ssl_domain_set_protocols(sd, "") == PN_ARG_ERR); + // Unknown protocol + CHECK(pn_ssl_domain_set_protocols(sd, "blah") == PN_ARG_ERR); + // Unknown protocol with known protocl prefix + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1.x") == PN_ARG_ERR); + + // known protocols + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1") == 0); + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1.1") == 0); + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1.2") == 0); + + // Multiple protocols + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.1 TLSv1.2") == 0); + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.1") == 0); + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1.1 TLSv1.2") == 0); + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.2") == 0); + + // Illegal separators + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1/TLSv1.1 TLSv1.2") == PN_ARG_ERR); + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1-TLSv1.1 TLSv1.2") == PN_ARG_ERR); + + // Legal separators + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1,TLSv1.1;TLSv1.2 ; ") == 0); + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1;TLSv1.1 TLSv1.2,,,,") == 0); + + // Known followed by unknown protocols + CHECK(pn_ssl_domain_set_protocols(sd, "TLSv1 TLSv1.x;TLSv1_2") == PN_ARG_ERR); +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/test_handler.h ---------------------------------------------------------------------- diff --git a/c/tests/test_handler.h b/c/tests/test_handler.h deleted file mode 100644 index 8799fb3..0000000 --- a/c/tests/test_handler.h +++ /dev/null @@ -1,184 +0,0 @@ -#ifndef TESTS_TEST_DRIVER_H -#define TESTS_TEST_DRIVER_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 "test_tools.h" -#include <proton/ssl.h> - -/* C event handlers for tests */ - -#define MAX_EVENT_LOG 2048 /* Max number of event types stored per proactor_test */ - -struct test_handler_t; - -/* Returns 0 if the test should continue processing events, non-0 if processing should pause here */ -typedef pn_event_type_t (*test_handler_fn)(struct test_handler_t*, pn_event_t*); - -/* A handler that logs event types and delegates to another handler */ -typedef struct test_handler_t { - test_t *t; - test_handler_fn f; - pn_event_type_t log[MAX_EVENT_LOG]; /* Log of event types */ - size_t log_size; /* Number of events in the log */ - void *context; /* Generic test context */ - /* Specific context slots for proton objects commonly used by handlers */ - pn_connection_t *connection; - pn_session_t *session; - pn_link_t *link; - pn_link_t *sender; - pn_link_t *receiver; - pn_delivery_t *delivery; - pn_message_t *message; - pn_ssl_domain_t *ssl_domain; -} test_handler_t; - -void test_handler_init(test_handler_t *th, test_t *t, test_handler_fn f) { - memset(th, 0, sizeof(*th)); - th->t = t; - th->f = f; -} - -/* Save event type in the handler log */ -void test_handler_log(test_handler_t *th, pn_event_t *e) { - TEST_ASSERT(th->log_size < MAX_EVENT_LOG); - th->log[th->log_size++] = pn_event_type(e); -} - -/* Keep at most n events in the handler's log, remove old events if necessary */ -void test_handler_clear(test_handler_t *th, size_t n) { - if (n == 0) { - th->log_size = 0; - } else if (n < th->log_size) { - memmove(th->log, th->log + th->log_size - n, n * sizeof(pn_event_type_t)); - th->log_size = n; - } -} - -void test_etypes_expect_(test_t *t, pn_event_type_t *etypes, size_t size, const char* file, int line, ...) { - va_list ap; - va_start(ap, line); /* ap is null terminated */ - pn_event_type_t want = (pn_event_type_t)va_arg(ap, int); - size_t i = 0; - while (want && i < size && want == etypes[i]) { - ++i; - want = (pn_event_type_t)va_arg(ap, int); - } - if (i < size || want) { - test_errorf_(t, NULL, file, line, "event mismatch"); - if (!t->inverted) { - fprintf(stderr, "after:"); - for (size_t j = 0; j < i; ++j) { /* These events matched */ - fprintf(stderr, " %s", pn_event_type_name(etypes[j])); - } - fprintf(stderr, "\n want:"); - for (; want; want = (pn_event_type_t)va_arg(ap, int)) { - fprintf(stderr, " %s", pn_event_type_name(want)); - } - fprintf(stderr, "\n got:"); - for (; i < size; ++i) { - fprintf(stderr, " %s", pn_event_type_name(etypes[i])); - } - fprintf(stderr, "\n"); - } - } - va_end(ap); -} - -#define TEST_HANDLER_EXPECT(TH, ...) do { \ - test_etypes_expect_((TH)->t, (TH)->log, (TH)->log_size, __FILE__, __LINE__, __VA_ARGS__); \ - test_handler_clear((TH), 0); \ - } while(0) - -#define TEST_HANDLER_EXPECT_LAST(TH, ETYPE) do { \ - test_handler_clear((TH), 1); \ - test_etypes_expect_((TH)->t, (TH)->log, (TH)->log_size, __FILE__, __LINE__, ETYPE, 0); \ - test_handler_clear((TH), 0); \ - } while(0) - -/* A pn_connection_driver_t with a test_handler */ -typedef struct test_connection_driver_t { - test_handler_t handler; - pn_connection_driver_t driver; -} test_connection_driver_t; - -void test_connection_driver_init(test_connection_driver_t *d, test_t *t, test_handler_fn f, void* context) -{ - test_handler_init(&d->handler, t, f); - d->handler.context = context; - pn_connection_driver_init(&d->driver, NULL, NULL); -} - -void test_connection_driver_destroy(test_connection_driver_t *d) { - pn_connection_driver_destroy(&d->driver); -} - -pn_event_type_t test_connection_driver_handle(test_connection_driver_t *d) { - for (pn_event_t *e = pn_connection_driver_next_event(&d->driver); - e; - e = pn_connection_driver_next_event(&d->driver)) - { - test_handler_log(&d->handler, e); - pn_event_type_t et = d->handler.f ? d->handler.f(&d->handler, e) : PN_EVENT_NONE; - if (et) return et; - } - return PN_EVENT_NONE; -} - -/* Transfer data from one driver to another in memory */ -static int test_connection_drivers_xfer(test_connection_driver_t *dst, test_connection_driver_t *src) -{ - pn_bytes_t wb = pn_connection_driver_write_buffer(&src->driver); - pn_rwbytes_t rb = pn_connection_driver_read_buffer(&dst->driver); - size_t size = rb.size < wb.size ? rb.size : wb.size; - if (size) { - memcpy(rb.start, wb.start, size); - pn_connection_driver_write_done(&src->driver, size); - pn_connection_driver_read_done(&dst->driver, size); - } - return size; -} - -/* Run a pair of test drivers till there is nothing to do or one of their handlers returns non-0 - In that case return that driver -*/ -test_connection_driver_t* test_connection_drivers_run(test_connection_driver_t *a, test_connection_driver_t *b) -{ - int data = 0; - do { - if (test_connection_driver_handle(a)) return a; - if (test_connection_driver_handle(b)) return b; - data = test_connection_drivers_xfer(a, b) + test_connection_drivers_xfer(b, a); - } while (data || pn_connection_driver_has_event(&a->driver) || pn_connection_driver_has_event(&b->driver)); - return NULL; -} - -/* Initialize a client-server driver pair */ -void test_connection_drivers_init(test_t *t, test_connection_driver_t *a, test_handler_fn fa, test_connection_driver_t *b, test_handler_fn fb) { - test_connection_driver_init(a, t, fa, NULL); - test_connection_driver_init(b, t, fb, NULL); - pn_transport_set_server(b->driver.transport); -} - -void test_connection_drivers_destroy(test_connection_driver_t *a, test_connection_driver_t *b) { - test_connection_driver_destroy(a); - test_connection_driver_destroy(b); -} -#endif // TESTS_TEST_DRIVER_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/test_main.cpp ---------------------------------------------------------------------- diff --git a/c/tests/test_main.cpp b/c/tests/test_main.cpp new file mode 100644 index 0000000..2375b7a --- /dev/null +++ b/c/tests/test_main.cpp @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#define CATCH_CONFIG_MAIN +#include <catch.hpp> + +namespace Catch { + +// Same as built-in "console" reporter, but prints the test name before +// running each test, as a progress indicator. Enable with +// -r console.progress +struct ConsoleProgresReporter : ConsoleReporter { + + ConsoleProgresReporter(ReporterConfig const &config) + : ConsoleReporter(config) {} + + static std::string getDescription() { + return "Shows each test-case before running, results as plain lines of " + "text"; + } + + void testCaseStarting(TestCaseInfo const &testCaseInfo) CATCH_OVERRIDE { + stream << "running test case \"" << testCaseInfo.name << '"' << std::endl; + ConsoleReporter::testCaseStarting(testCaseInfo); + } +}; + +INTERNAL_CATCH_REGISTER_REPORTER("console.progress", ConsoleProgresReporter) + +} // namespace Catch http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/test_tools.h ---------------------------------------------------------------------- diff --git a/c/tests/test_tools.h b/c/tests/test_tools.h deleted file mode 100644 index 164968e..0000000 --- a/c/tests/test_tools.h +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef TESTS_TEST_TOOLS_H -#define TESTS_TEST_TOOLS_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 <proton/condition.h> -#include <proton/connection_driver.h> -#include <proton/delivery.h> -#include <proton/event.h> -#include <proton/link.h> -#include <proton/message.h> -#include <proton/proactor.h> -#include <proton/transport.h> -#include <proton/type_compat.h> - -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* Handy way to make pn_bytes: PN_BYTES_LITERAL(FOO) => pn_bytes("FOO",3) */ -#define PN_BYTES_LITERAL(X) (pn_bytes(sizeof(#X)-1, #X)) - -/* A struct to collect the results of a test, created by RUN_TEST macro. */ -typedef struct test_t { - const char* name; - int errors; - uintptr_t data; /* Test can store some non-error data here */ - bool inverted; /* An inverted test prints no output and reports failure if it passes */ -} test_t; - -/* Internal, use macros. Print error message and increase the t->errors count. - All output from test macros goes to stderr so it interleaves with PN_TRACE logs. -*/ -void test_vlogf_(test_t *t, const char *prefix, const char* expr, - const char* file, int line, const char *fmt, va_list ap) -{ - if (t->inverted) return; - fprintf(stderr, "%s:%d", file, line); - if (prefix && *prefix) fprintf(stderr, ": %s", prefix); - if (expr && *expr) fprintf(stderr, ": %s", expr); - if (fmt && *fmt) { - fprintf(stderr, ": "); - vfprintf(stderr, fmt, ap); - } - if (t) fprintf(stderr, " [%s]", t->name); - fprintf(stderr, "\n"); - fflush(stderr); -} - -void test_logf_(test_t *t, const char *prefix, const char* expr, - const char* file, int line, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - test_vlogf_(t, prefix, expr, file, line, fmt, ap); - va_end(ap); -} - -void test_errorf_(test_t *t, const char* expr, - const char* file, int line, const char *fmt, ...) { - ++t->errors; - va_list ap; - va_start(ap, fmt); - test_vlogf_(t, "error", expr, file, line, fmt, ap); - va_end(ap); -} - -bool test_check_(test_t *t, bool expr, const char *sexpr, - const char *file, int line, const char* fmt, ...) { - if (!expr) { - ++t->errors; - va_list ap; - va_start(ap, fmt); - test_vlogf_(t, "check failed", sexpr, file, line, fmt, ap); - va_end(ap); - } - return expr; -} - -/* Call via TEST_ASSERT macros */ -void assert_fail_(const char* expr, const char* file, int line, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - test_vlogf_(NULL, "assertion failed", expr, file, line, fmt, ap); - va_end(ap); - abort(); -} - -/* Unconditional assert (does not depend on NDEBUG) for tests. */ -#define TEST_ASSERT(expr) \ - ((expr) ? (void)0 : assert_fail_(#expr, __FILE__, __LINE__, NULL)) - -/* Unconditional assert with printf-style message (does not depend on NDEBUG) for tests. */ -#define TEST_ASSERTF(expr, ...) \ - ((expr) ? (void)0 : assert_fail_(#expr, __FILE__, __LINE__, __VA_ARGS__)) - -/* Like TEST_ASSERT but includes errno string for err */ -/* TODO aconway 2017-02-16: not thread safe, replace with safe strerror_r or similar */ -#define TEST_ASSERT_ERRNO(expr, err) \ - TEST_ASSERTF((expr), "%s", strerror(err)) - - -/* Print a message but don't mark the test as having an error */ -#define TEST_LOGF(TEST, ...) \ - test_logf_((TEST), "info", NULL, __FILE__, __LINE__, __VA_ARGS__) - -/* Print an error with printf-style message, increment TEST->errors */ -#define TEST_ERRORF(TEST, ...) \ - test_errorf_((TEST), NULL, __FILE__, __LINE__, __VA_ARGS__) - -/* If EXPR is false, print and record an error for t including #EXPR */ -#define TEST_CHECKF(TEST, EXPR, ...) \ - test_check_((TEST), (EXPR), #EXPR, __FILE__, __LINE__, __VA_ARGS__) - -/* If EXPR is false, print and record an error for t including EXPR */ -#define TEST_CHECK(TEST, EXPR) \ - test_check_((TEST), (EXPR), #EXPR, __FILE__, __LINE__, "") - -/* If EXPR is false, print and record an error for t NOT including #EXPR */ -#define TEST_CHECKNF(TEST, EXPR, ...) \ - test_check_((TEST), (EXPR), NULL, __FILE__, __LINE__, __VA_ARGS__) - -bool test_etype_equal_(test_t *t, pn_event_type_t want, pn_event_type_t got, const char *file, int line) { - return test_check_(t, want == got, NULL, file, line, "want %s got %s", - pn_event_type_name(want), - pn_event_type_name(got)); -} -#define TEST_ETYPE_EQUAL(TEST, WANT, GOT) test_etype_equal_((TEST), (WANT), (GOT), __FILE__, __LINE__) - -bool test_int_equal_(test_t *t, int want, int got, const char *file, int line) { - return test_check_(t, want == got, NULL, file, line, "want %d, got %d", want, got); -} -#define TEST_INT_EQUAL(TEST, WANT, GOT) test_int_equal_((TEST), (WANT), (GOT), __FILE__, __LINE__) - -bool test_size_equal_(test_t *t, size_t want, size_t got, const char *file, int line) { - return test_check_(t, want == got, NULL, file, line, "want %zd, got %zd", want, got); -} -#define TEST_SIZE_EQUAL(TEST, WANT, GOT) test_size_equal_((TEST), (WANT), (GOT), __FILE__, __LINE__) - -bool test_str_equal_(test_t *t, const char* want, const char* got, const char *file, int line) { - return test_check_(t, !strcmp(want, got), NULL, file, line, "want '%s', got '%s'", want, got); -} -#define TEST_STR_EQUAL(TEST, WANT, GOT) test_str_equal_((TEST), (WANT), (GOT), __FILE__, __LINE__) - -#define TEST_INSPECT(TEST, WANT, GOT) do { \ - pn_string_t *s = pn_string(NULL); \ - TEST_ASSERT(0 == pn_inspect(GOT, s)); \ - TEST_STR_EQUAL((TEST), (WANT), pn_string_get(s)); \ - pn_free(s); \ - } while (0) - -#define TEST_STR_IN(TEST, WANT, GOT) \ - test_check_((TEST), strstr((GOT), (WANT)), NULL, __FILE__, __LINE__, "'%s' not in '%s'", (WANT), (GOT)) - -#define TEST_COND_EMPTY(TEST, C) \ - TEST_CHECKNF((TEST), (!(C) || !pn_condition_is_set(C)), "Unexpected condition - %s:%s", \ - pn_condition_get_name(C), pn_condition_get_description(C)) - -#define TEST_COND_DESC(TEST, WANT, C) \ - (TEST_CHECKNF(t, pn_condition_is_set((C)), "No condition, expected :%s", (WANT)) ? \ - TEST_STR_IN(t, (WANT), pn_condition_get_description(C)) : 0); - -#define TEST_COND_NAME(TEST, WANT, C) \ - (TEST_CHECKNF(t, pn_condition_is_set((C)), "No condition, expected %s:", (WANT)) ? \ - TEST_STR_EQUAL(t, (WANT), pn_condition_get_name(C)) : 0); - -#define TEST_CONDITION(TEST, NAME, DESC, C) do { \ - TEST_COND_NAME(TEST, NAME, C); \ - TEST_COND_DESC(TEST, DESC, C); \ - } while(0) - -/* T is name of a test_t variable, EXPR is the test expression (which should update T) - FAILED is incremented if the test has errors -*/ -#define RUN_TEST(FAILED, T, EXPR) do { \ - fprintf(stderr, "TEST: %s\n", #EXPR); \ - fflush(stdout); \ - test_t T = { #EXPR, 0 }; \ - (EXPR); \ - if (T.errors && !t.inverted) { \ - fprintf(stderr, "FAIL: %s (%d errors)\n", #EXPR, T.errors); \ - ++(FAILED); \ - } else if (!T.errors && t.inverted) { \ - fprintf(stderr, "UNEXPECTED PASS: %s", #EXPR); \ - ++(FAILED); \ - } \ - } while(0) - -/* Like RUN_TEST but only if one of the argv strings is found in the test EXPR */ -#define RUN_ARGV_TEST(FAILED, T, EXPR) do { \ - if (argc == 1) { \ - RUN_TEST(FAILED, T, EXPR); \ - } else { \ - for (int i = 1; i < argc; ++i) { \ - if (strstr(#EXPR, argv[i])) { \ - RUN_TEST(FAILED, T, EXPR); \ - break; \ - } \ - } \ - } \ - } while(0) - -/* Ensure buf has at least size bytes, use realloc if need be */ -void rwbytes_ensure(pn_rwbytes_t *buf, size_t size) { - if (buf->start == NULL || buf->size < size) { - buf->start = (char*)realloc(buf->start, size); - buf->size = size; - } -} - -static const size_t BUF_MIN = 1024; - -/* Encode message m into buffer buf, return the size. - * The buffer is expanded using realloc() if needed. - */ -size_t message_encode(pn_message_t* m, pn_rwbytes_t *buf) { - int err = 0; - rwbytes_ensure(buf, BUF_MIN); - size_t size = buf->size; - while ((err = pn_message_encode(m, buf->start, &size)) != 0) { - if (err == PN_OVERFLOW) { - rwbytes_ensure(buf, buf->size * 2); - size = buf->size; - } else { - TEST_ASSERTF(err == 0, "encoding: %s %s", pn_code(err), pn_error_text(pn_message_error(m))); - } - } - return size; -} - -/* Decode message from delivery d into message m. - * Use buf to hold intermediate message data, expand with realloc() if needed. - */ -void message_decode(pn_message_t *m, pn_delivery_t *d, pn_rwbytes_t *buf) { - pn_link_t *l = pn_delivery_link(d); - ssize_t size = pn_delivery_pending(d); - rwbytes_ensure(buf, size); - ssize_t result = pn_link_recv(l, buf->start, size); - TEST_ASSERTF(size == result, "%ld != %ld", (long)size, (long)result); - pn_message_clear(m); - TEST_ASSERTF(!pn_message_decode(m, buf->start, size), "decode: %s", pn_error_text(pn_message_error(m))); -} - -#endif // TESTS_TEST_TOOLS_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/c/tests/url_test.cpp ---------------------------------------------------------------------- diff --git a/c/tests/url_test.cpp b/c/tests/url_test.cpp new file mode 100644 index 0000000..027799f --- /dev/null +++ b/c/tests/url_test.cpp @@ -0,0 +1,137 @@ +/* + * + * 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. + * + */ + +#define PN_USE_DEPRECATED_API 1 + +#include "./pn_test.hpp" + +#include "proton/error.h" +#include "proton/type_compat.h" +#include "proton/url.h" + +using namespace pn_test; +using Catch::Matchers::Equals; + +void check_url(const char *url, const char *scheme, const char *user, + const char *pass, const char *host, const char *port, + const char *path, bool round_trip = true) { + INFO("url=\"" << url << '"'); + auto_free<pn_url_t, pn_url_free> purl(pn_url_parse(url)); + CHECK_THAT(scheme, Equals(pn_url_get_scheme(purl))); + CHECK_THAT(user, Equals(pn_url_get_username(purl))); + CHECK_THAT(pass, Equals(pn_url_get_password(purl))); + CHECK_THAT(host, Equals(pn_url_get_host(purl))); + CHECK_THAT(port, Equals(pn_url_get_port(purl))); + CHECK_THAT(path, Equals(pn_url_get_path(purl))); + if (round_trip) CHECK_THAT(url, Equals(pn_url_str(purl))); +} + +TEST_CASE("url") { + const char *null = 0; + check_url("/Foo.bar:90087@somewhere", null, null, null, null, null, + "Foo.bar:90087@somewhere"); + check_url("host", null, null, null, "host", null, null); + check_url("host:423", null, null, null, "host", "423", null); + check_url("user@host", null, "user", null, "host", null, null); + + // Can't round-trip passwords with ':', not strictly legal + // but the parser allows it. + check_url("user:1243^&^:pw@host:423", null, "user", "1243^&^:pw", "host", + "423", null, false); + check_url("user:1243^&^:pw@host:423/Foo.bar:90087", null, "user", + "1243^&^:pw", "host", "423", "Foo.bar:90087", false); + check_url("user:1243^&^:pw@host:423/Foo.bar:90087@somewhere", null, "user", + "1243^&^:pw", "host", "423", "Foo.bar:90087@somewhere", false); + + check_url("[::1]:amqp", null, null, null, "::1", "amqp", null); + check_url("user@[::1]", null, "user", null, "::1", null, null); + check_url("user@[::1]:amqp", null, "user", null, "::1", "amqp", null); + + // Can't round-trip passwords with ':', not strictly legal + // but the parser allows it. + check_url("user:1243^&^:pw@[::1]:amqp", null, "user", "1243^&^:pw", "::1", + "amqp", null, false); + check_url("user:1243^&^:pw@[::1]:amqp/Foo.bar:90087", null, "user", + "1243^&^:pw", "::1", "amqp", "Foo.bar:90087", false); + check_url("user:1243^&^:pw@[::1:amqp/Foo.bar:90087", null, "user", + "1243^&^:pw", "[::1", "amqp", "Foo.bar:90087", false); + check_url("user:1243^&^:pw@::1]:amqp/Foo.bar:90087", null, "user", + "1243^&^:pw", "::1]", "amqp", "Foo.bar:90087", false); + + check_url("amqp://user@[::1]", "amqp", "user", null, "::1", null, null); + check_url("amqp://user@[::1]:amqp", "amqp", "user", null, "::1", "amqp", + null); + check_url("amqp://user@[1234:52:0:1260:f2de:f1ff:fe59:8f87]:amqp", "amqp", + "user", null, "1234:52:0:1260:f2de:f1ff:fe59:8f87", "amqp", null); + + // Can't round-trip passwords with ':', not strictly legal + // but the parser allows it. + check_url("amqp://user:1243^&^:pw@[::1]:amqp", "amqp", "user", "1243^&^:pw", + "::1", "amqp", null, false); + check_url("amqp://user:1243^&^:pw@[::1]:amqp/Foo.bar:90087", "amqp", "user", + "1243^&^:pw", "::1", "amqp", "Foo.bar:90087", false); + + check_url("amqp://host", "amqp", null, null, "host", null, null); + check_url("amqp://user@host", "amqp", "user", null, "host", null, null); + check_url("amqp://user@host/path:%", "amqp", "user", null, "host", null, + "path:%"); + check_url("amqp://user@host:5674/path:%", "amqp", "user", null, "host", + "5674", "path:%"); + check_url("amqp://user@host/path:%", "amqp", "user", null, "host", null, + "path:%"); + check_url("amqp://bigbird@host/queue@host", "amqp", "bigbird", null, "host", + null, "queue@host"); + check_url("amqp://host/queue@host", "amqp", null, null, "host", null, + "queue@host"); + check_url("amqp://host:9765/queue@host", "amqp", null, null, "host", "9765", + "queue@host"); + check_url("user:pass%2fword@host", null, "user", "pass/word", "host", null, + null, false); + check_url("user:pass%2Fword@host", null, "user", "pass/word", "host", null, + null); + // Can't round-trip passwords with lowercase hex encoding + check_url("us%2fer:password@host", null, "us/er", "password", "host", null, + null, false); + check_url("us%2Fer:password@host", null, "us/er", "password", "host", null, + null); + // Can't round-trip passwords with lowercase hex encoding + check_url("user:pass%2fword%@host", null, "user", "pass/word%", "host", null, + null, false); + check_url("localhost/temp-queue://" + "ID:ganymede-36663-1408448359876-2:123:0", + null, null, null, "localhost", null, + "temp-queue://ID:ganymede-36663-1408448359876-2:123:0"); + check_url("/temp-queue://ID:ganymede-36663-1408448359876-2:123:0", null, null, + null, null, null, + "temp-queue://ID:ganymede-36663-1408448359876-2:123:0"); + check_url("amqp://localhost/temp-queue://" + "ID:ganymede-36663-1408448359876-2:123:0", + "amqp", null, null, "localhost", null, + "temp-queue://ID:ganymede-36663-1408448359876-2:123:0"); + // PROTON-995 + check_url("amqps://%40user%2F%3A:%40pass%[email protected]/" + "some_topic", + "amqps", "@user/:", "@pass/:", "example.net", null, "some_topic"); + check_url("amqps://user%2F%3A=:pass%2F%[email protected]/some_topic", "amqps", + "user/:=", "pass/:=", "example.net", null, "some_topic"); + // Really perverse url + check_url("://:@://:", "", "", "", null, "", "/:"); +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 794fcbe..794eb29 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -282,7 +282,6 @@ add_cpp_test(map_test) add_cpp_test(scalar_test) add_cpp_test(value_test) add_cpp_test(container_test) -add_cpp_test(url_test) add_cpp_test(reconnect_test) add_cpp_test(link_test) if (ENABLE_JSONCPP) @@ -292,3 +291,22 @@ if (ENABLE_JSONCPP) # Test data and output directories for connect_config_test file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/testdata" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") endif() + +# TODO aconway 2018-10-31: Catch2 tests +# This is a simple example of a C++ test using the Catch2 framework. +# See c/tests/ for more interesting examples. +# Eventually all the C++ tests will migrate to Catch2. + +include_directories(${CMAKE_SOURCE_DIR}/tests/include) +add_executable(cpp-test src/cpp-test.cpp src/url_test.cpp) +target_link_libraries(cpp-test qpid-proton-cpp ${PLATFORM_LIBS}) + +macro(add_catch_test tag) + add_test ( + NAME cpp-${tag}-test + COMMAND ${PN_ENV_SCRIPT} -- ${test_env} + ${TEST_EXE_PREFIX_CMD} $<TARGET_FILE:cpp-test> "[${tag}]" + ) +endmacro(add_catch_test) + +add_catch_test(url) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/cpp/src/cpp-test.cpp ---------------------------------------------------------------------- diff --git a/cpp/src/cpp-test.cpp b/cpp/src/cpp-test.cpp new file mode 100644 index 0000000..12a09dc --- /dev/null +++ b/cpp/src/cpp-test.cpp @@ -0,0 +1,21 @@ +/* + * 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. + */ + +#define CATCH_CONFIG_MAIN +#include <catch.hpp> http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/0bdba37d/cpp/src/url_test.cpp ---------------------------------------------------------------------- diff --git a/cpp/src/url_test.cpp b/cpp/src/url_test.cpp index 511c8d5..90f56fb 100644 --- a/cpp/src/url_test.cpp +++ b/cpp/src/url_test.cpp @@ -17,82 +17,64 @@ * under the License. */ -#include "test_bits.hpp" +#include <catch.hpp> #include <proton/url.hpp> namespace { +using proton::url; -#define CHECK_URL(S, SCHEME, USER, PWD, HOST, PORT, PATH) do { \ - proton::url u(S); \ - ASSERT_EQUAL(SCHEME, u.scheme()); \ - ASSERT_EQUAL(USER, u.user()); \ - ASSERT_EQUAL(PWD, u.password()); \ - ASSERT_EQUAL(HOST, u.host()); \ - ASSERT_EQUAL(PORT, u.port()); \ - ASSERT_EQUAL(PATH, u.path()); \ +#define CHECK_URL(U, SCHEME, USER, PWD, HOST, PORT, PATH) do { \ + CHECK((SCHEME) == (U).scheme()); \ + CHECK((USER) == (U).user()); \ + CHECK((PWD) == (U).password()); \ + CHECK((HOST) == (U).host()); \ + CHECK((PORT) == (U).port()); \ + CHECK((PATH) == (U).path()); \ } while(0) -void parse_to_string_test() { - CHECK_URL("amqp://foo:xyz/path", - "amqp", "", "", "foo", "xyz", "path"); - CHECK_URL("amqp://username:password@host:1234/path", - "amqp", "username", "password", "host", "1234", "path"); - CHECK_URL("host:1234", - "amqp", "", "", "host", "1234", ""); - CHECK_URL("host", - "amqp", "", "", "host", "amqp", ""); - CHECK_URL("host/path", - "amqp", "", "", "host", "amqp", "path"); - CHECK_URL("amqps://host", - "amqps", "", "", "host", "amqps", ""); - CHECK_URL("/path", - "amqp", "", "", "localhost", "amqp", "path"); - CHECK_URL("", - "amqp", "", "", "localhost", "amqp", ""); - CHECK_URL(":1234", - "amqp", "", "", "localhost", "1234", ""); +TEST_CASE("parse URL","[url]") { + SECTION("full and defaulted") { + CHECK_URL(url("amqp://foo:xyz/path"), + "amqp", "", "", "foo", "xyz", "path"); + CHECK_URL(url("amqp://username:password@host:1234/path"), + "amqp", "username", "password", "host", "1234", "path"); + CHECK_URL(url("host:1234"), + "amqp", "", "", "host", "1234", ""); + CHECK_URL(url("host"), + "amqp", "", "", "host", "amqp", ""); + CHECK_URL(url("host/path"), + "amqp", "", "", "host", "amqp", "path"); + CHECK_URL(url("amqps://host"), + "amqps", "", "", "host", "amqps", ""); + CHECK_URL(url("/path"), + "amqp", "", "", "localhost", "amqp", "path"); + CHECK_URL(url(""), + "amqp", "", "", "localhost", "amqp", ""); + CHECK_URL(url(":1234"), + "amqp", "", "", "localhost", "1234", ""); + } + SECTION("starting with //") { + CHECK_URL(url("//username:password@host:1234/path"), + "amqp", "username", "password", "host", "1234", "path"); + CHECK_URL(url("//host:port/path"), + "amqp", "", "", "host", "port", "path"); + CHECK_URL(url("//host"), + "amqp", "", "", "host", "amqp", ""); + CHECK_URL(url("//:port"), + "amqp", "", "", "localhost", "port", ""); + CHECK_URL(url("//:0"), + "amqp", "", "", "localhost", "0", ""); + } + SECTION("no defaults") { + CHECK_URL(url("", false), + "", "", "", "", "", ""); + CHECK_URL(url("//:", false), + "", "", "", "", "", ""); + CHECK_URL(url("//:0", false), + "", "", "", "", "0", ""); + CHECK_URL(url("//h:", false), + "", "", "", "h", "", ""); + } } -void parse_slash_slash() { - CHECK_URL("//username:password@host:1234/path", - "amqp", "username", "password", "host", "1234", "path"); - CHECK_URL("//host:port/path", - "amqp", "", "", "host", "port", "path"); - CHECK_URL("//host", - "amqp", "", "", "host", "amqp", ""); - CHECK_URL("//:port", - "amqp", "", "", "localhost", "port", ""); - CHECK_URL("//:0", - "amqp", "", "", "localhost", "0", ""); -} - -#define CHECK_URL_NODEFAULT(S, SCHEME, USER, PWD, HOST, PORT, PATH) do { \ - proton::url u(S, false); \ - ASSERT_EQUAL(SCHEME, u.scheme()); \ - ASSERT_EQUAL(USER, u.user()); \ - ASSERT_EQUAL(PWD, u.password()); \ - ASSERT_EQUAL(HOST, u.host()); \ - ASSERT_EQUAL(PORT, u.port()); \ - ASSERT_EQUAL(PATH, u.path()); \ - } while(0) - -} - -void parse_nodefault() { - CHECK_URL_NODEFAULT("", - "", "", "", "", "", ""); - CHECK_URL_NODEFAULT("//:", - "", "", "", "", "", ""); - CHECK_URL_NODEFAULT("//:0", - "", "", "", "", "0", ""); - CHECK_URL_NODEFAULT("//h:", - "", "", "", "h", "", ""); -} - -int main(int, char**) { - int failed = 0; - RUN_TEST(failed, parse_to_string_test()); - RUN_TEST(failed, parse_slash_slash()); - RUN_TEST(failed, parse_nodefault()); - return failed; -} +} // namespace --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
