From commits-return-45995-archive-asf-public=cust-asf.ponee.io@qpid.apache.org Wed Jul 4 00:12:55 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id B037C1807A3 for ; Wed, 4 Jul 2018 00:12:52 +0200 (CEST) Received: (qmail 62267 invoked by uid 500); 3 Jul 2018 22:12:51 -0000 Mailing-List: contact commits-help@qpid.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@qpid.apache.org Delivered-To: mailing list commits@qpid.apache.org Received: (qmail 61886 invoked by uid 99); 3 Jul 2018 22:12:51 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Jul 2018 22:12:51 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5FC92E0BEA; Tue, 3 Jul 2018 22:12:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: aconway@apache.org To: commits@qpid.apache.org Date: Tue, 03 Jul 2018 22:12:57 -0000 Message-Id: In-Reply-To: <506ba33a6fed44e08b20ccd012e637c7@git.apache.org> References: <506ba33a6fed44e08b20ccd012e637c7@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [08/89] [abbrv] [partial] qpid-proton git commit: PROTON-1728: Reorganize the source tree http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/reactor.c ---------------------------------------------------------------------- diff --git a/c/tests/reactor.c b/c/tests/reactor.c new file mode 100644 index 0000000..900d6a3 --- /dev/null +++ b/c/tests/reactor.c @@ -0,0 +1,578 @@ +/* + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/37136940/c/tests/refcount.c ---------------------------------------------------------------------- diff --git a/c/tests/refcount.c b/c/tests/refcount.c new file mode 100644 index 0000000..487f115 --- /dev/null +++ b/c/tests/refcount.c @@ -0,0 +1,393 @@ +/* + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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/37136940/c/tests/ssl-certs/README.txt ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/README.txt b/c/tests/ssl-certs/README.txt new file mode 100644 index 0000000..9a8a4f9 --- /dev/null +++ b/c/tests/ssl-certs/README.txt @@ -0,0 +1,24 @@ +This directory contains basic self signed test certificates for use by +proton examples. + +The ".pem" files are in the format expected by proton implementations +using OpenSSL. The ".p12" file are for Windows implementations using +SChannel. + +The commands used to generate the certificates follow. + + +make_pn_cert() +{ + name=$1 + subject=$2 + passwd=$3 + # create the pem files + openssl req -newkey rsa:2048 -keyout $name-private-key.pem -out $name-certificate.pem -subj $subject -passout pass:$passwd -x509 -days 3650 + # create the p12 files + openssl pkcs12 -export -out $name-full.p12 -passin pass:$passwd -passout pass:$passwd -inkey $name-private-key.pem -in $name-certificate.pem -name $name + openssl pkcs12 -export -out $name-certificate.p12 -in $name-certificate.pem -name $name -nokeys -passout pass: +} + +make_pn_cert tserver /CN=test_server/OU=proton_test tserverpw +make_pn_cert tclient /CN=test_client/OU=proton_test tclientpw http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tclient-certificate.p12 ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tclient-certificate.p12 b/c/tests/ssl-certs/tclient-certificate.p12 new file mode 100644 index 0000000..4d0e000 Binary files /dev/null and b/c/tests/ssl-certs/tclient-certificate.p12 differ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tclient-certificate.pem ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tclient-certificate.pem b/c/tests/ssl-certs/tclient-certificate.pem new file mode 100644 index 0000000..8088e2e --- /dev/null +++ b/c/tests/ssl-certs/tclient-certificate.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKzCCAhOgAwIBAgIJAIV7frIjftgcMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV +BAMMC3Rlc3RfY2xpZW50MRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx +ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3RfY2xpZW50MRQw +EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAPCIS4qUdOtQplUxZ6WW0LXcvosqFP6qOiCARLSEWpR3B8bq213rzefwwfcM +4TtMr88bP+huLKmlyMfwpl8yB88eXkscPgaAce2zk24urWkFXKSQ6GPitWBLGqBa +V+W0wJ4mfW7MwefVslWfGXI381QEUlBHjkFG30AtzMMTRj2GK2JqUlRXZPljGyB7 +WcXwxcoS+HkKV7FtHWSkLAzyXwQ9vsCUEYdWTUaGXfCUNRSRV7h1LIANbu03NxV0 +XdEl7WXcr7tuTw3axeUGhRFVhLegrxKLuZTTno4aAJnEr8uaDzjxvXnv3Ne2igvy +gRfZgOMx+XrZEob9OpAoRghQt4cCAwEAAaNQME4wHQYDVR0OBBYEFE4vbyiM0RjG +TLMLLGGhMZE/5x1GMB8GA1UdIwQYMBaAFE4vbyiM0RjGTLMLLGGhMZE/5x1GMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAErr/rvLS9Ig0UCMwh1J1lA9 +/gvXf93iIK/SjrFIAqYRmfZxg4husfoes8t2hFUeuqoH05TuSOoXG8p8DpgTSGmF +jAFe+T90vJZTm0oqZkkkI/hdzjGQoHURRp9/O2Z/lm39KSKGVAN5pUWCUDi/G5iS +P9LZPJN6a5syXMrR6x62IPxAXowlpXkRghKClF3zPOaOBTzT1V27EkI8IEgC+p45 +246EooLnw8ibB+ucNc3KHNzpgKGVd/622+I+Q5eg9AT9PLFttP+R2ECsrVDDPYuA +p0qaSnwgeozj/d6K3FOgKKEKbzBmpWgkv0jdcVk18aPMHypI/RDtZ/+3ET2Ksi8= +-----END CERTIFICATE----- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tclient-full.p12 ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tclient-full.p12 b/c/tests/ssl-certs/tclient-full.p12 new file mode 100644 index 0000000..ad2d7d3 Binary files /dev/null and b/c/tests/ssl-certs/tclient-full.p12 differ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tclient-private-key.pem ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tclient-private-key.pem b/c/tests/ssl-certs/tclient-private-key.pem new file mode 100644 index 0000000..e5c114d --- /dev/null +++ b/c/tests/ssl-certs/tclient-private-key.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQICy6ghWp45z4CAggA +MBQGCCqGSIb3DQMHBAiVdDoo4NIghQSCBMixGm1bm/omMxsaKnIPO7zm5dyLexJ+ +yTFpmh2KV7kQqmpzCyIOdoG6K8YqFnie2XdFWm3S8faRHoMq54bDmyEWIxfQPq5f +I1iYFbIZkbnhUvK53RActsEUMf0locS4xylU7VQK3XTAwp0TVip3Lp3ehEMEdcXL +iUWibGsoTPKcY9MIWGXZAJXsEXoeHt6k2hHo1G4E0/Bi6mLW1LY/cxZCjHTGD6qI +Kt54SCCDvinqVa+rixw6yX9F14EA6bhALami8e+Ccd3lqHOyYlXcBaSS1ezCg6ig +oNK97mC+gEGy1KlkZDKWXclFoOCBXRBe4DByre6Rlq3yeI9L42bvAuSBSmf5QT5g +73Yl8vjEAKR65awBT09dPuKu7t+Fb6vkwF8/t+uyj9IuL+42UuXhMLK3ohf+6DbU +8/zB4y3GXI80QmWM0+Wx4n6khFhPFLHt2q0Sn6V9PG1vtHyiq50oSCoyrPQLaecp +hefnMCFBYTcT3JUwmoVGGy0boIAwL7T4aGsMt7QhwOx5tU35tKFxyY7m4fX14AKo +2EIy+TPQwCGkGf3Puy/Pc9VA8IAxB5+WwSrjk+NeCv88eIX7gy43k4rCr+OmD9FF +wknr3xoP3KYhNXjdZ4Ep/1UHSK+JAtzzbNLQjDcqN+gQPg/yUX6ih0j5K3Wvh9bK +E/DvzbpJroUZPgzR+8z5O68CfsD+OIdpHBFTKqAFmzvUuqpADpr998LdCjD+lW+V +xZZgZa8KEblwgiH3fdGbYl46Ho1zrZisf439DbqyybAuBIQB4NSZcL/MAgVGO17k +QDpVElWZWYrFm4CFTcvS2HvIzRmbefF5m5oJedsN7Q6WQCp+3gnwYx1xIOknd7pW +N4AHNnqjscSj9yACj/EiBVKAKNnC5H7ZGZTsaAjMETZyjLXfI2AZ3Fviz4zFR+oz +NkAfFB6WUpRpl7H02FzrzYT7XkkLcXd6H6g+mv2iDa9uKWk/PS2QlqnJt8/dHEHD +JKTG331yDK5GHlKAVGF3nP5BwFGgTQMuSoeiOervMXPUwDpQ8OaYkuaRej0cZLgT +kAF9sUjqdsoYNcXDFHALp6y5g8qYkfrxrlIbKs82zIsmB5I+dtZbUaD3a0zAUrmW +5Xm3Pc9dVP0EXKwfHz6zqPReEw2yYLisB5IoHd4M2wa3GzHBdra1ij4QTmvd3o7e +buGFoX8KJQAcig0zpbYkoDP2gPhIh9rY4unVPQNX1Q8/wRsiJAZZsYvZY+A+SmuZ +bwSwk+8ZJRsFzdYYYhQeRytD5cDAIQiClcI5Yj4T9dWQV/gf0N/wIBDNTMp0jJAy +1l7PuXTfGZodNJWZH0oqsrNoWbn/k67NildvvofIKX+h09Nxszr670Pvj0qoHd5/ +CWq30lnxoJBUgbikFOz6ZuuHi/ZiCXL+haH+v8hJKN5ptRKnyYJQHchRB/IOGRoT +5lmWxo8a7K+yXhp0VBDHJfw3685ms0xQX8Xj4X3MEuN64zd0fB1JmhtP12ydK85J +ABawNKlRQPw5weckwtCviXQX+vX25S/xu3xA6IuqlHyqL/1t3DICzuxeOyT2mZxD +tKQxEgNihPvu32vn9m74qA3adEaxuWPRkPZuTeITHOkMTZolvqYX/5olBsSgYwka +7/g= +-----END ENCRYPTED PRIVATE KEY----- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tserver-certificate.p12 ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tserver-certificate.p12 b/c/tests/ssl-certs/tserver-certificate.p12 new file mode 100644 index 0000000..f38b67d Binary files /dev/null and b/c/tests/ssl-certs/tserver-certificate.p12 differ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tserver-certificate.pem ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tserver-certificate.pem b/c/tests/ssl-certs/tserver-certificate.pem new file mode 100644 index 0000000..86231f3 --- /dev/null +++ b/c/tests/ssl-certs/tserver-certificate.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKzCCAhOgAwIBAgIJAPnYOOQCJ3kDMA0GCSqGSIb3DQEBCwUAMCwxFDASBgNV +BAMMC3Rlc3Rfc2VydmVyMRQwEgYDVQQLDAtwcm90b25fdGVzdDAeFw0xNTExMjcx +ODEwMzlaFw0yNTExMjQxODEwMzlaMCwxFDASBgNVBAMMC3Rlc3Rfc2VydmVyMRQw +EgYDVQQLDAtwcm90b25fdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAKJNB78lgw4KtXDAvXocTLud6mbn6zgfB6ETIF+kcrukOH9DnPxjLBBM4Lig +sp1+kmeudFK5/X8riDrvIW52b/rlEBLgLB+oDtI74m6OTbBs9L+FUFYOuxApetQF +qoJy2vf9pWfy4uku24vCpeo7eVLi6ypu4lXE3LR+Km3FruHI1NKonHBMhwXSOWqF +pYM6/4IZJ4fbV0+eU0Jrx+05s6XHg5vone2BVJKxeSIBje+zWnNnh8+qG0Z70Jgp +aMetME5KGnLNgD1okpH0vb3lwjvuqkkx4WswGVZGbLLkSqqBpXPyM9fCFVy5aKSL +DBq7IABQtO67O2nBzK3OyigHrUUCAwEAAaNQME4wHQYDVR0OBBYEFGV1PY0FCFbJ +gpcDVKI6JGiRTt3kMB8GA1UdIwQYMBaAFGV1PY0FCFbJgpcDVKI6JGiRTt3kMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIx1TOTGWnnbpan4bse7wuvH +GYSNDJhoTVS+X1TC63xukJD1JBAsCNTqg/ZV6lN3XEl7vvOXfGoCiyXM6a9XOKUo +gSDtMrIr+wTh6Ss1yRO8QcCJmxH5JDXNu1ojtwsjFW/vneI4IL9kwpDsSlMQEX/E +EkkQwtAx/Cvfe7pecZL4qSeykJOUMTts9H8fCAZqEiRZBA3ugJxqF8jwLP3DoFVQ +6QZzKDY6CSPqfMnVb5i0MAIYVDpau+e3N9dgQpZD22F/zbua0OVbfAPdiRMnYxML +FT4sxLnh+5YVqwpVWbEKp4onHe2Fq6YIvAxUYAJ3SBA2C8O2RAVKWxf1jko3jYI= +-----END CERTIFICATE----- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tserver-full.p12 ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tserver-full.p12 b/c/tests/ssl-certs/tserver-full.p12 new file mode 100644 index 0000000..d4a0e40 Binary files /dev/null and b/c/tests/ssl-certs/tserver-full.p12 differ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl-certs/tserver-private-key.pem ---------------------------------------------------------------------- diff --git a/c/tests/ssl-certs/tserver-private-key.pem b/c/tests/ssl-certs/tserver-private-key.pem new file mode 100644 index 0000000..91dcf0e --- /dev/null +++ b/c/tests/ssl-certs/tserver-private-key.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI1cT0c2J3GcQCAggA +MBQGCCqGSIb3DQMHBAi1hxSX2LJ+EgSCBMheHJ0iXr5A36Natjk/LcAEeKUMT9s+ +sMzoQceCWe8qMlQluWksr9iDdZ4JRIE8cpK8dbmx4dLY/SShUzdlhJHCSa4zZBHq +8cZ/jGUF/RF1rqdgjK589eUq+uOl3/gXKzG/SxBqayy6PSn12kX3qnvmlkXCmtwU +lg+iBm5wRcJ0MyVHaJkyA8sW8gr186C/VAau6Yu0crQXN7NRo9snrd4ewuYMIEhZ +hgaG9XsYQWB1bPhAaKj80CZGxsQbJyTwcbKKkB3IY4WXx8mmhuiNl+vKT3HBJ9Ju +YB6tgIjs8CJ4X2P4aU3yNJwG1QldgHSqmFGQ19bcZAw3s3kzwjdzRf4H2V16XOBd +zQ5AEs/ffVMzMIAfkb1gYwgunZ2CVwwDJ2mi1RcgkX+Og2aFQc+fxXcVOnDcGLxV +6fuCuZ2lsXfoiIyRh9kj3L75N12GtVUvgBdnMuOc1wPw6XnGQtDwt0acJpdexLMG +k0j57r/gcgzTcmF3qNM+y9L/HLssgrJkvVJw2Np5gmtIyfDocsDUWUbClS4dTpYf +oTngUTU+vWtHBuaUnb+f5/WJaRS/S7mmR8usbVG3i9WnEr/vlPJpbJFSjW2S6u/H +7cFxKUmmBZsSuEv/EKt9a+Sh62kprOChm4myqfCI1/gvNKfUZC6m0Vp8zf+2LgAq +2RgbMuqysMjWUtV4kDRZT7oCYckUDwsCHdbLES3nmVrtBk2ShMKHBpDp8/GoRuiV +jdV7/EjKM/M1kXtFYYe3z7Mxv++lKYIJ7bNwVrQ8nrhce/VwHw6D5emWXNCJXhKZ +FW7EM2ZOZ9eaKOlCsIi8sbjV6Yie9IY6HJKKmi3CpO0Tv5kLBdHkru8vGCSFm3O1 +n7wz7Ys5FBSlZ19X0NwQSCQX1Q4w+tido6i1SCRX0qJEdTNGuGwVXMHCf4/1zyHV +hj8vnxh8fzo79LFrwlTTgwLg1Mr8sEUFFDJ/raJ1AhFXi8n24trtNR8EHxRW8wtD +CLCKaqkEqfBiFXK/Yq3RrefCayPHiD+DaNsI8BwefMGpED3vD8YYCjAzXNPh/CSF +sc1i1jWMzbJhzOoFSPNXhlfusbUFMFQ/6olatmH47SY6HBBOL3DDP5uQ0jw8P454 +QBjlMOpEZmZxO6TcEtJwu0vzgog4rQ5g3NWy6SIpjWehNwTynLt7yM3R5WTI6cZs +0GTv/rqo2/SUoNsFmnGIUwj/DrBe4XOAq1nS2ZlEctxKhBsKH0hMFp6D1rXOzrgl +bwcq+oistoB0TLcThShyNgSqzW1znQ1n5SVUk9b5rRhSttJxn3yOMewH0i3v8bPo +HOhP5kaGjblPsCYyhlL/SNVF0OXEGTwLNey7FQdWFOwVwTRRXe7k+uGZ2d5hg+Jn +It/trDZ1RDYbVmB7/Qy73c16J4mvhOUJ2de5ZciFBjkidbiiUKLj9xnjK9k9Sauo +MKhNnDMAEU5VDQM3xNe5BRdX8dFLwfF5H64sU3nROF83aUnDgvfFEowYPnCuPYfm +m4aQHfoBSg4j3v1OeOwktcl+Q2TjxPHfWhbWeRBfxOTqQ/suYhnQChuFSK/qyo9K +ccgotqghhunRsWMoZT25H7AZM6yKb1sMz/0oyMRIKeGqoYh+ULM5XLY0xNYd4/xU +WtQ= +-----END ENCRYPTED PRIVATE KEY----- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/ssl.c ---------------------------------------------------------------------- diff --git a/c/tests/ssl.c b/c/tests/ssl.c new file mode 100644 index 0000000..9acb362 --- /dev/null +++ b/c/tests/ssl.c @@ -0,0 +1,71 @@ +/* + * 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 + +#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/37136940/c/tests/test_config.h.in ---------------------------------------------------------------------- diff --git a/c/tests/test_config.h.in b/c/tests/test_config.h.in new file mode 100644 index 0000000..d1d3a18 --- /dev/null +++ b/c/tests/test_config.h.in @@ -0,0 +1,26 @@ +#ifndef TESTS_TEST_CONFIG_H +#define TESTS_TEST_CONFIG_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. + */ + +/* Make source tree locations available to tests */ +#define CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@" + +#endif // TESTS_TEST_CONFIG_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/test_handler.h ---------------------------------------------------------------------- diff --git a/c/tests/test_handler.h b/c/tests/test_handler.h new file mode 100644 index 0000000..108d0d9 --- /dev/null +++ b/c/tests/test_handler.h @@ -0,0 +1,170 @@ +#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 + +/* 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_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"); + 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; +} + +#endif // TESTS_TEST_DRIVER_H http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tests/test_tools.h ---------------------------------------------------------------------- diff --git a/c/tests/test_tools.h b/c/tests/test_tools.h new file mode 100644 index 0000000..d046a43 --- /dev/null +++ b/c/tests/test_tools.h @@ -0,0 +1,239 @@ +#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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* 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 */ +} 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) +{ + 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_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_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); + +/* 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) { \ + fprintf(stderr, "FAIL: %s (%d errors)\n", #EXPR, T.errors); \ + ++(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); + TEST_ASSERT(size == pn_link_recv(l, buf->start, size)); + 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/37136940/c/tests/valgrind.supp ---------------------------------------------------------------------- diff --git a/c/tests/valgrind.supp b/c/tests/valgrind.supp new file mode 100644 index 0000000..282a18c --- /dev/null +++ b/c/tests/valgrind.supp @@ -0,0 +1,131 @@ +{ + SSL does a number of uninitialized accesses (expected) 1 + Memcheck:Cond + fun:BN_bin2bn + obj:* + obj:* +} + +{ + SSL does a number of uninitialized accesses (expected) 2 + Memcheck:Cond + fun:BN_num_bits_word + fun:BN_num_bits +} + +{ + SSL does a number of uninitialized accesses (expected) 3 + Memcheck:Value8 + fun:BN_num_bits_word + fun:BN_num_bits + fun:BN_mod_exp_mont_consttime + obj:* + fun:ssl3_ctx_ctrl +} + +{ + SSL does a number of uninitialized accesses (expected) 4 + Memcheck:Value8 + fun:BN_mod_exp_mont_consttime + obj:* + fun:ssl3_ctx_ctrl +} + +{ + SSL does a number of uninitialized accesses (FreeBSD version) + Memcheck:Value8 + fun:BN_num_bits_word + fun:BN_num_bits + fun:BN_mod_exp_mont_consttime + fun:BN_mod_exp_mont + obj:*libcrypto.so* + fun:ssl3_ctx_ctrl +} + +{ + SSL does a number of uninitialized accesses (FreeBSD version) + Memcheck:Value8 + fun:BN_mod_exp_mont_consttime + fun:BN_mod_exp_mont + obj:*libcrypto.so* + fun:ssl3_ctx_ctrl +} + +{ + SSL does a number of uninitialized accesses (expected) 5 + Memcheck:Value4 + fun:BN_mod_exp_mont_consttime + fun:BN_mod_exp_mont + obj:* + obj:* +} + +{ + SSL does a number of uninitialized accesses (expected) 6 + Memcheck:Value4 + fun:BN_num_bits_word + fun:BN_mod_exp_mont_consttime + fun:BN_mod_exp_mont + obj:* + obj:* +} + +{ + SSL does a number of uninitialized accesses (expected) 7 + Memcheck:Cond + fun:ASN1_STRING_set + fun:ASN1_mbstring_ncopy + fun:ASN1_mbstring_copy +} + +{ + Since we can never safely uninitialize SSL, allow this + Memcheck:Leak + fun:_vgrZU_libcZdsoZa_realloc + fun:CRYPTO_realloc + fun:lh_insert + obj:/lib64/libcrypto.so.0.9.8e + fun:ERR_load_strings + fun:ERR_load_X509V3_strings + fun:ERR_load_crypto_strings + fun:SSL_load_error_strings +} + +{ + Since we can never safely uninitialize SSL, allow this + Memcheck:Leak + fun:_vgrZU_libcZdsoZa_malloc + fun:CRYPTO_malloc + fun:lh_new + fun:OBJ_NAME_init + fun:OBJ_NAME_add + fun:EVP_add_cipher + fun:SSL_library_init +} + +{ + Since we can never safely uninitialize SSL, allow this + Memcheck:Leak + fun:malloc + obj:* + fun:CRYPTO_malloc +} + +{ + Known memory leak in cyrus-sasl (fixed in 2.1.26) + Memcheck:Leak + fun:malloc + fun:* + fun:sasl_config_init + fun:sasl_server_init +} + +{ + Known bug in glibc which tries to free ipv6 related static when getaddrinfo used + Memcheck:Free + fun:free + fun:__libc_freeres + fun:_vgnU_freeres + fun:__run_exit_handlers + fun:exit +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tools/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/c/tools/CMakeLists.txt b/c/tools/CMakeLists.txt new file mode 100644 index 0000000..7a577cb --- /dev/null +++ b/c/tools/CMakeLists.txt @@ -0,0 +1,53 @@ +# +# 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(CheckIncludeFiles) + +include_directories (${PN_C_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include) + +CHECK_INCLUDE_FILES("inttypes.h" INTTYPES_AVAILABLE) +if (INTTYPES_AVAILABLE) + list(APPEND PLATFORM_DEFINITIONS "USE_INTTYPES") +else (INTTYPES_AVAILABLE) + if (CMAKE_COMPILER_IS_GNUCC) + # since inttypes.h provides portable printf format macros + set (COMPILE_WARNING_FLAGS "${COMPILE_WARNING_FLAGS} -Wno-format") + endif (CMAKE_COMPILER_IS_GNUCC) +endif (INTTYPES_AVAILABLE) + +add_executable(msgr-recv msgr-recv.c msgr-common.c) +add_executable(msgr-send msgr-send.c msgr-common.c) +add_executable(reactor-recv reactor-recv.c msgr-common.c) +add_executable(reactor-send reactor-send.c msgr-common.c) + +target_link_libraries(msgr-recv qpid-proton) +target_link_libraries(msgr-send qpid-proton) +target_link_libraries(reactor-recv qpid-proton) +target_link_libraries(reactor-send qpid-proton) + +set_target_properties ( + msgr-recv msgr-send reactor-recv reactor-send + PROPERTIES + COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS}" + COMPILE_DEFINITIONS "${PLATFORM_DEFINITIONS}" +) + +if (BUILD_WITH_CXX) + set_source_files_properties (msgr-recv.c msgr-send.c msgr-common.c reactor-recv.c reactor-send.c PROPERTIES LANGUAGE CXX) +endif (BUILD_WITH_CXX) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tools/README.txt ---------------------------------------------------------------------- diff --git a/c/tools/README.txt b/c/tools/README.txt new file mode 100644 index 0000000..7552489 --- /dev/null +++ b/c/tools/README.txt @@ -0,0 +1,14 @@ +This directory contains applications built using proton. These +applications are used by the testbed for soak tests. See the +"soak.py" file for the tests that utilize these applications. + +These applications can be used standalone to generate or consume +message traffic. + +Contents: + +msgr-send - this Messenger-based application generates message + traffic, and can be configured to consume responses. + +msgr-recv - this Messenger-based application consumes message traffic, + and can be configured to forward or reply to received messages. http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tools/include/pncompat/internal/LICENSE.txt ---------------------------------------------------------------------- diff --git a/c/tools/include/pncompat/internal/LICENSE.txt b/c/tools/include/pncompat/internal/LICENSE.txt new file mode 100644 index 0000000..2c1799c --- /dev/null +++ b/c/tools/include/pncompat/internal/LICENSE.txt @@ -0,0 +1,32 @@ +Free Getopt +Copyright (c)2002-2003 Mark K. Kim +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the original author of this software nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tools/include/pncompat/internal/getopt.c ---------------------------------------------------------------------- diff --git a/c/tools/include/pncompat/internal/getopt.c b/c/tools/include/pncompat/internal/getopt.c new file mode 100644 index 0000000..5f24dd8 --- /dev/null +++ b/c/tools/include/pncompat/internal/getopt.c @@ -0,0 +1,250 @@ +/***************************************************************************** +* getopt.c - competent and free getopt library. +* $Header: /cvsroot/freegetopt/freegetopt/getopt.c,v 1.2 2003/10/26 03:10:20 vindaci Exp $ +* +* Copyright (c)2002-2003 Mark K. Kim +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* * Neither the original author of this software nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGE. +*/ +#include +#include +#include +#include "getopt.h" + + +static const char* ID = "$Id: getopt.c,v 1.2 2003/10/26 03:10:20 vindaci Exp $"; + + +char* optarg = NULL; +int optind = 0; +int opterr = 1; +int optopt = '?'; + + +static char** prev_argv = NULL; /* Keep a copy of argv and argc to */ +static int prev_argc = 0; /* tell if getopt params change */ +static int argv_index = 0; /* Option we're checking */ +static int argv_index2 = 0; /* Option argument we're checking */ +static int opt_offset = 0; /* Index into compounded "-option" */ +static int dashdash = 0; /* True if "--" option reached */ +static int nonopt = 0; /* How many nonopts we've found */ + +static void increment_index() +{ + /* Move onto the next option */ + if(argv_index < argv_index2) + { + while(prev_argv[++argv_index] && prev_argv[argv_index][0] != '-' + && argv_index < argv_index2+1); + } + else argv_index++; + opt_offset = 1; +} + + +/* +* Permutes argv[] so that the argument currently being processed is moved +* to the end. +*/ +static int permute_argv_once() +{ + /* Movability check */ + if(argv_index + nonopt >= prev_argc) return 1; + /* Move the current option to the end, bring the others to front */ + else + { + char* tmp = prev_argv[argv_index]; + + /* Move the data */ + memmove(&prev_argv[argv_index], &prev_argv[argv_index+1], + sizeof(char**) * (prev_argc - argv_index - 1)); + prev_argv[prev_argc - 1] = tmp; + + nonopt++; + return 0; + } +} + + +int getopt(int argc, char** argv, char* optstr) +{ + int c = 0; + + /* If we have new argv, reinitialize */ + if(prev_argv != argv || prev_argc != argc) + { + /* Initialize variables */ + prev_argv = argv; + prev_argc = argc; + argv_index = 1; + argv_index2 = 1; + opt_offset = 1; + dashdash = 0; + nonopt = 0; + } + + /* Jump point in case we want to ignore the current argv_index */ + getopt_top: + + /* Misc. initializations */ + optarg = NULL; + + /* Dash-dash check */ + if(argv[argv_index] && !strcmp(argv[argv_index], "--")) + { + dashdash = 1; + increment_index(); + } + + /* If we're at the end of argv, that's it. */ + if(argv[argv_index] == NULL) + { + c = -1; + } + /* Are we looking at a string? Single dash is also a string */ + else if(dashdash || argv[argv_index][0] != '-' || !strcmp(argv[argv_index], "-")) + { + /* If we want a string... */ + if(optstr[0] == '-') + { + c = 1; + optarg = argv[argv_index]; + increment_index(); + } + /* If we really don't want it (we're in POSIX mode), we're done */ + else if(optstr[0] == '+' || getenv("POSIXLY_CORRECT")) + { + c = -1; + + /* Everything else is a non-opt argument */ + nonopt = argc - argv_index; + } + /* If we mildly don't want it, then move it back */ + else + { + if(!permute_argv_once()) goto getopt_top; + else c = -1; + } + } + /* Otherwise we're looking at an option */ + else + { + char* opt_ptr = NULL; + + /* Grab the option */ + c = argv[argv_index][opt_offset++]; + + /* Is the option in the optstr? */ + if(optstr[0] == '-') opt_ptr = strchr(optstr+1, c); + else opt_ptr = strchr(optstr, c); + /* Invalid argument */ + if(!opt_ptr) + { + if(opterr) + { + fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); + } + + optopt = c; + c = '?'; + + /* Move onto the next option */ + increment_index(); + } + /* Option takes argument */ + else if(opt_ptr[1] == ':') + { + /* ie, -oARGUMENT, -xxxoARGUMENT, etc. */ + if(argv[argv_index][opt_offset] != '\0') + { + optarg = &argv[argv_index][opt_offset]; + increment_index(); + } + /* ie, -o ARGUMENT (only if it's a required argument) */ + else if(opt_ptr[2] != ':') + { + /* One of those "you're not expected to understand this" moment */ + if(argv_index2 < argv_index) argv_index2 = argv_index; + while(argv[++argv_index2] && argv[argv_index2][0] == '-'); + optarg = argv[argv_index2]; + + /* Don't cross into the non-option argument list */ + if(argv_index2 + nonopt >= prev_argc) optarg = NULL; + + /* Move onto the next option */ + increment_index(); + } + else + { + /* Move onto the next option */ + increment_index(); + } + + /* In case we got no argument for an option with required argument */ + if(optarg == NULL && opt_ptr[2] != ':') + { + optopt = c; + c = '?'; + + if(opterr) + { + fprintf(stderr,"%s: option requires an argument -- %c\n", + argv[0], optopt); + } + } + } + /* Option does not take argument */ + else + { + /* Next argv_index */ + if(argv[argv_index][opt_offset] == '\0') + { + increment_index(); + } + } + } + + /* Calculate optind */ + if(c == -1) + { + optind = argc - nonopt; + } + else + { + optind = argv_index; + } + + return c; +} + + +/* vim:ts=3 +*/ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tools/include/pncompat/internal/getopt.h ---------------------------------------------------------------------- diff --git a/c/tools/include/pncompat/internal/getopt.h b/c/tools/include/pncompat/internal/getopt.h new file mode 100644 index 0000000..d4c0932 --- /dev/null +++ b/c/tools/include/pncompat/internal/getopt.h @@ -0,0 +1,63 @@ +/***************************************************************************** +* getopt.h - competent and free getopt library. +* $Header: /cvsroot/freegetopt/freegetopt/getopt.h,v 1.2 2003/10/26 03:10:20 vindaci Exp $ +* +* Copyright (c)2002-2003 Mark K. Kim +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided with the +* distribution. +* +* * Neither the original author of this software nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGE. +*/ +#ifndef GETOPT_H_ +#define GETOPT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern char* optarg; +extern int optind; +extern int opterr; +extern int optopt; + +int getopt(int argc, char** argv, char* optstr); + + +#ifdef __cplusplus +} +#endif + + +#endif /* GETOPT_H_ */ + + +/* vim:ts=3 +*/ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tools/include/pncompat/misc_defs.h ---------------------------------------------------------------------- diff --git a/c/tools/include/pncompat/misc_defs.h b/c/tools/include/pncompat/misc_defs.h new file mode 100644 index 0000000..90b0d4e --- /dev/null +++ b/c/tools/include/pncompat/misc_defs.h @@ -0,0 +1,50 @@ +#ifndef PNCOMAPT_MISC_DEFS_H +#define PNCOMAPT_MISC_DEFS_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. + * + */ + +#if defined(qpid_proton_EXPORTS) +#error This include file is not for use in the main proton library +#endif + +/* + * Platform neutral definitions. Only intended for use by Proton + * examples and test/debug programs. + * + * This file and any related support files may change or be removed + * at any time. + */ + +// getopt() + +#include + +#if defined(__IBMC__) +# include +#elif !defined(_WIN32) || defined (__CYGWIN__) +# include +#else +# include "internal/getopt.h" +#endif + +pn_timestamp_t time_now(void); + +#endif /* PNCOMPAT_MISC_DEFS_H */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37136940/c/tools/include/pncompat/misc_funcs.inc ---------------------------------------------------------------------- diff --git a/c/tools/include/pncompat/misc_funcs.inc b/c/tools/include/pncompat/misc_funcs.inc new file mode 100644 index 0000000..821aaf4 --- /dev/null +++ b/c/tools/include/pncompat/misc_funcs.inc @@ -0,0 +1,68 @@ +/* + * 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. + * + */ + +/* + * This file provides the functions for "misc_defs.h" in the form of + * included code, as opposed to a separate library or object + * dependency. In the absence of portable "pragma weak" compiler + * directives, this provides a simple workaround. + * + * Usage for a single compilation unit: + * + * #include "pncompat/misc_funcs.inc" + * + * Usage for multiple combined compilation units: chose one to include + * "pncompat/misc_funcs.inc" as above and in each other unit needing the + * definitions use + * + * #include "pncompat/misc_defs.h" + * + */ + +#include "misc_defs.h" + +#if defined(_WIN32) && ! defined(__CYGWIN__) +#include "pncompat/internal/getopt.c" +#endif + +#if defined(_WIN32) && ! defined(__CYGWIN__) +#include +pn_timestamp_t time_now(void) +{ + FILETIME now; + ULARGE_INTEGER t; + GetSystemTimeAsFileTime(&now); + t.u.HighPart = now.dwHighDateTime; + t.u.LowPart = now.dwLowDateTime; + // Convert to milliseconds and adjust base epoch + return t.QuadPart / 10000 - 11644473600000; +} +#else +#include +#include +#include +#include +pn_timestamp_t time_now(void) +{ + struct timeval now; + if (gettimeofday(&now, NULL)) {fprintf(stderr, "gettimeofday failed\n"); abort();} + return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_usec / 1000); +} +#endif --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org For additional commands, e-mail: commits-help@qpid.apache.org