#ifndef TESTS_PN_TEST_PROACTOR_HPP #define TESTS_PN_TEST_PROACTOR_HPP /* * 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. */ /// @file /// /// Wrapper for driving proactor tests. #include "./pn_test.hpp" #include namespace pn_test { // Get the listening port, l must be open. std::string listening_port(pn_listener_t *l); // Test proactor with an optional global handler. // For connection and listener events, if pn_*_get_context() is non-NULL // then it is cast to a handler and used instead of the global one. struct proactor : auto_free { struct handler *handler; proactor(struct handler *h = 0); // Listen on addr using optional listener handler lh pn_listener_t *listen(const std::string &addr = ":0", struct handler *lh = 0); // Connect to addr use optional handler, and optionally providing the // connection object. pn_connection_t *connect(const std::string &addr, struct handler *h = 0, pn_connection_t *c = 0); // Connect to listenr's address useing optional handler. pn_connection_t *connect(pn_listener_t *l, struct handler *h = 0, pn_connection_t *c = 0) { return connect(":" + pn_test::listening_port(l), h, c); } // Accept a connection, associate with optional connection handler. pn_connection_t *accept(pn_listener_t *l, struct handler *h = 0); // Wait for events and dispatch them until: // * A handler returns true. // * The `stop` event type is handled. // Return the event-type of the last event handled or PN_EVENT_NONE // if something went wrong. pn_event_type_t run(pn_event_type_t stop = PN_EVENT_NONE); // Dispatch immediately-available events until: // * A handler returns true. // * The `stop` event type is handled. // * All available events are flushed. // // Returns the number of events processed and // - PN_EVENT_NONE if all events were handled without stopping // - The type of the last event handled otherwise // std::pair flush(pn_event_type_t stop = PN_EVENT_NONE); // Alternate flushing this proactor and `other` until // * A handler on this proactor returns true. // * The `stop` event type is handled by this proactor. // * Both proactors become idle. // // Return the event-type of the last event handled or PN_EVENT_NONE // if the proactors are idle. pn_event_type_t corun(proactor &other, pn_event_type_t stop = PN_EVENT_NONE); // Wait for and handle a single event, return it's type. pn_event_type_t wait_next(); private: bool dispatch(pn_event_t *e); }; // CHECK/REQUIRE macros to run a proactor up to an expected event and // include the last condition in the error message if the expected event is not // returned. #define CHECK_RUN(P, E) \ CHECKED_IF((E) == (P).run(E)) {} \ else if ((P).handler) { \ FAIL_CHECK(*(P).handler->last_condition); \ } #define REQUIRE_RUN(P, E) \ CHECKED_IF((E) == (P).run(E)) {} \ else if ((P).handler) { \ FAIL(*(P).handler->last_condition); \ } #define CHECK_CORUN(P, O, E) \ CHECKED_IF((E) == (P).corun(O, E)) {} \ else if ((P).handler) { \ FAIL_CHECK(*(P).handler->last_condition); \ } #define REQUIRE_CORUN(P, E) \ CHECKED_IF((E) == (P).corun(O, E)) {} \ else if ((P).handler_) { \ FAIL(*(P).handler_->last_condition); \ } } // namespace pn_test #endif // TESTS_PN_TEST_PROACTOR_HPP