diff --git a/.cirrus.yml b/.cirrus.yml index 017d6d77f..3a517fc3c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -30,6 +30,14 @@ unix_env: &UNIX_ENV # Linux EOL timelines: https://linuxlifecycle.com/ # Fedora (~13 months): https://fedoraproject.org/wiki/Fedora_Release_Life_Cycle +fedora33_task: + container: + # Fedora 33 EOL: Around November 2022 + dockerfile: ci/fedora-33/Dockerfile + << : *RESOURCES_TEMPLATE + << : *CI_TEMPLATE + << : *UNIX_ENV + fedora32_task: container: # Fedora 32 EOL: Around May 2021 @@ -38,6 +46,14 @@ fedora32_task: << : *CI_TEMPLATE << : *UNIX_ENV +centos8_task: + container: + # CentOS 8 EOL: May 31, 2029 + dockerfile: ci/centos-8/Dockerfile + << : *RESOURCES_TEMPLATE + << : *CI_TEMPLATE + << : *UNIX_ENV + centos7_task: container: # CentOS 7 EOL: June 30, 2024 @@ -46,6 +62,14 @@ centos7_task: << : *CI_TEMPLATE << : *UNIX_ENV +debian10_task: + container: + # Debian 10 EOL: June 2024 + dockerfile: ci/debian-10/Dockerfile + << : *RESOURCES_TEMPLATE + << : *CI_TEMPLATE + << : *UNIX_ENV + debian9_task: container: # Debian 9 EOL: June 2022 @@ -62,6 +86,14 @@ debian9_32bit_task: << : *CI_TEMPLATE << : *UNIX_ENV +ubuntu20_task: + container: + # Ubuntu 20.04 EOL: April 2025 + dockerfile: ci/ubuntu-20.04/Dockerfile + << : *RESOURCES_TEMPLATE + << : *CI_TEMPLATE + << : *UNIX_ENV + ubuntu18_task: container: # Ubuntu 18.04 EOL: April 2023 @@ -95,10 +127,21 @@ macos_task: CIRRUS_WORKING_DIR: /tmp/broker # FreeBSD EOL timelines: https://www.freebsd.org/security/security.html#sup -freebsd_task: +freebsd12_task: freebsd_instance: # FreeBSD 12 EOL: June 30, 2024 - image_family: freebsd-12-1 + image_family: freebsd-12-2 + cpu: 8 + # Not allowed to request less than 8GB for an 8 CPU FreeBSD VM. + memory: 8GB + prepare_script: ./ci/freebsd/prepare.sh + << : *CI_TEMPLATE + << : *UNIX_ENV + +freebsd11_task: + freebsd_instance: + # FreeBSD 11 EOL: September 30, 2021 + image_family: freebsd-11-4 cpu: 8 # Not allowed to request less than 8GB for an 8 CPU FreeBSD VM. memory: 8GB diff --git a/.jenkinsfile b/.jenkinsfile new file mode 100644 index 000000000..4ab505515 --- /dev/null +++ b/.jenkinsfile @@ -0,0 +1,72 @@ +#!/usr/bin/env groovy + +@Library('caf-continuous-integration') _ + +// Configures the behavior of our stages. +config = [ + // Version dependency for the caf-continuous-integration library. + ciLibVersion: 1.0, + // GitHub path to repository. + repository: 'zeek/broker', + // List of enabled checks for email notifications. + checks: [ + 'build', + 'tests', + ], + // Default CMake flags. + buildFlags: [ + ], + // Our build matrix. Keys are the operating system labels and values are build configurations. + buildMatrix: [ + ['Windows', [ + numCores: 4, + builds: ['release'], + extraBuildFlags: [ + 'OPENSSL_ROOT_DIR:PATH=C:\\Program Files\\OpenSSL-Win64', + ], + ]], + ], +] + +// Declarative pipeline for triggering all stages. +pipeline { + options { + buildDiscarder(logRotator(numToKeepStr: '50', artifactNumToKeepStr: '3')) + } + agent { + label 'master' + } + environment { + PrettyJobBaseName = env.JOB_BASE_NAME.replace('%2F', '/') + PrettyJobName = "Broker/$PrettyJobBaseName #${env.BUILD_NUMBER}" + } + stages { + stage('Checkout') { + steps { + getSources(config) + } + } + stage('Build') { + steps { + buildParallel(config) + } + } + stage('Notify') { + steps { + collectResults(config, PrettyJobName) + } + } + } + post { + failure { + emailext( + subject: "$PrettyJobName: " + config['checks'].collect{ "⛔️ ${it}" }.join(', '), + recipientProviders: [culprits(), developers(), requestor(), upstreamDevelopers()], + attachLog: true, + compressLog: true, + body: "Check console output at ${env.BUILD_URL} or see attached log.\n", + ) + notifyAllChecks(config, 'failure', 'Failed due to earlier error') + } + } +} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d56dba83d..000000000 --- a/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -os: windows - -language: cpp - -branches: - only: - - master - - /^release\/.*$/ - -notifications: - email: - recipients: - - zeek-commits-internal@zeek.org - -before_install: - - df -h - - choco list --localonly - - cmake --version - - cmake --help - -install: - - choco install -y --no-progress openssl - -script: - - mkdir build && cd build - # Travis environment has 2-cores - - cmake -A x64 -DOPENSSL_ROOT_DIR="C:\Program Files\OpenSSL-Win64" -DEXTRA_FLAGS="-MP2" .. - - cmake --build . --target install --config release - - ctest -C release - -after_failure: - - cat CMakeFiles/CMakeOutput.log - - cat CMakeFiles/CMakeError.log diff --git a/3rdparty b/3rdparty index bc5e6ab4e..0e9ad7d91 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit bc5e6ab4e90e6a7af95d8a96003e12f41896f5ae +Subproject commit 0e9ad7d911e54a2b470e178959385feb52a5059c diff --git a/CHANGES b/CHANGES index d399f4e6b..53f9ff929 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,92 @@ +2.1.0-dev | 2020-12-14 20:16:02 -0800 + + * Update NEWS for start of v2.1.0 development (Jon Siwek, Corelight) + +1.5.0-dev.63 | 2020-12-14 10:38:14 -0800 + + * Update CAF submodule to fix handling of --libdir (Jon Siwek, Corelight) + +1.5.0-dev.62 | 2020-12-12 18:28:25 -0800 + + * Change `configure --prefix` to not set CMAKE_INSTALL_LIBDIR (Jon Siwek, Corelight) + + In places where that libdir option is used and not explicitly set + before, it will already correctly prepend CMAKE_INSTALL_PREFIX. Having + the configure script use the hardcoded 'lib' also prevented the + automatic use of 'lib64' on platforms that prefer it. + +1.5.0-dev.61 | 2020-12-10 14:07:51 -0800 + + * Add Jenkinsfile for re-enabling Windows builds (Dominik Charousset, Corelight) + + * Add Python context manager support (Dominik Charousset, Corelight) + + For proper resource management/cleanup, the Python API now requires + using Endpoint, Subscriber, StatusSubscriber, and Store objects within a + `with` statement or alternatively doing an explicit call to the + ``reset()`` method of subscriber/store objects before the associated + Endpoint's ``shutdown()`` method. + + Co-authored-by: Jon Siwek + + * Disable Windows builds via Travis CI (Dominik Charousset, Corelight) + + Remove the YAML file for Travis CI due to issues with getting Visual + Studio 2019 with support for `std::filesystem` working on Travis. This + is supposed to be a temporary measure until either finding a fix for the + setup or re-enabling Windows build through some other means. + + * Fix handling of initial subscription set (Dominik Charousset, Corelight) + + * Add missing to_string overloads (Dominik Charousset, Corelight) + + * Make CMake scaffold more robust against re-runs (Dominik Charousset, Corelight) + + * Clean up deprecation warnings for CAF 0.18 (Dominik Charousset, Corelight) + + * Fix CAF paths for bundled CAF version (Dominik Charousset, Corelight) + + * Migrate to CAF 0.18, update CAF submodule (Dominik Charousset, Corelight) + +1.5.0-dev.43 | 2020-12-09 17:27:31 -0800 + + * Update SQLite to 3.34.0 (Jon Siwek, Corelight) + +1.5.0-dev.42 | 2020-12-04 13:05:41 -0800 + + * Add FreeBSD 11.4 and 12.2 to CI (Jon Siwek, Corelight) + +1.5.0-dev.40 | 2020-12-04 11:32:19 -0800 + + * Suppress interactive tzdata setup on Ubuntu (Dominik Charousset) + + * Call update on Debian-based distros before install (Dominik Charousset) + + * Update CI build matrix (Dominik Charousset) + + * Update and streamline Docker files (Dominik Charousset) + +1.5.0-dev.34 | 2020-12-02 11:05:55 -0800 + + * Update minimum required CMake to 3.5 (Jon Siwek, Corelight) + +1.5.0-dev.32 | 2020-12-02 10:57:29 -0800 + + * Upgrade pybind11 to v2.6.1 and fix compatibility issues (Jon Siwek, Corelight) + +1.5.0-dev.30 | 2020-11-26 18:12:38 +0000 + + * Update macOS CI to use system default Python 3 (Jon Siwek, Corelight) + + * Remove Python 2 compatibility logic (Jon Siwek, Corelight) + + * Update CMake logic to enforce Python >= 3.5 for Python Bindings (Jon Siwek, Corelight) + + * Update Python Bindings docs for new Python >= 3.5 requirements (Jon Siwek, Corelight) + + * Update cmake submodules with changes related to Python 2 EOL (Jon Siwek, Corelight) + 1.5.0-dev.22 | 2020-10-21 15:37:57 -0700 * Move CI from Fedora 30 (EOL) to Fedora 32 (Jon Siwek, Corelight) diff --git a/CMakeLists.txt b/CMakeLists.txt index 188f1a870..803f917e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # -- Project Setup ------------------------------------------------------------ -cmake_minimum_required(VERSION 3.0 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5...3.18 FATAL_ERROR) project(broker C CXX) include(cmake/CommonCMakeConfig.cmake) include(GNUInstallDirs) @@ -194,39 +194,52 @@ if (NOT OPENSSL_LIBRARIES) endif() set(LINK_LIBS ${LINK_LIBS} ${OPENSSL_LIBRARIES}) -if ( CAF_ROOT_DIR ) - find_package(CAF COMPONENTS openssl test io core REQUIRED) - set(caf_dir "${CAF_LIBRARY_CORE}") - set(caf_config "${CAF_INCLUDE_DIR_CORE}/caf/config.hpp") - get_filename_component(caf_dir ${caf_dir} PATH) +set(CAF_VERSION_MIN_REQUIRED 0.18.0) - if (EXISTS "${caf_dir}/../libcaf_core") - get_filename_component(caf_dir ${caf_dir} PATH) - else () - set(caf_dir "${CAF_INCLUDE_DIR_CORE}") - endif () +if ( TARGET CAF::core ) + message(STATUS "CAF version ${CAF_VERSION} passed in by parent project") +elseif ( CAF_ROOT ) + # TODO: drop < 3.12 compatibility check when raising the minimum CMake version + if (CMAKE_VERSION VERSION_LESS 3.12) + find_package(CAF ${CAF_VERSION_MIN_REQUIRED} REQUIRED CONFIG + COMPONENTS openssl test io core + PATHS "${CAF_ROOT}") + else() + find_package(CAF ${CAF_VERSION_MIN_REQUIRED} REQUIRED CONFIG + COMPONENTS openssl test io core) + endif() + message(STATUS "Using system CAF version ${CAF_VERSION}") + # TODO: drop these legacy variables and simply use the targets consistently + set(CAF_LIBRARIES CAF::core CAF::io CAF::openssl CACHE INTERNAL "") + set(caf_dirs "") + foreach(caf_lib IN LISTS CAF_LIBRARIES ITEMS CAF::test) + get_target_property(dirs ${caf_lib} INTERFACE_INCLUDE_DIRECTORIES) + if ( dirs ) + list(APPEND caf_dirs ${dirs}) + endif () + endforeach() + list(REMOVE_DUPLICATES caf_dirs) + list(GET caf_dirs 0 caf_dir) + set(CAF_INCLUDE_DIRS "${caf_dirs}" CACHE INTERNAL "") else () - if ( BROKER_ENABLE_DEBUG ) - set(CAF_ENABLE_RUNTIME_CHECKS ON) - endif () - set(CAF_NO_EXAMPLES ON) - set(CAF_NO_OPENCL ON) - set(CAF_NO_TOOLS ON) - set(CAF_NO_PYTHON ON) - set(CAF_NO_UNIT_TESTS ON) - if (ENABLE_STATIC) - set(CAF_BUILD_STATIC ON) - elseif (ENABLE_STATIC_ONLY) - set(CAF_BUILD_STATIC_ONLY ON) + set(CAF_ENABLE_EXAMPLES OFF CACHE INTERNAL "") + set(CAF_ENABLE_TESTING OFF CACHE INTERNAL "") + set(CAF_ENABLE_TOOLS OFF CACHE INTERNAL "") + if (ENABLE_STATIC_ONLY) + set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "") endif () + message(STATUS "Using bundled CAF") add_subdirectory(caf) -endif () - -set(CAF_VERSION_REQUIRED 0.17.5) - -if (CAF_VERSION VERSION_LESS CAF_VERSION_REQUIRED) - message(FATAL_ERROR "Broker requires at least CAF version" - " ${CAF_VERSION_REQUIRED}, detected version: ${CAF_VERSION}") + set(caf_dir "${CMAKE_CURRENT_SOURCE_DIR}/caf") + set(CAF_LIBRARIES CAF::core CAF::io CAF::openssl CACHE INTERNAL "") + set(caf_dirs "") + foreach(comp core io openssl test) + list(APPEND caf_dirs + "${CMAKE_CURRENT_SOURCE_DIR}/caf/libcaf_${comp}" + "${CMAKE_CURRENT_BINARY_DIR}/caf/libcaf_${comp}") + endforeach() + set(CAF_INCLUDE_DIRS "${caf_dirs}" CACHE INTERNAL "") + set(CAF_FOUND TRUE CACHE INTERNAL "") endif () include_directories(BEFORE ${CAF_INCLUDE_DIRS}) @@ -388,8 +401,8 @@ if (NOT DISABLE_PYTHON_BINDINGS) set(PYTHONINTERP_FOUND false) endif () - if (${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} VERSION_LESS 2.7) - message(WARNING "Skipping Python bindings: Python 2.7 or Python 3 required") + if (${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} VERSION_LESS 3.5) + message(WARNING "Skipping Python bindings: Python 3.5 or greater required") set(PYTHONINTERP_FOUND false) endif () diff --git a/NEWS b/NEWS index b3b75ff7e..7a21077d0 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,23 @@ -Broker 1.5.0 +Broker 2.1.0 ============ -TODO: No important changes yet +- Nothing notable yet. + +Broker 2.0.0 +============ + +- Broker 2.0.0 now depends on CAF 0.18.0 with a wire format targeting + compatibility with Zeek 4.0.x. + +- CMake 3.5+ is now required to compiler Broker. + +- Support for the optional Python Bindings now requires at least Python 3.5 + +- For proper resource management/cleanup, the Python API now requires + using Endpoint, Subscriber, StatusSubscriber, and Store objects within a + `with` statement or alternatively doing an explicit call to the + `reset()` method of subscriber/store objects before the associated + Endpoint's `shutdown()` method. Broker 1.4.0 ============ diff --git a/README b/README index bb8ad2126..0d2e1fdc2 100644 --- a/README +++ b/README @@ -44,9 +44,8 @@ installed: * OpenSSL headers/libraries (http://www.openssl.org) * CMake 3.0 or greater (https://cmake.org) -The optional Python bindings also require Python 2.7 or greater -along with Python development packages. For Python 2.7, you'll -also need the ``ipaddress`` backport from Python 3. +The optional Python bindings also require Python 3.5 or greater +along with Python development packages. By default, Broker will use an integrated version of the C++ Actor Framework (CAF; https://actor-framework.org), though there's still the diff --git a/VERSION b/VERSION index 230d1256a..c10edc3fa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.0-dev.22 +2.1.0-dev diff --git a/bindings/python/3rdparty/pybind11 b/bindings/python/3rdparty/pybind11 index 80d452484..f1abf5d91 160000 --- a/bindings/python/3rdparty/pybind11 +++ b/bindings/python/3rdparty/pybind11 @@ -1 +1 @@ -Subproject commit 80d452484c5409444b0ec19383faa84bb7a4d351 +Subproject commit f1abf5d9159b805674197f6bc443592e631c9130 diff --git a/bindings/python/_broker.cpp b/bindings/python/_broker.cpp index 07804b7ed..bc7911476 100644 --- a/bindings/python/_broker.cpp +++ b/bindings/python/_broker.cpp @@ -304,7 +304,7 @@ PYBIND11_MODULE(_broker, m) { bcfg.openssl_certificate = cfg.openssl_certificate; bcfg.openssl_key = cfg.openssl_key; if ( cfg.max_threads > 0 ) - bcfg.set("scheduler.max-threads", cfg.max_threads); + bcfg.set("caf.scheduler.max-threads", cfg.max_threads); return std::unique_ptr(new broker::endpoint(std::move(bcfg))); })) .def("__repr__", [](const broker::endpoint& e) { return to_string(e.node_id()); }) diff --git a/bindings/python/broker/__init__.py b/bindings/python/broker/__init__.py index d598c921f..bad86c440 100644 --- a/bindings/python/broker/__init__.py +++ b/bindings/python/broker/__init__.py @@ -47,14 +47,6 @@ def __ne__(self, other): utc = UTC() -# Check the Python version -py2 = (sys.version_info.major < 3) - -# Python 2/3 compatibility: Make sure the "long" and "unicode" types are defined -if not py2: - long = int - unicode = str - Version = _broker.Version Version.string = lambda: '%u.%u.%u' % (Version.MAJOR, Version.MINOR, Version.PATCH) @@ -80,7 +72,7 @@ def __ne__(self, other): # for comparision against the enum. _EC_eq = _broker.EC.__eq__ def _our_EC_eq(self, other): - if isinstance(other, (int, long)): + if isinstance(other, int): return other == int(self) else: return _EC_eq(self, other) @@ -114,7 +106,7 @@ def _make_topics(ts): return _broker.VectorTopic(ts) # This class does not derive from the internal class because we -# need to pass in existign instances. That means we need to +# need to pass in existing instances. That means we need to # wrap all methods, even those that just reuse the internal # implementation. class Subscriber: @@ -128,6 +120,10 @@ def __exit__(self, type, value, traceback): self._subscriber.reset() self._subscriber = None + def reset(self): + self._subscriber.reset() + self._subscriber = None + def get(self, *args, **kwargs): msg = self._subscriber.get(*args, **kwargs) @@ -164,7 +160,7 @@ def add_topic(self, topic, block=False): def remove_topic(self, topic, block=False): return self._subscriber.remove_topic(_make_topic(topic), block) -class StatusSubscriber(_broker.Subscriber): +class StatusSubscriber(): def __init__(self, internal_subscriber): self._subscriber = internal_subscriber @@ -175,6 +171,10 @@ def __exit__(self, type, value, traceback): self._subscriber.reset() self._subscriber = None + def reset(self): + self._subscriber.reset() + self._subscriber = None + def get(self, *args, **kwargs): x = self._subscriber.get(*args, **kwargs) return self._to_result(x) @@ -206,7 +206,7 @@ def _to_error_or_status(self, x): class Publisher: # This class does not derive from the internal class because we - # need to pass in existign instances. That means we need to + # need to pass in existing instances. That means we need to # wrap all methods, even those that just reuse the internal # implementation. def __init__(self, internal_publisher): @@ -219,6 +219,10 @@ def __exit__(self, type, value, traceback): self._publisher.reset() self._publisher = None + def reset(self): + self._publisher.reset() + self._publisher = None + def demand(self): return self._publisher.demand() @@ -252,6 +256,17 @@ class Store: # implementation. def __init__(self, internal_store): self._store = internal_store + # Points to the "owning" Endpoint to make sure Python cleans this object up + # before destroying the endpoint. + self._parent = None + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self._store.reset() + self._parent = None + self._store = None def __enter__(self): return self @@ -448,7 +463,7 @@ def __init__(self, x = None): elif isinstance(x, _broker.Data): _broker.Data.__init__(self, x) - elif isinstance(x, (bool, int, long, float, str, unicode, bytes, + elif isinstance(x, (bool, int, float, str, bytes, Address, Count, Enum, Port, Set, Subnet, Table, Timespan, Timestamp, Vector)): _broker.Data.__init__(self, x) @@ -458,15 +473,7 @@ def __init__(self, x = None): _broker.Data.__init__(self, _broker.Timespan(ns)) elif isinstance(x, datetime.datetime): - if py2: - if x.tzinfo: - secs = (x - datetime.datetime(1970, 1, 1, tzinfo=utc)).total_seconds() - else: - # Assume the naive datetime is in local time - secs = time.mktime(x.timetuple()) + x.microsecond/1e6 - else: - secs = x.timestamp() - + secs = x.timestamp() _broker.Data.__init__(self, _broker.Timestamp(secs)) elif isinstance(x, ipaddress.IPv4Address): diff --git a/bindings/python/data.cpp b/bindings/python/data.cpp index 173790168..21817fd9d 100644 --- a/bindings/python/data.cpp +++ b/bindings/python/data.cpp @@ -38,6 +38,7 @@ void init_data(py::module& m) { }) .def("__repr__", [](const broker::address& a) { return broker::to_string(a); }) + .def(hash(py::self)) .def(py::self < py::self) .def(py::self <= py::self) .def(py::self > py::self) @@ -82,6 +83,7 @@ void init_data(py::module& m) { .def(py::init()) .def_readwrite("name", &broker::enum_value::name) .def("__repr__", [](const broker::enum_value& e) { return broker::to_string(e); }) + .def(hash(py::self)) .def(py::self < py::self) .def(py::self <= py::self) .def(py::self > py::self) @@ -96,6 +98,7 @@ void init_data(py::module& m) { .def("number", &broker::port::number) .def("get_type", &broker::port::type) .def("__repr__", [](const broker::port& p) { return broker::to_string(p); }) + .def(hash(py::self)) .def(py::self < py::self) .def(py::self <= py::self) .def(py::self > py::self) @@ -123,6 +126,7 @@ void init_data(py::module& m) { .def("network", &broker::subnet::network) .def("length", &broker::subnet::length) .def("__repr__", [](const broker::subnet& sn) { return to_string(sn); }) + .def(hash(py::self)) .def(py::self < py::self) .def(py::self <= py::self) .def(py::self > py::self) @@ -138,6 +142,7 @@ void init_data(py::module& m) { })) .def("count", &broker::timespan::count) .def("__repr__", [](const broker::timespan& s) { return broker::to_string(s); }) + .def(hash(py::self)) .def(py::self + py::self) .def(py::self - py::self) .def(py::self * broker::timespan::rep{}) @@ -161,6 +166,7 @@ void init_data(py::module& m) { })) .def("time_since_epoch", &broker::timestamp::time_since_epoch) .def("__repr__", [](const broker::timestamp& ts) { return broker::to_string(ts); }) + .def(hash(py::self)) .def(py::self < py::self) .def(py::self <= py::self) .def(py::self > py::self) @@ -217,6 +223,7 @@ void init_data(py::module& m) { .def("as_vector", [](const broker::data& d) { return caf::get(d); }) .def("get_type", &broker::data::get_type) .def("__str__", [](const broker::data& d) { return broker::to_string(d); }) + .def(hash(py::self)) .def(py::self < py::self) .def(py::self <= py::self) .def(py::self > py::self) diff --git a/bindings/python/set_bind.h b/bindings/python/set_bind.h index 0363c431c..f79c2edc6 100644 --- a/bindings/python/set_bind.h +++ b/bindings/python/set_bind.h @@ -6,8 +6,8 @@ #include -NAMESPACE_BEGIN(pybind11) -NAMESPACE_BEGIN(detail) +PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +PYBIND11_NAMESPACE_BEGIN(detail) /* For a set data structure, recursively check the value type (which is std::pair for maps) */ template @@ -107,7 +107,7 @@ template auto set_if_insertion_operator(Class_ & "Return the canonical string representation of this set."); } -NAMESPACE_END(detail) +PYBIND11_NAMESPACE_END(detail) // // std::set @@ -147,4 +147,4 @@ class_ bind_set(module &m, std::string const &name, Args&&... return cl; } -NAMESPACE_END(pybind11) +PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/caf b/caf index 566b6642f..dc04d7898 160000 --- a/caf +++ b/caf @@ -1 +1 @@ -Subproject commit 566b6642fe638118b911fe57b9b54bd5407dd51b +Subproject commit dc04d7898ede57e6d460ea25e6fdba1aed527ec9 diff --git a/ci/centos-7/Dockerfile b/ci/centos-7/Dockerfile index 418a3c8a8..aff7b5455 100644 --- a/ci/centos-7/Dockerfile +++ b/ci/centos-7/Dockerfile @@ -1,30 +1,20 @@ FROM centos:7 -RUN yum -y install \ - epel-release \ - && yum clean all && rm -rf /var/cache/yum +RUN yum install -y centos-release-scl \ + && yum install -y epel-release \ + && yum update -y \ + && yum clean all -RUN yum -y install \ - centos-release-scl \ - && yum clean all && rm -rf /var/cache/yum - -RUN yum -y install \ +RUN yum install -y \ + cmake3 \ devtoolset-7 \ - && yum clean all && rm -rf /var/cache/yum - -RUN yum -y install \ git \ - cmake3 \ make \ - openssl \ openssl-devel \ python3 \ python3-devel \ - && yum clean all && rm -rf /var/cache/yum - -RUN echo 'unset BASH_ENV PROMPT_COMMAND ENV' > /usr/bin/broker-ci-env && \ - echo 'source /opt/rh/devtoolset-7/enable' >> /usr/bin/broker-ci-env + && yum clean all \ + && rm -rf /var/cache/yum -ENV BASH_ENV="/usr/bin/broker-ci-env" \ - ENV="/usr/bin/broker-ci-env" \ - PROMPT_COMMAND=". /usr/bin/broker-ci-env" +ENV CC=/opt/rh/devtoolset-7/root/usr/bin/gcc +ENV CXX=/opt/rh/devtoolset-7/root/usr/bin/g++ diff --git a/ci/centos-8/Dockerfile b/ci/centos-8/Dockerfile new file mode 100644 index 000000000..5b0f2f670 --- /dev/null +++ b/ci/centos-8/Dockerfile @@ -0,0 +1,13 @@ +FROM centos:8 + +RUN yum install -y \ + cmake \ + gcc \ + gcc-c++ \ + git \ + make \ + openssl-devel \ + python3 \ + python3-devel \ + && yum clean all \ + && rm -rf /var/cache/yum diff --git a/ci/debian-10/Dockerfile b/ci/debian-10/Dockerfile new file mode 100644 index 000000000..b6b33aed8 --- /dev/null +++ b/ci/debian-10/Dockerfile @@ -0,0 +1,14 @@ +FROM debian:10 + +RUN apt update -y \ + && apt install -y \ + cmake \ + g++ \ + gcc \ + git \ + libssl-dev \ + make \ + python3 \ + python3-dev \ + && apt autoclean \ + && rm -rf /var/lib/apt/lists/* diff --git a/ci/debian-9-32bit/Dockerfile b/ci/debian-9-32bit/Dockerfile index bf8accc96..bd21c5e7b 100644 --- a/ci/debian-9-32bit/Dockerfile +++ b/ci/debian-9-32bit/Dockerfile @@ -1,18 +1,19 @@ FROM i386/debian:9 -RUN apt-get update && apt-get -y install \ - git \ - cmake \ - make \ - libssl-dev \ - python3 \ - python3-dev \ - clang-7 \ - libc++-7-dev \ - libc++abi-7-dev \ - && rm -rf /var/lib/apt/lists/* - -RUN update-alternatives --install /usr/bin/cc cc /usr/bin/clang-7 100 -RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-7 100 +RUN apt update -y \ + && apt install -y \ + clang-7 \ + cmake \ + git \ + libc++-7-dev \ + libc++abi-7-dev \ + libssl-dev \ + make \ + python3 \ + python3-dev \ + && apt autoclean \ + && rm -rf /var/lib/apt/lists/* +ENV CC=/usr/bin/clang-7 +ENV CXX=/usr/bin/clang++-7 ENV CXXFLAGS=-stdlib=libc++ diff --git a/ci/debian-9/Dockerfile b/ci/debian-9/Dockerfile index b75edf38a..3410cae13 100644 --- a/ci/debian-9/Dockerfile +++ b/ci/debian-9/Dockerfile @@ -1,18 +1,19 @@ FROM debian:9 -RUN apt-get update && apt-get -y install \ - git \ - cmake \ - make \ - libssl-dev \ - python3 \ - python3-dev \ - clang-7 \ - libc++-7-dev \ - libc++abi-7-dev \ - && rm -rf /var/lib/apt/lists/* - -RUN update-alternatives --install /usr/bin/cc cc /usr/bin/clang-7 100 -RUN update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-7 100 +RUN apt update -y \ + && apt install -y \ + clang-7 \ + cmake \ + git \ + libc++-7-dev \ + libc++abi-7-dev \ + libssl-dev \ + make \ + python3 \ + python3-dev \ + && apt autoclean \ + && rm -rf /var/lib/apt/lists/* +ENV CC=/usr/bin/clang-7 +ENV CXX=/usr/bin/clang++-7 ENV CXXFLAGS=-stdlib=libc++ diff --git a/ci/fedora-32/Dockerfile b/ci/fedora-32/Dockerfile index 01786414e..9c2ee4690 100644 --- a/ci/fedora-32/Dockerfile +++ b/ci/fedora-32/Dockerfile @@ -1,13 +1,14 @@ FROM fedora:32 -RUN yum -y install \ - git \ +RUN yum install -y \ cmake \ - make \ gcc \ gcc-c++ \ + git \ + make \ openssl \ openssl-devel \ python3 \ python3-devel \ - && yum clean all && rm -rf /var/cache/yum + && yum clean all \ + && rm -rf /var/cache/yum diff --git a/ci/fedora-33/Dockerfile b/ci/fedora-33/Dockerfile new file mode 100644 index 000000000..e7aa3a76c --- /dev/null +++ b/ci/fedora-33/Dockerfile @@ -0,0 +1,14 @@ +FROM fedora:33 + +RUN yum install -y \ + cmake \ + gcc \ + gcc-c++ \ + git \ + make \ + openssl \ + openssl-devel \ + python3 \ + python3-devel \ + && yum clean all \ + && rm -rf /var/cache/yum diff --git a/ci/macos/prepare.sh b/ci/macos/prepare.sh index 0042c427a..400cd43ba 100755 --- a/ci/macos/prepare.sh +++ b/ci/macos/prepare.sh @@ -5,8 +5,4 @@ sysctl hw.model hw.machine hw.ncpu hw.physicalcpu hw.logicalcpu set -e set -x -brew install cmake openssl python3 - -pip3 install virtualenv -virtualenv -p /usr/local/bin/python3 ~/.virtualenv/py3 -source ~/.virtualenv/py3/bin/activate +brew install cmake openssl diff --git a/ci/ubuntu-16.04/Dockerfile b/ci/ubuntu-16.04/Dockerfile index 8295f39c4..e906f1a78 100644 --- a/ci/ubuntu-16.04/Dockerfile +++ b/ci/ubuntu-16.04/Dockerfile @@ -1,24 +1,19 @@ FROM ubuntu:16.04 -RUN apt-get update && apt-get -y install \ - git \ - cmake \ - make \ - gcc \ - g++ \ - libssl-dev \ - python3 \ - python3-dev \ - bsdmainutils \ - wget \ - xz-utils \ - && rm -rf /var/lib/apt/lists/* - -RUN wget -q https://releases.llvm.org/9.0.0/clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz -RUN mkdir /clang-9 -RUN tar --strip-components=1 -C /clang-9 -xvf clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz -RUN update-alternatives --install /usr/bin/cc cc /clang-9/bin/clang 100 -RUN update-alternatives --install /usr/bin/c++ c++ /clang-9/bin/clang++ 100 +RUN apt update -y \ + && apt install -y \ + clang-8 \ + cmake \ + git \ + libc++-8-dev \ + libc++abi-8-dev \ + libssl-dev \ + make \ + python3 \ + python3-dev \ + && apt autoclean \ + && rm -rf /var/lib/apt/lists/* +ENV CC=/usr/bin/clang-8 +ENV CXX=/usr/bin/clang++-8 ENV CXXFLAGS=-stdlib=libc++ -ENV LD_LIBRARY_PATH=/clang-9/lib diff --git a/ci/ubuntu-18.04/Dockerfile b/ci/ubuntu-18.04/Dockerfile index 076ecd4b4..e02f6fa98 100644 --- a/ci/ubuntu-18.04/Dockerfile +++ b/ci/ubuntu-18.04/Dockerfile @@ -1,12 +1,17 @@ FROM ubuntu:18.04 -RUN apt-get update && apt-get -y install \ - git \ - cmake \ - make \ - gcc \ - g++ \ - libssl-dev \ - python3 \ - python3-dev \ - && rm -rf /var/lib/apt/lists/* +RUN apt update -y \ + && apt install -y \ + cmake \ + g++-8 \ + gcc-8 \ + git \ + libssl-dev \ + make \ + python3 \ + python3-dev \ + && apt-get autoclean \ + && rm -rf /var/lib/apt/lists/* + +ENV CC=/usr/bin/gcc-8 +ENV CXX=/usr/bin/g++-8 diff --git a/ci/ubuntu-20.04/Dockerfile b/ci/ubuntu-20.04/Dockerfile new file mode 100644 index 000000000..2de6bd7dc --- /dev/null +++ b/ci/ubuntu-20.04/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:20.04 + +RUN apt update -y \ + && DEBIAN_FRONTEND="noninteractive" apt install -y \ + cmake \ + g++ \ + git \ + libssl-dev \ + make \ + python3 \ + python3-dev \ + && apt autoclean \ + && rm -rf /var/lib/apt/lists/* diff --git a/cmake b/cmake index cf652b845..40251ae85 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit cf652b845908a15c02e11dca3162f3eecca0a9c5 +Subproject commit 40251ae850dee52eae8eb05e552c165e2deef354 diff --git a/configure b/configure index 3ee21d6b2..72506b18b 100755 --- a/configure +++ b/configure @@ -28,7 +28,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]... Installation Directories: --prefix=PREFIX installation directory [/usr/local] - --libdir=DIR installation directory for static and dynamic + --libdir=PATH installation directory for static and dynamic libraries [PREFIX/lib] --python-home=PATH explicit installation method for optional Python bindings [PATH/lib/python], the path tracks @@ -107,7 +107,6 @@ while [ $# -ne 0 ]; do ;; --prefix=*) append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg - append_cache_entry CMAKE_INSTALL_LIBDIR PATH $optarg/lib append_cache_entry BROKER_PYTHON_HOME PATH $optarg ;; --libdir=*) @@ -147,7 +146,7 @@ while [ $# -ne 0 ]; do append_cache_entry BROKER_DISABLE_TESTS BOOL true ;; --with-caf=*) - append_cache_entry CAF_ROOT_DIR PATH $optarg + append_cache_entry CAF_ROOT PATH $optarg ;; --with-openssl=*) append_cache_entry OPENSSL_ROOT_DIR PATH $optarg diff --git a/doc/_examples/ping.py b/doc/_examples/ping.py index 84cb3889c..92853eeef 100644 --- a/doc/_examples/ping.py +++ b/doc/_examples/ping.py @@ -4,24 +4,25 @@ import broker # Setup endpoint and connect to Zeek. -ep = broker.Endpoint() -sub = ep.make_subscriber("/topic/test") -ss = ep.make_status_subscriber(True); -ep.peer("127.0.0.1", 9999) +with broker.Endpoint() as ep, \ + ep.make_subscriber("/topic/test") as sub, \ + ep.make_status_subscriber(True) as ss: -# Wait until connection is established. -st = ss.get() + ep.peer("127.0.0.1", 9999) -if not (type(st) == broker.Status and st.code() == broker.SC.PeerAdded): - print("could not connect") - sys.exit(0) + # Wait until connection is established. + st = ss.get() -for n in range(5): - # Send event "ping(n)". - ping = broker.zeek.Event("ping", n); - ep.publish("/topic/test", ping); + if not (type(st) == broker.Status and st.code() == broker.SC.PeerAdded): + print("could not connect") + sys.exit(0) - # Wait for "pong" reply event. - (t, d) = sub.get() - pong = broker.zeek.Event(d) - print("received {}{}".format(pong.name(), pong.args())) + for n in range(5): + # Send event "ping(n)". + ping = broker.zeek.Event("ping", n); + ep.publish("/topic/test", ping); + + # Wait for "pong" reply event. + (t, d) = sub.get() + pong = broker.zeek.Event(d) + print("received {}{}".format(pong.name(), pong.args())) diff --git a/doc/_examples/sqlite-connect.py b/doc/_examples/sqlite-connect.py index d6e0785a1..dd413d710 100644 --- a/doc/_examples/sqlite-connect.py +++ b/doc/_examples/sqlite-connect.py @@ -4,20 +4,21 @@ import sys import time -ep = broker.Endpoint() -s = ep.make_subscriber('/test') -ss = ep.make_status_subscriber(True); -ep.peer('127.0.0.1', 9999, 1.0) +with broker.Endpoint() as ep, \ + ep.make_subscriber('/test') as s, \ + ep.make_status_subscriber(True) as ss: -st = ss.get(); + ep.peer('127.0.0.1', 9999, 1.0) -if not (type(st) == broker.Status and st.code() == broker.SC.PeerAdded): - print('could not connect') - sys.exit(1) + st = ss.get(); -c = ep.attach_clone('mystore') + if not (type(st) == broker.Status and st.code() == broker.SC.PeerAdded): + print('could not connect') + sys.exit(1) -while True: - time.sleep(1) - c.increment('foo', 1) - print(c.get('foo')) + c = ep.attach_clone('mystore') + + while True: + time.sleep(1) + c.increment('foo', 1) + print(c.get('foo')) diff --git a/doc/_examples/sqlite-listen.py b/doc/_examples/sqlite-listen.py index b0157b5db..24f628c6d 100644 --- a/doc/_examples/sqlite-listen.py +++ b/doc/_examples/sqlite-listen.py @@ -2,14 +2,15 @@ import broker -ep = broker.Endpoint() -s = ep.make_subscriber('/test') -ss = ep.make_status_subscriber(True); -ep.listen('127.0.0.1', 9999) +with broker.Endpoint() as ep, \ + ep.make_subscriber('/test') as s, \ + ep.make_status_subscriber(True) as ss: -m = ep.attach_master('mystore', - broker.Backend.SQLite, {'path': 'mystore.sqlite'}) + ep.listen('127.0.0.1', 9999) -while True: - print(ss.get()) - print(m.get('foo')) + m = ep.attach_master('mystore', + broker.Backend.SQLite, {'path': 'mystore.sqlite'}) + + while True: + print(ss.get()) + print(m.get('foo')) diff --git a/doc/python.rst b/doc/python.rst index 5501472aa..c655ace82 100644 --- a/doc/python.rst +++ b/doc/python.rst @@ -10,10 +10,7 @@ transparent conversion between Python values and Broker values. In the following we demonstrate the main parts of the Python API, assuming a general understanding of Broker's concepts and the C++ interface. -.. note:: Broker's Python bindings require Python 2.7 or Python 3. If you - are using Python 2.7, then you will need to install - the `ipaddress `_ module from - PyPI (one way to do this is to run "pip install ipaddress"). +.. note:: Broker's Python bindings require Python 3.5 or greater. Installation in a Virtual Environment ------------------------------------- @@ -29,9 +26,9 @@ location. $ virtualenv -p python3 /Users/user/sandbox/broker/venv $ . /Users/user/sandbox/broker/venv/bin/activate - $ ./configure --prefix=/Users/user/sandbox/broker --python-prefix=$(python -c 'import sys; print(sys.exec_prefix)') + $ ./configure --prefix=/Users/user/sandbox/broker --python-prefix=$(python3 -c 'import sys; print(sys.exec_prefix)') $ make install - $ python -c 'import broker; print(broker.__file__)' + $ python3 -c 'import broker; print(broker.__file__)' /Users/user/sandbox/broker/venv/lib/python3.7/site-packages/broker/__init__.py Communication @@ -160,7 +157,7 @@ similar to the C++ interface: .. literalinclude:: ../tests/python/communication.py :language: python :start-after: --error-start - :lines: 1-3,5-6 + :lines: 1-4,6-7 :end-before: --error-end .. literalinclude:: ../tests/python/communication.py diff --git a/include/broker/address.hh b/include/broker/address.hh index 07429704f..bf1c15bca 100644 --- a/include/broker/address.hh +++ b/include/broker/address.hh @@ -9,8 +9,6 @@ #include #include -#include "broker/detail/is_legacy_inspector.hh" - namespace broker { /// Stores an IPv4 or IPv6 address. @@ -73,6 +71,15 @@ public: return addr_.compare(other.addr_); } + // -- inspection support ----------------------------------------------------- + + template + friend bool inspect(Inspector& f, address& x) { + // We transparently expose the member variable. Hence, broker::address and + // caf::ip_address are one and the same to CAF inspectors. + return inspect(f, x.addr_); + } + // -- conversion support ----------------------------------------------------- friend bool convert(const address& a, std::string& str) { @@ -86,24 +93,6 @@ public: return true; } - // -- inspection support ----------------------------------------------------- - - // We transparently expose the member variable. Hence, broker::address and - // caf::ip_address are one and the same to CAF inspectors. - - template - friend typename Inspector::result_type inspect(Inspector& f, address& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.addr_); - else - return f.apply_object(x); - } - - template - friend bool inspect_value(Inspector& f, address& x) { - return f.apply_value(x.addr_); - } - private: caf::ip_address addr_; }; diff --git a/include/broker/alm/lamport_timestamp.hh b/include/broker/alm/lamport_timestamp.hh index d80c867fe..e008bbc2c 100644 --- a/include/broker/alm/lamport_timestamp.hh +++ b/include/broker/alm/lamport_timestamp.hh @@ -3,8 +3,6 @@ #include #include -#include "broker/detail/is_legacy_inspector.hh" - namespace broker::alm { /// A logical clock using a 64-bit counter. @@ -60,10 +58,7 @@ constexpr lamport_timestamp operator+(uint64_t x, lamport_timestamp y) { /// @relates lamport_timestamp template typename Inspector::result_type inspect(Inspector& f, lamport_timestamp& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.value); - else - return f.object(x).fields(f.field("value", x.value)); + return f.apply(x.value); } /// @relates lamport_timestamp diff --git a/include/broker/alm/multipath.hh b/include/broker/alm/multipath.hh index 4e66f153f..37611127f 100644 --- a/include/broker/alm/multipath.hh +++ b/include/broker/alm/multipath.hh @@ -10,7 +10,6 @@ #include "caf/sec.hpp" #include "broker/detail/assert.hh" -#include "broker/detail/is_legacy_inspector.hh" namespace broker::alm { @@ -261,38 +260,9 @@ public: other.nodes_end(), is_equal); } - template - friend typename Inspector::result_type inspect_legacy(Inspector& f, - multipath& x) { - if constexpr (Inspector::reads_state) { - auto tag = caf::meta::omittable_if_empty(); - auto nodes = x.nodes(); - return f(std::tie(x.id_, tag, nodes)); - } else { - if (auto err = f(x.id_)) - return err; - size_t num_children = 0; - if (auto err = f.begin_sequence(num_children)) - return err; - x.size_ = 0; - for (size_t i = 0; i < num_children; ++i) { - multipath tmp; - if (auto err = inspect(f, tmp)) - return err; - // TODO: this assumes Inspector::result_type is constructible from - // caf::sec. - if (!x.merge(std::move(tmp))) - return typename Inspector::result_type{caf::sec::runtime_error}; - } - return f.end_sequence(); - } - } - template friend typename Inspector::result_type inspect(Inspector& f, multipath& x) { - if constexpr (detail::is_legacy_inspector) - return inspect_legacy(f, x); - else if constexpr (Inspector::is_loading) { + if constexpr (Inspector::is_loading) { multipath tmp; auto nodes = tmp.nodes(); auto write_back = [&x, &tmp] { diff --git a/include/broker/alm/routing_table.hh b/include/broker/alm/routing_table.hh index 7adc1945b..84629de9b 100644 --- a/include/broker/alm/routing_table.hh +++ b/include/broker/alm/routing_table.hh @@ -14,7 +14,6 @@ #include "broker/alm/lamport_timestamp.hh" #include "broker/detail/algorithms.hh" #include "broker/detail/assert.hh" -#include "broker/detail/is_legacy_inspector.hh" #include "broker/detail/iterator_range.hh" #include "broker/detail/map_index_iterator.hh" #include "broker/optional.hh" @@ -76,13 +75,10 @@ public: template typename Inspector::result_type inspect(Inspector& f, routing_table_row& x) { - if constexpr (detail::is_legacy_inspector) - return f(caf::meta::type_name("row"), x.hdl, x.distances, x.paths); - else - return f.object(x) - .pretty_name("row") // - .fields(f.field("hdl", x.hdl), f.field("distances", x.distances), - f.field("paths", x.paths)); + return f.object(x) + .pretty_name("row") // + .fields(f.field("hdl", x.hdl), f.field("distances", x.distances), + f.field("paths", x.paths)); } /// Stores direct connections to peers as well as distances to all other peers @@ -321,13 +317,10 @@ bool operator<(const std::tuple& x, /// @relates blacklist_entry template typename Inspector::result_type inspect(Inspector& f, blacklist_entry& x) { - if constexpr(detail::is_legacy_inspector) - return f(caf::meta::type_name("blacklist_entry"), x.revoker, x.ts, x.hop); - else - return f.object(x) - .pretty_name("blacklist_entry") - .fields(f.field("revoker", x.revoker), f.field("ts", x.ts), - f.field("hop", x.hop)); + return f.object(x) + .pretty_name("blacklist_entry") + .fields(f.field("revoker", x.revoker), f.field("ts", x.ts), + f.field("hop", x.hop)); } /// A container for storing path revocations, sorted by `revoker` then `ts` then diff --git a/include/broker/data.hh b/include/broker/data.hh index cbe6c7a25..12ffe4e40 100644 --- a/include/broker/data.hh +++ b/include/broker/data.hh @@ -18,7 +18,6 @@ #include "broker/bad_variant_access.hh" #include "broker/convert.hh" #include "broker/detail/hash.hh" -#include "broker/detail/is_legacy_inspector.hh" #include "broker/detail/type_traits.hh" #include "broker/enum_value.hh" #include "broker/fwd.hh" @@ -220,16 +219,8 @@ constexpr bool has_data_tag() { } template -typename Inspector::result_type inspect(Inspector& f, data& x) { - if constexpr (detail::is_legacy_inspector) - return inspect(f, x.get_data()); - else - return f.apply_object(x.get_data()); -} - -template -bool inspect_value(Inspector& f, data& x) { - return f.apply_value(x.get_data()); +bool inspect(Inspector& f, data& x) { + return f.object(x).fields(f.field("data", x.get_data())); } /// @relates data diff --git a/include/broker/detail/blob.hh b/include/broker/detail/blob.hh index 0e07625b7..fd3457169 100644 --- a/include/broker/detail/blob.hh +++ b/include/broker/detail/blob.hh @@ -6,15 +6,16 @@ #include #include -#include "broker/detail/inspect_objects.hh" - namespace broker::detail { template auto to_blob(T&& x, Ts&&... xs) { typename caf::binary_serializer::container_type buf; caf::binary_serializer sink{nullptr, buf}; - detail::inspect_objects(sink, x, xs...); + auto res = sink.apply(std::forward(x)) + && (sink.apply(std::forward(xs)) && ...); + // TODO: maybe throw? No other way to report errors here. + static_cast(res); return buf; } @@ -22,8 +23,10 @@ template T from_blob(const void* buf, size_t size) { caf::binary_deserializer source{nullptr, reinterpret_cast(buf), size}; - T result; - detail::inspect_objects(source, result); + auto result = T{}; + auto res = source.apply(result); + // TODO: maybe throw? No other way to report errors here. + static_cast(res); return result; } diff --git a/include/broker/detail/channel.hh b/include/broker/detail/channel.hh index b52c17049..01ed916a8 100644 --- a/include/broker/detail/channel.hh +++ b/include/broker/detail/channel.hh @@ -10,7 +10,6 @@ #include #include "broker/alm/lamport_timestamp.hh" -#include "broker/detail/is_legacy_inspector.hh" #include "broker/error.hh" #include "broker/logger.hh" @@ -39,14 +38,10 @@ public: sequence_number_type seq; template - friend typename Inspector::result_type inspect(Inspector& f, - cumulative_ack& x) { - if constexpr (is_legacy_inspector) - return f(caf::meta::type_name("cumulative_ack"), x.seq); - else - return f.object(x) - .pretty_name("cumulative_ack") - .fields(f.field("seq", x.seq)); + friend bool inspect(Inspector& f, cumulative_ack& x) { + return f.object(x) + .pretty_name("cumulative_ack") + .fields(f.field("seq", x.seq)); } }; @@ -57,11 +52,8 @@ public: std::vector seqs; template - friend typename Inspector::result_type inspect(Inspector& f, nack& x) { - if constexpr (is_legacy_inspector) - return f(caf::meta::type_name("nack"), x.seqs); - else - return f.object(x).pretty_name("nack").fields(f.field("seqs", x.seqs)); + friend bool inspect(Inspector& f, nack& x) { + return f.object(x).pretty_name("nack").fields(f.field("seqs", x.seqs)); } }; @@ -81,15 +73,11 @@ public: tick_interval_type connection_timeout; template - friend typename Inspector::result_type inspect(Inspector& f, handshake& x) { - if constexpr (is_legacy_inspector) - return f(caf::meta::type_name("handshake"), x.offset, - x.heartbeat_interval); - else - return f.object(x) - .pretty_name("handshake") - .fields(f.field("offset", x.offset), - f.field("heartbeat_interval", x.heartbeat_interval)); + friend bool inspect(Inspector& f, handshake& x) { + return f.object(x) + .pretty_name("handshake") + .fields(f.field("offset", x.offset), + f.field("heartbeat_interval", x.heartbeat_interval)); } }; @@ -99,12 +87,10 @@ public: Payload content; template - friend typename Inspector::result_type inspect(Inspector& f, event& x) { - if constexpr (is_legacy_inspector) - return f(caf::meta::type_name("event"), x.seq, x.content); - else - return f.object(x).pretty_name("event").fields( - f.field("seq", x.seq), f.field("content", x.content)); + friend bool inspect(Inspector& f, event& x) { + return f.object(x) + .pretty_name("event") // + .fields(f.field("seq", x.seq), f.field("content", x.content)); } }; @@ -113,14 +99,10 @@ public: sequence_number_type seq; template - friend typename Inspector::result_type inspect(Inspector& f, - retransmit_failed& x) { - if constexpr (is_legacy_inspector) - return f(caf::meta::type_name("retransmit_failed"), x.seq); - else - return f.object(x) - .pretty_name("retransmit_failed") - .fields(f.field("seq", x.seq)); + friend bool inspect(Inspector& f, retransmit_failed& x) { + return f.object(x) + .pretty_name("retransmit_failed") + .fields(f.field("seq", x.seq)); } }; @@ -130,13 +112,8 @@ public: sequence_number_type seq; template - friend typename Inspector::result_type inspect(Inspector& f, heartbeat& x) { - if constexpr (is_legacy_inspector) - return f(caf::meta::type_name("heartbeat"), x.seq); - else - return f.object(x) - .pretty_name("heartbeat") - .fields(f.field("seq", x.seq)); + friend bool inspect(Inspector& f, heartbeat& x) { + return f.object(x).pretty_name("heartbeat").fields(f.field("seq", x.seq)); } }; @@ -472,14 +449,10 @@ public: } template - friend typename Inspector::result_type inspect(Inspector& f, - optional_event& x) { - if constexpr (is_legacy_inspector) - return f(caf::meta::type_name("optional_event"), x.seq, x.content); - else - return f.object(x) - .pretty_name("optional_event") - .fields(f.field("seq", x.seq), f.field("content", x.content)); + friend bool inspect(Inspector& f, optional_event& x) { + return f.object(x) + .pretty_name("optional_event") + .fields(f.field("seq", x.seq), f.field("content", x.content)); } }; diff --git a/include/broker/detail/inspect_objects.hh b/include/broker/detail/inspect_objects.hh deleted file mode 100644 index 90d7f92dc..000000000 --- a/include/broker/detail/inspect_objects.hh +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "broker/error.hh" - -#include - -namespace broker::detail { - -// Wraps object inspection and always returns an error for backwards -// compatibility with CAF 0.17 versions. -template -error inspect_objects(Inspector& f, Ts&... xs) { -#if CAF_VERSION >= 1800 - if (f.apply_objects(xs...)) - return {}; - return f.get_error(); -#else - return f(xs...); -#endif -} - -} // namespace broker::detail diff --git a/include/broker/detail/is_legacy_inspector.hh b/include/broker/detail/is_legacy_inspector.hh deleted file mode 100644 index 8500547a9..000000000 --- a/include/broker/detail/is_legacy_inspector.hh +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -// TODO: compatibility header for CAF < 0.18. Drop when setting the minimum -// required CAF version to ≥ 0.18. - -#include - -namespace broker::detail { - -/// Evaulates to `true` if the `Inspector` uses the CAF inspection API prior to -/// CAF 0.18, `false` otherwise. -template -constexpr bool is_legacy_inspector - = !std::is_same::value; - -} // namespace broker::detail diff --git a/include/broker/detail/radix_tree.hh b/include/broker/detail/radix_tree.hh index bfb5bd66a..148ec3777 100644 --- a/include/broker/detail/radix_tree.hh +++ b/include/broker/detail/radix_tree.hh @@ -1429,29 +1429,5 @@ operator=(iterator rhs) { return *this; } -template -auto inspect(Inspector& f, radix_tree& rt) { - if constexpr (Inspector::reads_state) { - auto n = rt.size(); - if (auto err = f.begin_sequence(n)) - return err; - for (auto& ts : rt) - if (auto err = f(ts.first)) - return err; - return f.end_sequence(); - } else { - size_t n = 0; - if (auto err = f.begin_sequence(n)) - return err; - for (size_t i = 0; i < n; ++i) { - std::string str; - if (auto err = f(str)) - return err; - rt.insert({std::move(str), true}); - } - return f.end_sequence(); - } -} - } // namespace detail } // namespace broker diff --git a/include/broker/detail/read_value.hh b/include/broker/detail/read_value.hh new file mode 100644 index 000000000..b1c9b6798 --- /dev/null +++ b/include/broker/detail/read_value.hh @@ -0,0 +1,29 @@ +#pragma once + +#include "broker/error.hh" + +namespace broker::detail { + +// Utility class for reading a primitive value from an inspector (source). If T +// is an enum, then this function performs (unsafe) static casts. This utility +// should eventually get the axe, it only makes transitioning from 0.17 to 0.18 +// easier since Broker still uses CAF 0.17-style `if (auto err = ...)` a lot. +template +error read_value(Source& source, T& storage) { + if constexpr (std::is_enum::value) { + auto tmp = std::underlying_type_t{}; + if (source.value(tmp)) { + storage = static_cast(tmp); + return {}; + } else { + return source.get_error(); + } + } else { + if (source.value(storage)) + return {}; + else + return source.get_error(); + } +} + +} // namespace broker::detail diff --git a/include/broker/detail/write_value.hh b/include/broker/detail/write_value.hh new file mode 100644 index 000000000..048a535fa --- /dev/null +++ b/include/broker/detail/write_value.hh @@ -0,0 +1,28 @@ +#pragma once + +#include "broker/error.hh" + +namespace broker::detail { + +// Utility class for writing a primitive value from an inspector (source). If T +// is an enum, then this function performs (unsafe) static casts. This utility +// should eventually get the axe, it only makes transitioning from 0.17 to 0.18 +// easier since Broker still uses CAF 0.17-style `if (auto err = ...)` a lot. +template +error write_value(Sink& sink, const T& x) { + if constexpr (std::is_enum::value) { + auto tmp = static_cast>(x); + if (sink.value(tmp)) + return {}; + else + return sink.get_error(); + + } else { + if (sink.value(x)) + return {}; + else + return sink.get_error(); + } +} + +} // namespace broker::detail diff --git a/include/broker/endpoint_info.hh b/include/broker/endpoint_info.hh index 720f2f65e..2c1b701be 100644 --- a/include/broker/endpoint_info.hh +++ b/include/broker/endpoint_info.hh @@ -31,13 +31,10 @@ inline bool operator!=(const endpoint_info& x, const endpoint_info& y) { /// @relates endpoint_info template -typename Inspector::result_type inspect(Inspector& f, endpoint_info& x) { - if constexpr (detail::is_legacy_inspector) - return f(caf::meta::type_name("endpoint_info"), x.node, x.network); - else - return f.object(x) - .pretty_name("endpoint_info") - .fields(f.field("node", x.node), f.field("network", x.network)); +bool inspect(Inspector& f, endpoint_info& x) { + return f.object(x) + .pretty_name("endpoint_info") + .fields(f.field("node", x.node), f.field("network", x.network)); } /// @relates endpoint_info @@ -67,4 +64,7 @@ struct can_convert_predicate { } }; +/// @relates endpoint_info +std::string to_string(const endpoint_info& x); + } // namespace broker diff --git a/include/broker/entity_id.hh b/include/broker/entity_id.hh index 3848fdee9..f69cbff4e 100644 --- a/include/broker/entity_id.hh +++ b/include/broker/entity_id.hh @@ -4,11 +4,11 @@ #include #include +#include #include #include #include "broker/detail/hash.hh" -#include "broker/detail/is_legacy_inspector.hh" #include "broker/fwd.hh" namespace broker { @@ -44,13 +44,10 @@ struct entity_id { /// @relates entity_id template -typename Inspector::result_type inspect(Inspector& f, entity_id& x) { - if constexpr (detail::is_legacy_inspector) - return f(caf::meta::type_name("entity_id"), x.endpoint, x.object); - else - return f.object(x) - .pretty_name("entity_id") - .fields(f.field("endpoint", x.endpoint), f.field("object", x.object)); +bool inspect(Inspector& f, entity_id& x) { + return f.object(x) + .pretty_name("entity_id") + .fields(f.field("endpoint", x.endpoint), f.field("object", x.object)); } /// @relates entity_id @@ -78,11 +75,7 @@ namespace std { template <> struct hash { size_t operator()(const broker::entity_id& x) const noexcept { - // TODO: use caf::hash::fnv when switching to CAF 0.18. - hash f; - auto result = f(x.endpoint); - broker::detail::hash_combine(result, x.object); - return result; + return caf::hash::fnv::compute(x); } }; diff --git a/include/broker/enum_value.hh b/include/broker/enum_value.hh index 9fa327c4f..0248ee55e 100644 --- a/include/broker/enum_value.hh +++ b/include/broker/enum_value.hh @@ -4,7 +4,6 @@ #include #include -#include "broker/detail/is_legacy_inspector.hh" #include "broker/detail/operators.hh" namespace broker { @@ -35,17 +34,8 @@ inline bool operator<(const enum_value& lhs, const enum_value& rhs) { /// @relates enum_value template -typename Inspector::result_type inspect(Inspector& f, enum_value& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.name); - else - return f.apply_object(x.name); -} - -/// @relates enum_value -template -bool inspect_value(Inspector& f, enum_value& x) { - return f.apply_value(x.name); +bool inspect(Inspector& f, enum_value& e) { + return f.object(e).fields(f.field("name", e.name)); } /// @relates enum_value diff --git a/include/broker/error.hh b/include/broker/error.hh index 57ee2d8d1..da4659805 100644 --- a/include/broker/error.hh +++ b/include/broker/error.hh @@ -107,7 +107,7 @@ template using ec_constant = std::integral_constant; /// @relates ec -const char* to_string(ec code) noexcept; +std::string to_string(ec code) noexcept; /// @relates ec bool convert(const std::string& str, ec& code) noexcept; diff --git a/include/broker/fwd.hh b/include/broker/fwd.hh index 11376e9c9..3516bd4c2 100644 --- a/include/broker/fwd.hh +++ b/include/broker/fwd.hh @@ -165,6 +165,8 @@ BROKER_CAF_ATOM_ALIAS(update) } // namespace broker::atom +#undef BROKER_CAF_ATOM_ALIAS + // -- type announcements and custom atoms -------------------------------------- // Our type aliases for `timespan` and `timestamp` are identical to @@ -177,8 +179,7 @@ static_assert(caf::has_type_id::value, static_assert(caf::has_type_id::value, "broker::timestamp != caf::timestamp"); -#define BROKER_ADD_ATOM(name, text) \ - CAF_ADD_ATOM(broker, broker::atom, name, text) +#define BROKER_ADD_ATOM(...) CAF_ADD_ATOM(broker, broker::atom, __VA_ARGS__) #define BROKER_ADD_TYPE_ID(type) CAF_ADD_TYPE_ID(broker, type) @@ -186,56 +187,56 @@ CAF_BEGIN_TYPE_ID_BLOCK(broker, caf::first_custom_type_id) // -- atoms for generic communication ---------------------------------------- - BROKER_ADD_ATOM(ack, "ack") + BROKER_ADD_ATOM(ack) BROKER_ADD_ATOM(default_, "default") - BROKER_ADD_ATOM(id, "id") - BROKER_ADD_ATOM(init, "init") - BROKER_ADD_ATOM(name, "name") - BROKER_ADD_ATOM(network, "network") - BROKER_ADD_ATOM(peer, "peer") - BROKER_ADD_ATOM(ping, "ping") - BROKER_ADD_ATOM(pong, "pong") - BROKER_ADD_ATOM(read, "read") - BROKER_ADD_ATOM(retry, "retry") - BROKER_ADD_ATOM(run, "run") - BROKER_ADD_ATOM(shutdown, "shutdown") - BROKER_ADD_ATOM(status, "status") - BROKER_ADD_ATOM(unpeer, "unpeer") - BROKER_ADD_ATOM(write, "write") + BROKER_ADD_ATOM(id) + BROKER_ADD_ATOM(init) + BROKER_ADD_ATOM(name) + BROKER_ADD_ATOM(network) + BROKER_ADD_ATOM(peer) + BROKER_ADD_ATOM(ping) + BROKER_ADD_ATOM(pong) + BROKER_ADD_ATOM(read) + BROKER_ADD_ATOM(retry) + BROKER_ADD_ATOM(run) + BROKER_ADD_ATOM(shutdown) + BROKER_ADD_ATOM(status) + BROKER_ADD_ATOM(unpeer) + BROKER_ADD_ATOM(write) // -- atoms for communication with workers ----------------------------------- - BROKER_ADD_ATOM(resume, "resume") + BROKER_ADD_ATOM(resume) // -- atoms for communication with stores ------------------------------------ - BROKER_ADD_ATOM(attach, "attach") - BROKER_ADD_ATOM(await, "await") - BROKER_ADD_ATOM(clear, "clear") - BROKER_ADD_ATOM(clone, "clone") - BROKER_ADD_ATOM(decrement, "decrement") - BROKER_ADD_ATOM(erase, "erase") - BROKER_ADD_ATOM(exists, "exists") - BROKER_ADD_ATOM(expire, "expire") - BROKER_ADD_ATOM(idle, "idle") - BROKER_ADD_ATOM(increment, "increment") - BROKER_ADD_ATOM(keys, "keys") - BROKER_ADD_ATOM(local, "local") - BROKER_ADD_ATOM(master, "master") - BROKER_ADD_ATOM(mutable_check, "mutable") - BROKER_ADD_ATOM(resolve, "resolve") - BROKER_ADD_ATOM(restart, "restart") - BROKER_ADD_ATOM(revoke, "subtract") - BROKER_ADD_ATOM(stale_check, "stale") - BROKER_ADD_ATOM(store, "store") - BROKER_ADD_ATOM(subtract, "subtract") - BROKER_ADD_ATOM(sync_point, "sync_point") + BROKER_ADD_ATOM(attach) + BROKER_ADD_ATOM(await) + BROKER_ADD_ATOM(clear) + BROKER_ADD_ATOM(clone) + BROKER_ADD_ATOM(decrement) + BROKER_ADD_ATOM(erase) + BROKER_ADD_ATOM(exists) + BROKER_ADD_ATOM(expire) + BROKER_ADD_ATOM(idle) + BROKER_ADD_ATOM(increment) + BROKER_ADD_ATOM(keys) + BROKER_ADD_ATOM(local) + BROKER_ADD_ATOM(master) + BROKER_ADD_ATOM(mutable_check) + BROKER_ADD_ATOM(resolve) + BROKER_ADD_ATOM(restart) + BROKER_ADD_ATOM(revoke) + BROKER_ADD_ATOM(stale_check) + BROKER_ADD_ATOM(store) + BROKER_ADD_ATOM(subtract) + BROKER_ADD_ATOM(sync_point) // -- atoms for communciation with the core actor ---------------------------- - BROKER_ADD_ATOM(no_events, "noEvents") - BROKER_ADD_ATOM(snapshot, "snapshot") - BROKER_ADD_ATOM(subscriptions, "subs") + BROKER_ADD_ATOM(no_events) + BROKER_ADD_ATOM(snapshot) + BROKER_ADD_ATOM(subscriptions) // -- Broker type announcements ---------------------------------------------- diff --git a/include/broker/internal_command.hh b/include/broker/internal_command.hh index deafba756..f456dbe44 100644 --- a/include/broker/internal_command.hh +++ b/include/broker/internal_command.hh @@ -6,11 +6,9 @@ #include #include #include -#include #include "broker/data.hh" #include "broker/detail/channel.hh" -#include "broker/detail/is_legacy_inspector.hh" #include "broker/entity_id.hh" #include "broker/fwd.hh" #include "broker/snapshot.hh" @@ -61,17 +59,13 @@ bool inspect_impl(Inspector& f, T& obj, caf::string_view pretty_name, friend typename Inspector::result_type inspect(Inspector& f, \ name##_command& x) { \ auto& [__VA_ARGS__, publisher] = x; \ - if constexpr (detail::is_legacy_inspector) { \ - return f(caf::meta::type_name(#name), __VA_ARGS__, publisher); \ - } else { \ - caf::string_view field_names[] = { \ - BROKER_PP_EXPAND field_names_pack, \ - "publisher", \ - }; \ - auto refs = std::forward_as_tuple(__VA_ARGS__, publisher); \ - std::make_index_sequence::value> iseq; \ - return detail::inspect_impl(f, x, #name, field_names, refs, iseq); \ - } \ + caf::string_view field_names[] = { \ + BROKER_PP_EXPAND field_names_pack, \ + "publisher", \ + }; \ + auto refs = std::forward_as_tuple(__VA_ARGS__, publisher); \ + std::make_index_sequence::value> iseq; \ + return detail::inspect_impl(f, x, #name, field_names, refs, iseq); \ } /// Sets a value in the key-value store. @@ -141,14 +135,10 @@ struct clear_command { entity_id publisher; static constexpr auto tag = command_tag::action; template - friend typename Inspector::result_type inspect(Inspector& f, - clear_command& x) { - if constexpr (detail::is_legacy_inspector) - return f(caf::meta::type_name("clear"), x.publisher); - else - return f.object(x) - .pretty_name("clear") // - .fields(f.field("publisher", x.publisher)); + friend bool inspect(Inspector& f, clear_command& x) { + return f.object(x) + .pretty_name("clear") // + .fields(f.field("publisher", x.publisher)); } }; @@ -163,14 +153,10 @@ struct clear_command { friend typename Inspector::result_type inspect(Inspector& f, \ name##_command& x) { \ auto& [__VA_ARGS__] = x; \ - if constexpr (detail::is_legacy_inspector) { \ - return f(caf::meta::type_name(#name), __VA_ARGS__); \ - } else { \ - caf::string_view field_names[] = {BROKER_PP_EXPAND field_names_pack}; \ - auto refs = std::forward_as_tuple(__VA_ARGS__); \ - std::make_index_sequence::value> iseq; \ - return detail::inspect_impl(f, x, #name, field_names, refs, iseq); \ - } \ + caf::string_view field_names[] = {BROKER_PP_EXPAND field_names_pack}; \ + auto refs = std::forward_as_tuple(__VA_ARGS__); \ + std::make_index_sequence::value> iseq; \ + return detail::inspect_impl(f, x, #name, field_names, refs, iseq); \ } /// Causes the master to add `remote_clone` to its list of clones. @@ -178,12 +164,8 @@ struct attach_clone_command { static constexpr auto tag = command_tag::consumer_control; template - friend typename Inspector::result_type inspect(Inspector& f, - attach_clone_command& x) { - if constexpr (detail::is_legacy_inspector) - return f(caf::meta::type_name("attach_clone")); - else - return f.object(x).pretty_name("attach_clone").fields(); + friend bool inspect(Inspector& f, attach_clone_command& x) { + return f.object(x).pretty_name("attach_clone").fields(); } }; @@ -271,15 +253,9 @@ public: }; template -typename Inspector::result_type inspect(Inspector& f, internal_command& x) { - if constexpr (detail::is_legacy_inspector) - return f(caf::meta::type_name("internal_command"), x.seq, x.sender, - x.content); - else - return f.object(x) - .pretty_name("internal_command") - .fields(f.field("seq", x.seq), f.field("sender", x.sender), - f.field("content", x.content)); +bool inspect(Inspector& f, internal_command& x) { + return f.object(x).fields(f.field("seq", x.seq), f.field("sender", x.sender), + f.field("content", x.content)); } } // namespace broker diff --git a/include/broker/network_info.hh b/include/broker/network_info.hh index 909479f82..76a9fd24d 100644 --- a/include/broker/network_info.hh +++ b/include/broker/network_info.hh @@ -5,7 +5,6 @@ #include -#include "broker/detail/is_legacy_inspector.hh" #include "broker/detail/operators.hh" #include "broker/timeout.hh" @@ -33,20 +32,13 @@ bool operator<(const network_info& x, const network_info& y); /// @relates network_info template -typename Inspector::result_type inspect(Inspector& f, network_info& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.address, x.port, x.retry); - else - return f.object(x).fields(f.field("address", x.address), - f.field("port", x.port), - f.field("retry", x.retry)); +bool inspect(Inspector& f, network_info& x) { + return f.object(x).fields(f.field("address", x.address), + f.field("port", x.port), f.field("retry", x.retry)); } /// @relates network_info -inline std::string to_string(const network_info& info) { - using std::to_string; - return info.address + ':' + to_string(info.port); -} +std::string to_string(const network_info& info); } // namespace broker diff --git a/include/broker/peer_info.hh b/include/broker/peer_info.hh index 39c496822..d10b6d017 100644 --- a/include/broker/peer_info.hh +++ b/include/broker/peer_info.hh @@ -1,6 +1,5 @@ #pragma once -#include "broker/detail/is_legacy_inspector.hh" #include "broker/endpoint_info.hh" #include "broker/peer_flags.hh" #include "broker/peer_status.hh" @@ -16,13 +15,9 @@ struct peer_info { }; template -typename Inspector::result_type inspect(Inspector& f, peer_info& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.peer, x.flags, x.status); - else - return f.object(x).fields(f.field("peer", x.peer), - f.field("flags", x.flags), - f.field("status", x.status)); +bool inspect(Inspector& f, peer_info& x) { + return f.object(x).fields(f.field("peer", x.peer), f.field("flags", x.flags), + f.field("status", x.status)); } } // namespace broker diff --git a/include/broker/port.hh b/include/broker/port.hh index 655b31aec..0a0eff912 100644 --- a/include/broker/port.hh +++ b/include/broker/port.hh @@ -3,7 +3,6 @@ #include #include -#include "broker/detail/is_legacy_inspector.hh" #include "broker/detail/operators.hh" namespace broker { @@ -36,12 +35,9 @@ public: friend bool operator<(const port& lhs, const port& rhs); template - friend typename Inspector::result_type inspect(Inspector& f, port& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.num_, x.proto_); - else - return f.object(x).fields(f.field("num_", x.num_), - f.field("proto_", x.proto_)); + friend bool inspect(Inspector& f, port& x) { + return f.object(x).fields(f.field("num", x.num_), + f.field("proto", x.proto_)); } private: diff --git a/include/broker/shutdown_options.hh b/include/broker/shutdown_options.hh index 337920fac..31bb3d976 100644 --- a/include/broker/shutdown_options.hh +++ b/include/broker/shutdown_options.hh @@ -3,8 +3,6 @@ #include #include -#include "broker/detail/is_legacy_inspector.hh" - namespace broker { class shutdown_options { @@ -27,11 +25,7 @@ public: template friend auto inspect(Inspector& f, shutdown_options& x) { - if constexpr (detail::is_legacy_inspector) { - return f(x.flags_); - } else { - return f.object(x).fields(f.field("flags", x.flags_)); - } + return f.object(x).fields(f.field("flags", x.flags_)); } private: diff --git a/include/broker/status.hh b/include/broker/status.hh index 04f5e0146..b4ddaa84b 100644 --- a/include/broker/status.hh +++ b/include/broker/status.hh @@ -122,22 +122,11 @@ public: friend bool operator==(sc x, const status& y); template - friend typename Inspector::result_type inspect(Inspector& f, status& x) { - if constexpr (detail::is_legacy_inspector) { - auto verify = [&x] { return x.verify(); }; - return f(x.code_, x.context_, x.message_, - caf::meta::load_callback(verify)); - } else { - auto verify = [&x] { - if (auto err = x.verify()) - return false; - return true; - }; - return f.object(x) - .on_load(verify) // - .fields(f.field("code_", x.code_), f.field("context_", x.context_), - f.field("message_", x.message_)); - } + friend bool inspect(Inspector& f, status& x) { + auto verify = [&x] { return x.verify(); }; + return f.object(x).on_load(verify).fields(f.field("code", x.code_), + f.field("context", x.context_), + f.field("message", x.message_)); } /// Maps `src` to `["status", code, context, message]`, whereas: diff --git a/include/broker/subnet.hh b/include/broker/subnet.hh index bfb022f32..5167df535 100644 --- a/include/broker/subnet.hh +++ b/include/broker/subnet.hh @@ -1,7 +1,6 @@ #pragma once #include "broker/address.hh" -#include "broker/detail/is_legacy_inspector.hh" #include "broker/detail/operators.hh" namespace broker { @@ -28,11 +27,8 @@ public: friend bool operator<(const subnet& lhs, const subnet& rhs); template - friend typename Inspector::result_type inspect(Inspector& f, subnet& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.net_, x.len_); - else - return f.object(x).fields(f.field("net", x.net_), f.field("len", x.len_)); + friend bool inspect(Inspector& f, subnet& x) { + return f.object(x).fields(f.field("net", x.net_), f.field("len", x.len_)); } private: diff --git a/include/broker/topic.hh b/include/broker/topic.hh index bdd7bd61e..49a8dc574 100644 --- a/include/broker/topic.hh +++ b/include/broker/topic.hh @@ -6,7 +6,6 @@ #include #include -#include "broker/detail/is_legacy_inspector.hh" #include "broker/detail/operators.hh" namespace broker { @@ -57,16 +56,8 @@ public: bool prefix_of(const topic& t) const; template - friend typename Inspector::result_type inspect(Inspector& f, topic& x) { - if constexpr (detail::is_legacy_inspector) - return f(x.str_); - else - return f.object(x).fields(f.field("str", x.str_)); - } - - template - friend bool inspect_value(Inspector& f, topic& x) { - return f.apply_value(x.str_); + friend bool inspect(Inspector& f, topic& x) { + return f.object(x).fields(f.field("str", x.str_)); } private: diff --git a/include/broker/version.hh b/include/broker/version.hh index f3edf1317..cf2e622a9 100644 --- a/include/broker/version.hh +++ b/include/broker/version.hh @@ -8,8 +8,8 @@ namespace version { /// The type used for version numbers. using type = unsigned; -constexpr type major = 1; -constexpr type minor = 5; +constexpr type major = 2; +constexpr type minor = 1; constexpr type patch = 0; constexpr auto suffix = "-dev"; diff --git a/src/broker-node.cc b/src/broker-node.cc index acf1b1271..11da09cc3 100644 --- a/src/broker-node.cc +++ b/src/broker-node.cc @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/src/broker-pipe.cc b/src/broker-pipe.cc index 69567680b..ce2fb32c3 100644 --- a/src/broker-pipe.cc +++ b/src/broker-pipe.cc @@ -19,7 +19,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated" #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#include #include #include #include @@ -259,8 +258,13 @@ int main(int argc, char** argv) { } if (cfg.cli_helptext_printed) return EXIT_SUCCESS; - cfg.parse(argc, argv); - broker::endpoint ep{std::move(cfg)}; + config cfg_copy; + if (auto err = cfg_copy.parse(argc, argv)) { + std::cerr << "*** error while reading config: " << to_string(err) + << std::endl; + return EXIT_FAILURE; + } + broker::endpoint ep{std::move(cfg_copy)}; auto el = ep.system().spawn(event_listener); // Publish endpoint at demanded port. if (cfg.local_port != 0) diff --git a/src/configuration.cc b/src/configuration.cc index acefcef39..1947b2743 100644 --- a/src/configuration.cc +++ b/src/configuration.cc @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -62,37 +61,6 @@ auto concat(Ts... xs) { throw std::invalid_argument(what); } -#if CAF_VERSION < 1800 - -constexpr caf::string_view file_verbosity_key = "logger.file-verbosity"; - -constexpr caf::string_view console_verbosity_key = "logger.console-verbosity"; - -bool valid_log_level(caf::atom_value x) { - using caf::atom_uint; - switch (atom_uint(x)) { - default: - return false; - case atom_uint("trace"): - case atom_uint("debug"): - case atom_uint("info"): - case atom_uint("warning"): - case atom_uint("error"): - case atom_uint("quiet"): - return true; - } -} - -caf::atom_value to_log_level(const char* var, const char* cstr) { - caf::string_view str{cstr, strlen(cstr)}; - auto atm = caf::to_lowercase(caf::atom_from_string(str)); - if (valid_log_level(atm)) - return atm; - throw_illegal_log_level(var, cstr); -} - -#else - constexpr caf::string_view file_verbosity_key = "caf.logger.file.verbosity"; constexpr caf::string_view console_verbosity_key = "caf.logger.console.verbosity"; @@ -109,8 +77,6 @@ std::string to_log_level(const char* var, const char* cstr) { throw_illegal_log_level(var, cstr); } -#endif - } // namespace configuration::configuration(skip_init_t) { @@ -140,28 +106,6 @@ configuration::configuration(skip_init_t) { // Ensure that we're only talking to compatible Broker instances. std::vector ids{"broker.v" + std::to_string(version::protocol)}; // Override CAF defaults. -#if CAF_VERSION < 1800 - using caf::atom; - using caf::atom_value; - set("logger.file-name", "broker_[PID]_[TIMESTAMP].log"); - set("logger.file-verbosity", atom("quiet")); - set("logger.console-format", "[%c/%p] %d %m"); - set("middleman.app-identifiers", std::move(ids)); - set("middleman.workers", 0); - // Enable console output (and color it if stdout is a TTY) but set verbosty to - // errors-only. Users can still override via the environment variable - // BROKER_CONSOLE_VERBOSITY. - if (isatty(STDOUT_FILENO)) - set("logger.console", atom("colored")); - else - set("logger.console", atom("uncolored")); - set("logger.console-verbosity", atom("error")); - // Turn off all CAF output by default. - std::vector blacklist{atom("caf"), atom("caf_io"), - atom("caf_net"), atom("caf_flow"), - atom("caf_stream")}; - set("logger.component-blacklist", std::move(blacklist)); -#else set("caf.logger.file.path", "broker_[PID]_[TIMESTAMP].log"); set("caf.logger.file.verbosity", "quiet"); set("caf.logger.console.format", "[%c/%p] %d %m"); @@ -175,7 +119,6 @@ configuration::configuration(skip_init_t) { "caf_flow", "caf_stream"}; set("caf.logger.file.excluded-components", excluded_components); set("caf.logger.console.excluded-components", std::move(excluded_components)); -#endif } configuration::configuration(broker_options opts) : configuration(skip_init) { @@ -268,18 +211,6 @@ caf::settings configuration::dump_content() const { return result; } -#if CAF_VERSION < 1800 - -void configuration::add_message_types(caf::actor_system_config& cfg) { - cfg.add_message_types(); -} - -void configuration::init_global_state() { - // nop -} - -#else - void configuration::add_message_types(caf::actor_system_config&) { // nop } @@ -299,8 +230,6 @@ void configuration::init_global_state() { }); } -#endif - void configuration::sync_options() { set("broker.disable-ssl", options_.disable_ssl); set("broker.disable-forwarding", options_.disable_forwarding); diff --git a/src/core_actor.cc b/src/core_actor.cc index bff458359..e8a759281 100644 --- a/src/core_actor.cc +++ b/src/core_actor.cc @@ -1,6 +1,24 @@ #include "broker/core_actor.hh" -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "broker/domain_options.hh" @@ -14,6 +32,8 @@ core_manager::core_manager(caf::node_id core_id, endpoint::clock* clock, caf::event_based_actor* self, const domain_options* adaptation) : super(self, clock) { +auto id_str= to_string(core_id); +printf("id: %s\n",id_str.c_str()); id(std::move(core_id)); if (adaptation && adaptation->disable_forwarding) disable_forwarding(true); @@ -50,7 +70,7 @@ caf::behavior core_actor_t::operator()(core_actor_type* self, if (!initial_filter.empty()) mgr->subscribe(initial_filter); auto& cfg = self->system().config(); - mgr->cache().set_use_ssl(not caf::get_or(cfg, "broker.disable-ssl", false)); + mgr->cache().set_use_ssl(!caf::get_or(cfg, "broker.disable-ssl", false)); self->set_exit_handler([self](caf::exit_msg& msg) { if (msg.reason) { BROKER_DEBUG("shutting down after receiving an exit message with reason:" diff --git a/src/detail/data_generator.cc b/src/detail/data_generator.cc index d0dd4789a..f202a3c4d 100644 --- a/src/detail/data_generator.cc +++ b/src/detail/data_generator.cc @@ -7,8 +7,8 @@ #include #include -#include "broker/detail/inspect_objects.hh" #include "broker/detail/meta_data_writer.hh" +#include "broker/detail/read_value.hh" #include "broker/logger.hh" using std::string; @@ -22,10 +22,6 @@ using std::string; break; \ } -#define READ(var_name) \ - if (auto err = detail::inspect_objects(source_, var_name)) \ - return err - #define GENERATE(var_name) \ if (auto err = generate(var_name)) \ return err @@ -54,7 +50,8 @@ void recreate(data_generator& self, T& xs) { } xs = std::move(tmp); } -} + +} // namespace data_generator::data_generator(caf::binary_deserializer& meta_data_source, unsigned seed) @@ -74,8 +71,8 @@ caf::error data_generator::operator()(internal_command& x) { } caf::error data_generator::generate(data& x) { - data::type tag{}; - READ(tag); + auto tag = data::type{}; + BROKER_TRY(read_value(source_, tag)); return generate(tag, x); } @@ -104,7 +101,7 @@ caf::error data_generator::generate(data::type tag, data& x) { caf::error data_generator::generate(internal_command& x) { internal_command::type tag{}; - READ(tag); + BROKER_TRY(read_value(source_, tag)); return generate(tag, x); } @@ -147,7 +144,7 @@ caf::error data_generator::generate(internal_command::type tag, data::type init_type{}; GENERATE(key); GENERATE(val); - READ(init_type); + BROKER_TRY(read_value(source_, init_type)); x.content = add_command{std::move(key), std::move(val), init_type, nil}; break; } @@ -217,7 +214,7 @@ caf::error data_generator::generate(internal_command::type tag, caf::error data_generator::generate(vector& xs) { uint32_t size = 0; - READ(size); + BROKER_TRY(read_value(source_, size)); for (size_t i = 0; i < size; ++i) { data value; GENERATE(value); @@ -228,7 +225,7 @@ caf::error data_generator::generate(vector& xs) { caf::error data_generator::generate(set& xs) { uint32_t size = 0; - READ(size); + BROKER_TRY(read_value(source_, size)); data value; for (size_t i = 0; i < size; ++i) { GENERATE(value); @@ -240,7 +237,7 @@ caf::error data_generator::generate(set& xs) { caf::error data_generator::generate(table& xs) { uint32_t size = 0; - READ(size); + BROKER_TRY(read_value(source_, size)); data key; data value; for (size_t i = 0; i < size; ++i) { @@ -254,7 +251,7 @@ caf::error data_generator::generate(table& xs) { caf::error data_generator::generate(std::unordered_map& xs) { uint32_t size = 0; - READ(size); + BROKER_TRY(read_value(source_, size)); data key; data value; for (size_t i = 0; i < size; ++i) { @@ -268,7 +265,7 @@ caf::error data_generator::generate(std::unordered_map& xs) { caf::error data_generator::generate(std::string& x) { uint32_t string_size = 0; - READ(string_size); + BROKER_TRY(read_value(source_, string_size)); x.insert(x.end(), string_size, 'x'); return caf::none; } diff --git a/src/detail/generator_file_reader.cc b/src/detail/generator_file_reader.cc index a51bcef80..85bf23a8f 100644 --- a/src/detail/generator_file_reader.cc +++ b/src/detail/generator_file_reader.cc @@ -11,7 +11,7 @@ #include "broker/config.hh" #include "broker/detail/assert.hh" #include "broker/detail/generator_file_writer.hh" -#include "broker/detail/inspect_objects.hh" +#include "broker/detail/read_value.hh" #include "broker/error.hh" #include "broker/logger.hh" #include "broker/message.hh" @@ -158,11 +158,11 @@ caf::error generator_file_reader::read_raw(read_raw_callback f) { while (!at_end()) { entry_type entry{}; auto pos = source_.remainder().data(); - BROKER_TRY(detail::inspect_objects(source_, entry)); + BROKER_TRY(read_value(source_, entry)); switch (entry) { case entry_type::new_topic: { std::string str; - BROKER_TRY(detail::inspect_objects(source_, str)); + BROKER_TRY(read_value(source_, str)); if (!sealed_) topic_table_.emplace_back(str); auto consumed = caf::make_span(pos, source_.remainder().data()); @@ -172,7 +172,7 @@ caf::error generator_file_reader::read_raw(read_raw_callback f) { } case entry_type::data_message: { uint16_t topic_id; - BROKER_TRY(detail::inspect_objects(source_, topic_id)); + BROKER_TRY(read_value(source_, topic_id)); if (topic_id >= topic_table_.size()) return ec::invalid_topic_key; data value; @@ -188,7 +188,7 @@ caf::error generator_file_reader::read_raw(read_raw_callback f) { } case entry_type::command_message: { uint16_t topic_id; - BROKER_TRY(detail::inspect_objects(source_, topic_id)); + BROKER_TRY(read_value(source_, topic_id)); if (topic_id >= topic_table_.size()) return ec::invalid_topic_key; internal_command cmd; diff --git a/src/detail/generator_file_writer.cc b/src/detail/generator_file_writer.cc index 5dd94ba38..55a8a70ac 100644 --- a/src/detail/generator_file_writer.cc +++ b/src/detail/generator_file_writer.cc @@ -3,8 +3,8 @@ #include #include -#include "broker/detail/inspect_objects.hh" #include "broker/detail/meta_data_writer.hh" +#include "broker/detail/write_value.hh" #include "broker/error.hh" #include "broker/logger.hh" #include "broker/message.hh" @@ -69,8 +69,8 @@ caf::error generator_file_writer::write(const data_message& x) { meta_data_writer writer{sink_}; uint16_t tid; auto entry = format::entry_type::data_message; - BROKER_TRY(topic_id(get_topic(x), tid), - detail::inspect_objects(sink_, entry, tid), writer(get_data(x))); + BROKER_TRY(topic_id(get_topic(x), tid), write_value(sink_, entry), + write_value(sink_, tid), writer(get_data(x))); if (buf_.size() >= flush_threshold()) return flush(); return caf::none; @@ -80,9 +80,8 @@ caf::error generator_file_writer::write(const command_message& x) { meta_data_writer writer{sink_}; uint16_t tid; auto entry = format::entry_type::command_message; - BROKER_TRY(topic_id(get_topic(x), tid), - detail::inspect_objects(sink_, entry, tid), - writer(get_command(x))); + BROKER_TRY(topic_id(get_topic(x), tid), write_value(sink_, entry), + write_value(sink_, tid), writer(get_command(x))); if (buf_.size() >= flush_threshold()) return flush(); return caf::none; @@ -100,8 +99,7 @@ caf::error generator_file_writer::topic_id(const topic& x, uint16_t& id) { if (i == e) { // Write the new topic to file first. auto entry = format::entry_type::new_topic; - if (auto err = detail::inspect_objects(sink_, entry, x.string())) - return err; + BROKER_TRY(write_value(sink_, entry), write_value(sink_, x.string())); id = static_cast(topic_table_.size()); topic_table_.emplace_back(x); return caf::none; @@ -127,7 +125,9 @@ generator_file_writer_ptr make_generator_file_writer(const std::string& fname) { generator_file_writer& operator<<(generator_file_writer& out, const data_message& x) { - out.write(x); + if (auto err = out.write(x)) { + BROKER_ERROR("error writing data message to generator file:" << to_string(err)); + } return out; } diff --git a/src/detail/meta_command_writer.cc b/src/detail/meta_command_writer.cc new file mode 100644 index 000000000..05335ceb7 --- /dev/null +++ b/src/detail/meta_command_writer.cc @@ -0,0 +1,91 @@ +#include "broker/detail/meta_command_writer.hh" + +#include +#include + +#include "broker/error.hh" +#include "broker/internal_command.hh" + +namespace broker { +namespace detail { + +meta_command_writer::meta_command_writer(caf::binary_serializer& sink) + : writer_(sink) { + // nop +} + +caf::error meta_command_writer::operator()(const internal_command& x) { + return caf::visit(*this, x.content); +} + +caf::error meta_command_writer::operator()(const none& x) { + return apply_tag(internal_command_uint_tag()); +} + +caf::error meta_command_writer::operator()(const put_command& x) { + BROKER_TRY(apply_tag(internal_command_uint_tag()), + writer_(x.key), writer_(x.value)); + return caf::none; +} + +caf::error meta_command_writer::operator()(const put_unique_command& x) { + BROKER_TRY(apply_tag(internal_command_uint_tag()), + writer_(x.key), writer_(x.value)); + return caf::none; +} + +caf::error meta_command_writer::operator()(const erase_command& x) { + BROKER_TRY(apply_tag(internal_command_uint_tag()), + writer_(x.key)); + return caf::none; +} + +caf::error meta_command_writer::operator()(const expire_command& x) { + BROKER_TRY(apply_tag(internal_command_uint_tag()), + writer_(x.key)); + return caf::none; +} + +caf::error meta_command_writer::operator()(const add_command& x) { + static_assert( + std::is_same>::value); + BROKER_TRY(apply_tag(internal_command_uint_tag()), + writer_(x.key), writer_(x.value), + apply_tag(static_cast(x.init_type))); + return caf::none; +} + +caf::error meta_command_writer::operator()(const subtract_command& x) { + BROKER_TRY(apply_tag(internal_command_uint_tag()), + writer_(x.key), writer_(x.value)); + return caf::none; +} + +caf::error meta_command_writer::operator()(const snapshot_command& x) { + return apply_tag(internal_command_uint_tag()); +} + +caf::error meta_command_writer::operator()(const snapshot_sync_command& x) { + return apply_tag(internal_command_uint_tag()); +} + +caf::error meta_command_writer::operator()(const set_command& x) { + BROKER_TRY(apply_tag(internal_command_uint_tag()), + writer_.apply_container(x.state)); + return caf::none; +} + +caf::error meta_command_writer::operator()(const clear_command& x) { + return apply_tag(internal_command_uint_tag()); +} + +caf::error meta_command_writer::apply_tag(uint8_t tag) { + auto& sink = writer_.sink(); + if (sink.value(tag)) + return {}; + else + return sink.get_error(); +} + +} // namespace detail +} // namespace broker diff --git a/src/detail/meta_data_writer.cc b/src/detail/meta_data_writer.cc index 5a70d2dd5..5310e96e4 100644 --- a/src/detail/meta_data_writer.cc +++ b/src/detail/meta_data_writer.cc @@ -2,7 +2,6 @@ #include -#include "broker/detail/inspect_objects.hh" #include "broker/internal_command.hh" namespace broker::detail { @@ -130,17 +129,10 @@ class helper { template bool apply(T x) { if constexpr (std::is_integral::value) { -#if CAF_VERSION >= 1800 if (!f_.value(x)) { err_ = f_.get_error(); return false; } -#else - if (auto err = f_(x)) { - err_ = std::move(err); - return false; - } -#endif return true; } else { static_assert(std::is_enum::value); diff --git a/src/detail/store_actor.cc b/src/detail/store_actor.cc index ebe145d85..11d8b4791 100644 --- a/src/detail/store_actor.cc +++ b/src/detail/store_actor.cc @@ -50,6 +50,8 @@ void fill_vector(vector& vec, const Ts&... xs) { void store_actor_state::init(caf::event_based_actor* self, endpoint_id this_endpoint, endpoint::clock* clock, std::string&& store_name, caf::actor&& core) { +auto ep_str=to_string(this_endpoint); +printf("store_actor.this_endpoint = %s\n", ep_str.c_str()); BROKER_ASSERT(self != nullptr); BROKER_ASSERT(clock != nullptr); this->self = self; @@ -57,6 +59,8 @@ void store_actor_state::init(caf::event_based_actor* self, this->store_name = std::move(store_name); this->id.endpoint = this_endpoint; this->id.object = self->id(); +auto id_str = to_string(this->id); +printf("store_actor.id= %s\n", id_str.c_str()); this->core = std::move(core); this->dst = topics::store_events / this->store_name; auto& cfg = self->system().config(); diff --git a/src/endpoint.cc b/src/endpoint.cc index bba27c974..71737de44 100644 --- a/src/endpoint.cc +++ b/src/endpoint.cc @@ -403,7 +403,7 @@ caf::actor endpoint::make_actor(actor_init_fun f) { // "Hide" unhandled-exception warning if users throw. self->set_exception_handler( [](caf::scheduled_actor* thisptr, std::exception_ptr& e) -> caf::error { - return caf::exit_reason::unhandled_exception; + return caf::sec::runtime_error; } ); #endif // CAF_NO_EXCEPTION diff --git a/src/error.cc b/src/error.cc index 99a4f16ca..ee6ec3ad0 100644 --- a/src/error.cc +++ b/src/error.cc @@ -53,7 +53,7 @@ constexpr size_t array_size(const T (&)[N]) { } // namespace -const char* to_string(ec code) noexcept { +std::string to_string(ec code) noexcept { auto index = static_cast(code); BROKER_ASSERT(index < array_size(ec_names)); return ec_names[index]; diff --git a/src/network_info.cc b/src/network_info.cc index 48f090620..88be4d185 100644 --- a/src/network_info.cc +++ b/src/network_info.cc @@ -1,7 +1,9 @@ -#include -#include +#include "broker/network_info.hh" + #include #include +#include +#include #include @@ -40,4 +42,9 @@ bool operator<(const network_info& x, const network_info& y) { return std::tie(x.address, x.port) < std::tie(y.address, y.port); } +std::string to_string(const network_info& info) { + using std::to_string; + return info.address + ':' + to_string(info.port); +} + } // namespace broker diff --git a/src/store_event.cc b/src/store_event.cc index 5fe54fcbd..cbfde9d3a 100644 --- a/src/store_event.cc +++ b/src/store_event.cc @@ -1,6 +1,6 @@ #include "broker/store_event.hh" -#include "caf/deep_to_string.hpp" +#include namespace broker { diff --git a/src/subscriber.cc b/src/subscriber.cc index 6ce17ec40..c1ce36840 100644 --- a/src/subscriber.cc +++ b/src/subscriber.cc @@ -69,11 +69,9 @@ class subscriber_sink : public stream_sink { // nop } -#if CAF_VERSION >= 1800 + using super::congested; + bool congested(const inbound_path&) const noexcept override { -#else - bool congested() const noexcept override { -#endif return queue_->buffer_size() >= max_qsize_; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index efcba71e3..e4cc59d9c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,7 +57,7 @@ else () set(libbroker broker_static) endif () add_executable(broker-test ${tests}) -target_link_libraries(broker-test ${libbroker}) +target_link_libraries(broker-test ${libbroker} CAF::test) set(BROKER_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/tests/benchmark/broker-cluster-benchmark.cc b/tests/benchmark/broker-cluster-benchmark.cc index 5f506ed8b..d1ae94057 100644 --- a/tests/benchmark/broker-cluster-benchmark.cc +++ b/tests/benchmark/broker-cluster-benchmark.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -183,13 +184,8 @@ struct config : actor_system_config { .add("verbose,v", "enable verbose output") .add("excluded-nodes,e", "excludes given nodes from the setup"); - set("scheduler.max-threads", 1); -#if CAF_VERSION < 1800 - set("logger.file-verbosity", caf::atom("quiet")); - broker::configuration::add_message_types(*this); -#else - set("logger.file-verbosity", "quiet"); -#endif + set("caf.scheduler.max-threads", 1); + set("caf.logger.file.verbosity", "quiet"); } string usage() { @@ -1135,6 +1131,7 @@ program_mode_t get_mode(const config& cfg) { } int main(int argc, char** argv) { + broker::configuration::init_global_state(); // Read CAF configuration. config cfg; if (auto err = cfg.parse(argc, argv)) { diff --git a/tests/cpp/alm/multipath.cc b/tests/cpp/alm/multipath.cc index a9f0188fa..e89d6f9d0 100644 --- a/tests/cpp/alm/multipath.cc +++ b/tests/cpp/alm/multipath.cc @@ -8,7 +8,6 @@ #include #include "broker/alm/routing_table.hh" -#include "broker/detail/inspect_objects.hh" using namespace broker; @@ -93,13 +92,13 @@ TEST(multipaths are serializable) { MESSAGE("serializer the path into a buffer"); { caf::binary_serializer sink{sys, buf}; - CHECK_EQUAL(detail::inspect_objects(sink, path), caf::none); + CHECK(sink.apply(path)); } multipath copy{"a"}; MESSAGE("deserializers a copy from the path from the buffer"); { caf::binary_deserializer source{sys,buf}; - CHECK_EQUAL(detail::inspect_objects(source, copy), caf::none); + CHECK(source.apply(copy)); } MESSAGE("after a serialization roundtrip, the path is equal to its copy"); CHECK_EQUAL(path, copy); diff --git a/tests/cpp/detail/data_generator.cc b/tests/cpp/detail/data_generator.cc index beff06160..09613554a 100644 --- a/tests/cpp/detail/data_generator.cc +++ b/tests/cpp/detail/data_generator.cc @@ -10,8 +10,8 @@ #include #include -#include "broker/detail/inspect_objects.hh" #include "broker/detail/meta_data_writer.hh" +#include "broker/detail/write_value.hh" using namespace broker; @@ -29,11 +29,12 @@ struct fixture { } void add_meta(data::type tag) { - CHECK_EQUAL(detail::inspect_objects(sink, tag), caf::none); + CHECK_EQUAL(detail::write_value(sink, tag), caf::none); } void add_meta(data::type tag, uint32_t container_size) { - CHECK_EQUAL(detail::inspect_objects(sink, tag, container_size), caf::none); + CHECK_EQUAL(detail::write_value(sink, tag), caf::none); + CHECK_EQUAL(detail::write_value(sink, container_size), caf::none); } data generate() { diff --git a/tests/cpp/detail/meta_command_writer.cc b/tests/cpp/detail/meta_command_writer.cc new file mode 100644 index 000000000..bee55ce2f --- /dev/null +++ b/tests/cpp/detail/meta_command_writer.cc @@ -0,0 +1,140 @@ +#define SUITE meta_command_writer + +#include "broker/detail/meta_command_writer.hh" +#include "broker/detail/read_value.hh" + +#include "test.hh" + +#include + +#include +#include + +#include "broker/data.hh" + +using namespace broker; + +namespace { + +struct fixture { + caf::binary_serializer::container_type buf; + caf::binary_serializer sink; + size_t read_pos; + + fixture() : sink(nullptr, buf), read_pos(0) { + // nop + } + + template + void push(T&& x) { + internal_command cmd{std::forward(x)}; + detail::meta_command_writer writer{sink}; + CHECK_EQUAL(writer(cmd), caf::none); + } + + template + T pull() { + caf::binary_deserializer source{nullptr, buf.data() + read_pos, + buf.size() - read_pos}; + auto result = T{}; + CHECK_EQUAL(detail::read_value(source, result), caf::none); + read_pos = buf.size() - source.remaining(); + return result; + } + + bool at_end() const { + return read_pos == buf.size(); + } +}; + +} // namespace + +CAF_TEST_FIXTURE_SCOPE(meta_command_writer_tests, fixture) + +CAF_TEST(default constructed command) { + push(internal_command{}); + CHECK_EQUAL(pull(), internal_command::type::none); + CHECK(at_end()); +} + +CAF_TEST(put_command) { + push(put_command{data{"hello"}, data{"broker"}, nil}); + CHECK_EQUAL(pull(), + internal_command::type::put_command); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 5u); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 6u); + CHECK(at_end()); +} + +CAF_TEST(put_unique_command) { + push(put_unique_command{data{"hello"}, data{"broker"}, nil, nullptr, 0}); + CHECK_EQUAL(pull(), + internal_command::type::put_unique_command); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 5u); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 6u); + CHECK(at_end()); +} + +CAF_TEST(erase_command) { + push(erase_command{data{"foobar"}}); + CHECK_EQUAL(pull(), + internal_command::type::erase_command); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 6u); + CHECK(at_end()); +} + +CAF_TEST(add_command) { + push(add_command{data{"key"}, data{"value"}, data::type::table, nil}); + CHECK_EQUAL(pull(), + internal_command::type::add_command); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 3u); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 5u); + CHECK_EQUAL(pull(), data::type::table); + CHECK(at_end()); +} + +CAF_TEST(subtract_command) { + push(subtract_command{data{"key"}, data{"value"}, nil}); + CHECK_EQUAL(pull(), + internal_command::type::subtract_command); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 3u); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 5u); + CHECK(at_end()); +} + +CAF_TEST(snapshot_command) { + push(snapshot_command{nullptr, nullptr}); + CHECK_EQUAL(pull(), + internal_command::type::snapshot_command); + CHECK(at_end()); +} + +CAF_TEST(snapshot_sync_command) { + push(snapshot_sync_command{nullptr}); + CHECK_EQUAL(pull(), + internal_command::type::snapshot_sync_command); + CHECK(at_end()); +} + +CAF_TEST(set_command) { + push(set_command{{{data{"key"}, data{"value"}}}}); + CHECK_EQUAL(pull(), + internal_command::type::set_command); + CHECK_EQUAL(pull(), 1u); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 3u); + CHECK_EQUAL(pull(), data::type::string); + CHECK_EQUAL(pull(), 5u); + CHECK(at_end()); +} + +CAF_TEST_FIXTURE_SCOPE_END() diff --git a/tests/cpp/detail/meta_data_writer.cc b/tests/cpp/detail/meta_data_writer.cc index dbde00eff..a42089f8c 100644 --- a/tests/cpp/detail/meta_data_writer.cc +++ b/tests/cpp/detail/meta_data_writer.cc @@ -9,7 +9,7 @@ #include #include -#include "broker/detail/inspect_objects.hh" +#include "broker/detail/read_value.hh" using namespace broker; @@ -35,7 +35,7 @@ struct fixture { caf::binary_deserializer source{nullptr, buf.data() + read_pos, buf.size() - read_pos}; T result{}; - CHECK_EQUAL(detail::inspect_objects(source, result), caf::none); + CHECK_EQUAL(detail::read_value(source, result), caf::none); read_pos = static_cast(source.current() - buf.data()); return result; } diff --git a/tests/cpp/integration.cc b/tests/cpp/integration.cc index 44c172db7..7d856b6a9 100644 --- a/tests/cpp/integration.cc +++ b/tests/cpp/integration.cc @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -59,17 +58,12 @@ configuration make_config() { broker_options options; options.disable_ssl = true; configuration cfg(options); - cfg.parse(caf::test::engine::argc(), caf::test::engine::argv()); -#if CAF_VERSION < 1800 - using caf::atom; - cfg.set("middleman.network-backend", atom("testing")); - cfg.set("scheduler.policy", atom("testing")); - cfg.set("logger.inline-output", true); -#else + if (auto err = cfg.parse(caf::test::engine::argc(), + caf::test::engine::argv())) + CAF_FAIL("parsing the config failed: " << to_string(err)); cfg.set("caf.middleman.network-backend", "testing"); cfg.set("caf.scheduler.policy", "testing"); cfg.set("caf.logger.inline-output", true); -#endif return cfg; } @@ -147,10 +141,9 @@ struct peer_fixture { sys(ep.system()), sched(dynamic_cast(sys.scheduler())), mm(sys.middleman()), - mpx(dynamic_cast(mm.backend())), - credit_round_interval(get_or(sys.config(), - "stream.credit-round-interval", - caf::defaults::stream::credit_round_interval)) { + mpx(dynamic_cast(mm.backend())) { + // Register at parent. + parent->peers.emplace(name, this); // Run initialization code exec_loop(); // Give the core actor a recognizable ID. diff --git a/tests/cpp/master.cc b/tests/cpp/master.cc index 13747ce07..be330ee1f 100644 --- a/tests/cpp/master.cc +++ b/tests/cpp/master.cc @@ -218,7 +218,7 @@ TEST(master_with_clone) { CHECK_EQUAL(value_of(ds_earth.get("test")), data{123}); // --- phase 5: peer from earth to mars -------------------------------------- auto foo_master = "foo" / topics::master_suffix; -// Initiate handshake between core1 and core2. + // Initiate handshake between core1 and core2. earth.self->send(core1, atom::peer_v, core2_proxy.node(), core2_proxy); run(tick_interval); // --- phase 6: attach a clone on mars --------------------------------------- diff --git a/tests/cpp/ssl.cc b/tests/cpp/ssl.cc index d80a50e27..d92685b33 100644 --- a/tests/cpp/ssl.cc +++ b/tests/cpp/ssl.cc @@ -19,22 +19,19 @@ using namespace broker; namespace { -#if CAF_VERSION < 1800 -#define CFG_PREFIX -#else -#define CFG_PREFIX "caf." -#endif - configuration make_config(std::string cert_id) { configuration cfg; - cfg.parse(caf::test::engine::argc(), caf::test::engine::argv()); + if (auto err = cfg.parse(caf::test::engine::argc(), + caf::test::engine::argv())) + CAF_FAIL("parsing the config failed: " << to_string(err)); + cfg.set("caf.logger.inline-output", true); if (cert_id.size()) { auto test_dir = getenv("BROKER_TEST_DIR"); CAF_REQUIRE(test_dir); auto cd = std::string(test_dir) + "/cpp/certs/"; - cfg.set(CFG_PREFIX "openssl.cafile", cd + "ca.pem"); - cfg.set(CFG_PREFIX "openssl.certificate", cd + "cert." + cert_id + ".pem"); - cfg.set(CFG_PREFIX "openssl.key", cd + "key." + cert_id + ".pem"); + cfg.set("caf.openssl.cafile", cd + "ca.pem"); + cfg.set("caf.openssl.certificate", cd + "cert." + cert_id + ".pem"); + cfg.set("caf.openssl.key", cd + "key." + cert_id + ".pem"); MESSAGE("using certififcate " << cfg.openssl_certificate << ", key " << cfg.openssl_key); } diff --git a/tests/cpp/test.cc b/tests/cpp/test.cc index 2e6da3387..4b187a974 100644 --- a/tests/cpp/test.cc +++ b/tests/cpp/test.cc @@ -17,12 +17,6 @@ #include "Winsock2.h" #endif -#if CAF_VERSION < 1800 -#define CFG_PREFIX -#else -#define CFG_PREFIX "caf." -#endif - using namespace caf; using namespace broker; @@ -30,10 +24,7 @@ base_fixture::base_fixture() : ep(make_config()), sys(ep.system()), self(sys), - sched(dynamic_cast(sys.scheduler())), - credit_round_interval( - get_or(sys.config(), CFG_PREFIX "stream.credit-round-interval", - caf::defaults::stream::credit_round_interval)) { + sched(dynamic_cast(sys.scheduler())) { init_socket_api(); } @@ -83,9 +74,7 @@ void base_fixture::consume_message() { } int main(int argc, char** argv) { -#if CAF_VERSION >= 1800 caf::init_global_meta_objects(); -#endif broker::configuration::init_global_state(); //if (! broker::logger::file(broker::logger::debug, "broker-unit-test.log")) // return 1; diff --git a/tests/cpp/test.hh b/tests/cpp/test.hh index cb142f969..a9b4a9e83 100644 --- a/tests/cpp/test.hh +++ b/tests/cpp/test.hh @@ -15,10 +15,10 @@ #include "broker/configuration.hh" #include "broker/detail/channel.hh" -#include "broker/detail/is_legacy_inspector.hh" #include "broker/endpoint.hh" #include "broker/fwd.hh" +#include #include // -- test setup macros -------------------------------------------------------- @@ -91,21 +91,15 @@ CAF_END_TYPE_ID_BLOCK(broker_test) // -- inspection support ------------------------------------------------------- template -typename Inspector::result_type inspect(Inspector& f, producer_msg& x) { - if constexpr (broker::detail::is_legacy_inspector) - return f(x.source, x.content); - else - return f.object(x).fields(f.field("source", x.source), - f.field("content", x.content)); +bool inspect(Inspector& f, producer_msg& x) { + return f.object(x).fields(f.field("source", x.source), + f.field("content", x.content)); } template -typename Inspector::result_type inspect(Inspector& f, consumer_msg& x) { - if constexpr (broker::detail::is_legacy_inspector) - return f(x.source, x.content); - else - return f.object(x).fields(f.field("source", x.source), - f.field("content", x.content)); +bool inspect(Inspector& f, consumer_msg& x) { + return f.object(x).fields(f.field("source", x.source), + f.field("content", x.content)); } // -- fixtures ----------------------------------------------------------------- @@ -166,7 +160,6 @@ public: caf::actor_system& sys; caf::scoped_actor self; scheduler_type& sched; - caf::timespan credit_round_interval; using super::run; diff --git a/tests/python/broker-cluster-benchmark.py b/tests/python/broker-cluster-benchmark.py index 8954961e2..e9da90589 100644 --- a/tests/python/broker-cluster-benchmark.py +++ b/tests/python/broker-cluster-benchmark.py @@ -41,7 +41,7 @@ def clear_environment(self): def test_config_generation(exe, recording_dir, expected): dirs = [f.path for f in os.scandir(recording_dir) if f.is_dir()] - cmd = [exe, '--logger.verbosity=quiet', '--mode=generate-config'] + dirs + cmd = [exe, '--caf.logger.console.verbosity=quiet', '--mode=generate-config'] + dirs with subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE, close_fds=True, universal_newlines=True) as proc: output, errors = proc.communicate() if proc.returncode != 0: @@ -57,7 +57,7 @@ def test_config_generation(exe, recording_dir, expected): return output def run_benchmark(exe, config): - cmd = [exe, '--logger.verbosity=quiet', '--cluster-config-file=-'] + cmd = [exe, '--caf.logger.console.verbosity=quiet', '--cluster-config-file=-'] with subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE, close_fds=True, universal_newlines=True) as proc: proc.stdin.write(config) proc.stdin.close() diff --git a/tests/python/communication.py b/tests/python/communication.py index 3b82197a7..020f7d4ff 100644 --- a/tests/python/communication.py +++ b/tests/python/communication.py @@ -1,7 +1,4 @@ -# This is needed in order to use the "ipaddress" module on Python 2.7. -from __future__ import unicode_literals - import unittest import multiprocessing import sys @@ -17,7 +14,6 @@ def test_ping(self): broker.Endpoint() as ep2, \ ep1.make_subscriber("/test") as s1, \ ep2.make_subscriber("/test") as s2: - port = ep1.listen("127.0.0.1", 0) self.assertTrue(ep2.peer("127.0.0.1", port, 1.0)) @@ -138,7 +134,10 @@ def test_status_subscriber_error(self): self.assertEqual(st1.code(), broker.EC.PeerUnavailable) # Async version. - ep1.peer_nosync("127.0.0.1", 1947, 0.0) + ep1.peer_nosync("127.0.0.1", 1947, 1.0) + st1 = es1.get() + self.assertEqual(st1.code(), broker.EC.PeerUnavailable) + st1 = es1.get() self.assertEqual(st1.code(), broker.EC.PeerUnavailable) diff --git a/tests/python/data.py b/tests/python/data.py index e19e6ec15..84d7f436d 100644 --- a/tests/python/data.py +++ b/tests/python/data.py @@ -4,9 +4,6 @@ # sure that the transparent conversion works as expected. # -# This is needed in order to use the "ipaddress" module on Python 2.7. -from __future__ import unicode_literals - import datetime import time import math @@ -16,9 +13,6 @@ import broker -# Check the Python version -py2 = (sys.version_info.major < 3) - class TestDataConstruction(unittest.TestCase): @@ -44,17 +38,6 @@ def check_to_py(self, b, p): b2p = broker.Data.to_py(b) #print("[to_py] data({} / {}) -> ({} / {})".format(str(b), b.get_type(), b2p, type(b2p))) - if py2: - # Python 2.7 compatibility: convert objects of type 'int' to 'long' - # to match the type returned by broker.Data.to_py(b) - if isinstance(p, int) and not isinstance(p, bool): - p = long(p) - - # Python 2.7 compatibility: convert objects of type 'str' to - # 'unicode' to match the type returned by broker.Data.to_py(b) - if isinstance(p, str): - p = unicode(p) - self.assertIsInstance(b2p, type(p)) if isinstance(p, datetime.datetime): @@ -113,25 +96,15 @@ def test_integer(self): self.check_to_broker_and_back(-42, '-42', broker.Data.Type.Integer) - # Test a value that is beyond range of unsigned 32-bit integer (on - # 32-bit python 2.x systems, this will be type 'long') + # Test a value that is beyond range of unsigned 32-bit integer self.check_to_broker_and_back(5123123123, '5123123123', broker.Data.Type.Integer) - if py2: - # Explicitly pass a 'long' value (this is not relevant for python 3) - self.check_to_broker_and_back(long(5), '5', broker.Data.Type.Integer) - def test_count(self): self.check_to_broker_and_back(broker.Count(42), '42', broker.Data.Type.Count) - # Test a value that is beyond range of unsigned 32-bit integer (on - # 32-bit python 2.x systems, this will be type 'long') + # Test a value that is beyond range of unsigned 32-bit integer self.check_to_broker_and_back(broker.Count(5123123123), '5123123123', broker.Data.Type.Count) - if py2: - # Explicitly pass a 'long' value (this is not relevant for python 3) - self.check_to_broker_and_back(broker.Count(long(5)), '5', broker.Data.Type.Count) - def test_count_overflow(self): with self.assertRaises(Exception) as context: # I've seen this raise either OverflowError or SystemError @@ -182,9 +155,8 @@ def test_timestamp(self): today = datetime.datetime.now(broker.utc) self.check_to_broker_and_back(today, None, broker.Data.Type.Timestamp) - if not py2: - today = datetime.datetime.now(datetime.timezone.utc) - self.check_to_broker_and_back(today, None, broker.Data.Type.Timestamp) + today = datetime.datetime.now(datetime.timezone.utc) + self.check_to_broker_and_back(today, None, broker.Data.Type.Timestamp) today = datetime.datetime.now() self.check_to_broker_and_back(today, None, broker.Data.Type.Timestamp) @@ -208,17 +180,6 @@ def test_string(self): self.check_to_broker_and_back('\ttab', '\ttab', broker.Data.Type.String) self.check_to_broker_and_back('new\n', 'new\n', broker.Data.Type.String) - if py2: - # These test cases are not relevant for Python 3 - - # Explicitly pass a 'unicode' value (this is relevant in case - # unicode_literals isn't imported) - self.check_to_broker_and_back(u'foo2', 'foo2', broker.Data.Type.String) - - # Explicitly pass a 'str' value (this is relevant in case - # unicode_literals is imported) - self.check_to_broker_and_back(str('foo3'), 'foo3', broker.Data.Type.String) - def test_address_v4(self): addr = ipaddress.IPv4Address('0.0.0.0') self.check_to_broker_and_back(addr, '0.0.0.0', broker.Data.Type.Address) diff --git a/tests/python/forwarding.py b/tests/python/forwarding.py index c960e8345..a113540ff 100644 --- a/tests/python/forwarding.py +++ b/tests/python/forwarding.py @@ -6,6 +6,14 @@ import broker +def cleanup(es, ss): + for s in ss: + if s: + s.reset() + + for e in es: + e.shutdown() + def setup_peers(opts1=None, opts2=None, opts3=None, opts4=None, create_s1=True, create_s2=True, create_s3=True, create_s4=True): def cfg(opts): return broker.Configuration(opts) if opts else broker.Configuration(broker.BrokerOptions()) @@ -45,6 +53,7 @@ def test_two_subscribed_hops(self): self.assertEqual(x, ('/test/foo', 'Foo!')) x = s1.get() self.assertEqual(x, ('/test/bar', 'Bar!')) + cleanup((ep1, ep2, ep3, ep4), (s1, s2, s3, s4)) def test_two_unsubscribed_hops(self): # Two hops that are not subscribed, but still forward due to the source @@ -61,6 +70,7 @@ def test_two_unsubscribed_hops(self): self.assertEqual(x, ('/test/foo', 'Foo!')) x = s1.get() self.assertEqual(x, ('/test/bar', 'Bar!')) + cleanup((ep1, ep2, ep3, ep4), (s1, s2, s3, s4)) if __name__ == '__main__': #TestCommunication().test_two_hops() diff --git a/tests/python/ssl-tests.py b/tests/python/ssl-tests.py index d2d99a9ad..fe98ebad3 100644 --- a/tests/python/ssl-tests.py +++ b/tests/python/ssl-tests.py @@ -28,18 +28,16 @@ def test_ssl_auth_success_ca(self): cfg.openssl_key = data_path("key.1.pem") cfg.openssl_cafile = data_path("ca.pem") - ep1 = broker.Endpoint(cfg) - ep2 = broker.Endpoint(cfg) - s1 = ep1.make_subscriber("/test") - s2 = ep2.make_subscriber("/test") - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, True) + with broker.Endpoint(cfg) as ep1, \ + broker.Endpoint(cfg) as ep2, \ + ep1.make_subscriber("/test") as s1, \ + ep2.make_subscriber("/test") as s2: - self.check_ping(ep1, s1, ep2, s2) + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, True) - ep1.shutdown() - ep2.shutdown() + self.check_ping(ep1, s1, ep2, s2) def test_ssl_auth_success_ca_pw(self): cfg = broker.Configuration(broker.BrokerOptions()) @@ -48,18 +46,16 @@ def test_ssl_auth_success_ca_pw(self): cfg.openssl_cafile = data_path("ca.pem") cfg.openssl_passphrase = "12345" - ep1 = broker.Endpoint(cfg) - ep2 = broker.Endpoint(cfg) - s1 = ep1.make_subscriber("/test") - s2 = ep2.make_subscriber("/test") - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, True) + with broker.Endpoint(cfg) as ep1, \ + broker.Endpoint(cfg) as ep2, \ + ep1.make_subscriber("/test") as s1, \ + ep2.make_subscriber("/test") as s2: - self.check_ping(ep1, s1, ep2, s2) + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, True) - ep1.shutdown() - ep2.shutdown() + self.check_ping(ep1, s1, ep2, s2) def test_ssl_auth_success_self_signed(self): cfg = broker.Configuration(broker.BrokerOptions()) @@ -67,18 +63,16 @@ def test_ssl_auth_success_self_signed(self): cfg.openssl_key = data_path("key.self-signed.pem") cfg.openssl_cafile = data_path("cert.self-signed.pem") - ep1 = broker.Endpoint(cfg) - ep2 = broker.Endpoint(cfg) - s1 = ep1.make_subscriber("/test") - s2 = ep2.make_subscriber("/test") - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, True) + with broker.Endpoint(cfg) as ep1, \ + broker.Endpoint(cfg) as ep2, \ + ep1.make_subscriber("/test") as s1, \ + ep2.make_subscriber("/test") as s2: - self.check_ping(ep1, s1, ep2, s2) + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, True) - ep1.shutdown() - ep2.shutdown() + self.check_ping(ep1, s1, ep2, s2) def test_ssl_auth_failure_self_signed(self): cfg1 = broker.Configuration(broker.BrokerOptions()) @@ -91,20 +85,20 @@ def test_ssl_auth_failure_self_signed(self): cfg2.openssl_key = data_path("key.self-signed.pem") cfg2.openssl_cafile = data_path("cert.self-signed.pem") - ep1 = broker.Endpoint(cfg1) - ep2 = broker.Endpoint(cfg2) - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, False) + with broker.Endpoint(cfg1) as ep1, \ + broker.Endpoint(cfg2) as ep2: - ep1 = broker.Endpoint(cfg2) - ep2 = broker.Endpoint(cfg1) - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, False) + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, False) + + with broker.Endpoint(cfg2) as ep1, \ + broker.Endpoint(cfg1) as ep2: + + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, False) - ep1.shutdown() - ep2.shutdown() def test_ssl_auth_failure_no_auth(self): cfg1 = broker.Configuration(broker.BrokerOptions()) @@ -114,17 +108,19 @@ def test_ssl_auth_failure_no_auth(self): cfg2 = broker.Configuration(broker.BrokerOptions()) - ep1 = broker.Endpoint(cfg1) - ep2 = broker.Endpoint(cfg2) - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, False) + with broker.Endpoint(cfg1) as ep1, \ + broker.Endpoint(cfg2) as ep2: + + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, False) - ep1 = broker.Endpoint(cfg2) - ep2 = broker.Endpoint(cfg1) - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, False) + with broker.Endpoint(cfg2) as ep1, \ + broker.Endpoint(cfg1) as ep2: + + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, False) def test_ssl_auth_failure_no_ssl(self): cfg1 = broker.Configuration(broker.BrokerOptions()) @@ -134,17 +130,19 @@ def test_ssl_auth_failure_no_ssl(self): cfg2 = broker.Configuration(broker.BrokerOptions()) - ep1 = broker.Endpoint(cfg1) - ep2 = broker.Endpoint(cfg2) - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, False) + with broker.Endpoint(cfg1) as ep1, \ + broker.Endpoint(cfg2) as ep2: + + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, False) + + with broker.Endpoint(cfg2) as ep1, \ + broker.Endpoint(cfg1) as ep2: - ep1 = broker.Endpoint(cfg2) - ep2 = broker.Endpoint(cfg1) - port = ep1.listen("127.0.0.1", 0) - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, False) + port = ep1.listen("127.0.0.1", 0) + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, False) def XXXtest_ssl_auth_failure_ca_pw(self): cfg = broker.Configuration(broker.BrokerOptions()) @@ -153,17 +151,15 @@ def XXXtest_ssl_auth_failure_ca_pw(self): cfg.openssl_cafile = data_path("ca.pem") cfg.openssl_passphrase = "WRONG PASSWORD" - ep1 = broker.Endpoint(cfg) - ep2 = broker.Endpoint(cfg) - port = ep1.listen("127.0.0.1", 0) + with broker.Endpoint(cfg) as ep1, \ + broker.Endpoint(cfg) as ep2: - # TODO: This correctly generates an exception in CAF, for which I - # don't know where to catch it. - r = ep2.peer("127.0.0.1", port, 0) - self.assertEqual(r, False) + port = ep1.listen("127.0.0.1", 0) - ep1.shutdown() - ep2.shutdown() + # TODO: This correctly generates an exception in CAF, for which I + # don't know where to catch it. + r = ep2.peer("127.0.0.1", port, 0) + self.assertEqual(r, False) if __name__ == '__main__': unittest.main(verbosity=3) diff --git a/tests/python/store.py b/tests/python/store.py index 2a69b4bb3..c3585add3 100644 --- a/tests/python/store.py +++ b/tests/python/store.py @@ -9,26 +9,32 @@ def create_stores(self): ep0 = broker.Endpoint() - m = ep0.attach_master("test", broker.Backend.Memory) - port = ep0.listen("127.0.0.1", 0) - ep1 = broker.Endpoint() - c1 = ep1.attach_clone("test") - self.assertEqual(ep1.peer("127.0.0.1", port), True) - ep2 = broker.Endpoint() - c2 = ep2.attach_clone("test") - es2 = ep2.make_status_subscriber() - self.assertEqual(ep2.peer("127.0.0.1", port), True) - ep0.await_peer(ep1.node_id()) - ep1.await_peer(ep0.node_id()) - ep0.await_peer(ep2.node_id()) - ep2.await_peer(ep0.node_id()) - ep1.await_peer(ep2.node_id()) - ep2.await_peer(ep1.node_id()) + with ep0.make_subscriber("/test") as s0, \ + ep1.make_subscriber("/test") as s1, \ + ep1.make_status_subscriber() as es1, \ + ep2.make_subscriber("/test") as s2, \ + ep2.make_status_subscriber() as es2: + + p = ep0.listen("127.0.0.1", 0) + ep1.peer("127.0.0.1", p) + ep2.peer("127.0.0.1", p) - return (ep0, ep1, ep2, m, c1, c2) + # TODO: This doesn't work. Once it does, remove the event handshake. + # es1.get() + # es2.get() + ep0.publish("/test", "go-ahead") + s1.get() + s2.get() + #### + + m = ep0.attach_master("test", broker.Backend.Memory) + c1 = ep1.attach_clone("test") + c2 = ep2.attach_clone("test") + + return (ep0, ep1, ep2, m, c1, c2) # Runs a test with one master and two clones # --tri-setup-start @@ -69,6 +75,7 @@ def test_basic(self): # --master-start with broker.Endpoint() as ep1, \ ep1.attach_master("test", broker.Backend.Memory) as m: + m.put("key", "value") x = m.get("key") # x == "value" diff --git a/tests/python/zeek.py b/tests/python/zeek.py index 333b992a7..d8124c74e 100644 --- a/tests/python/zeek.py +++ b/tests/python/zeek.py @@ -76,37 +76,36 @@ def RunZeek(script, port): class TestCommunication(unittest.TestCase): def test_ping(self): - ep = broker.Endpoint() - sub = ep.make_subscriber("/test") - port = ep.listen("127.0.0.1", 0) + with broker.Endpoint() as ep, \ + ep.make_subscriber("/test") as sub: - p = multiprocessing.Process(target=RunZeek, args=(ZeekPing, port)) - p.daemon = True - p.start() + port = ep.listen("127.0.0.1", 0) - for i in range(0, 6): - (t, msg) = sub.get() - ev = broker.zeek.Event(msg) - (s, c) = ev.args() - expected_arg = "x" + "Xx" * i + p = multiprocessing.Process(target=RunZeek, args=(ZeekPing, port)) + p.daemon = True + p.start() - if i == 5: - expected_arg = expected_arg.encode('utf-8') + b'\x82' + for i in range(0, 6): + (t, msg) = sub.get() + ev = broker.zeek.Event(msg) + (s, c) = ev.args() + expected_arg = "x" + "Xx" * i - self.assertEqual(ev.name(), "ping") - self.assertEqual(s, expected_arg) - self.assertEqual(c, i) + if i == 5: + expected_arg = expected_arg.encode('utf-8') + b'\x82' - if i < 3: - ev = broker.zeek.Event("pong", s + "X", c) - elif i < 5: - ev = broker.zeek.Event("pong", s.encode('utf-8') + b'X', c) - else: - ev = broker.zeek.Event("pong", 'done', c) + self.assertEqual(ev.name(), "ping") + self.assertEqual(s, expected_arg) + self.assertEqual(c, i) - ep.publish("/test", ev) + if i < 3: + ev = broker.zeek.Event("pong", s + "X", c) + elif i < 5: + ev = broker.zeek.Event("pong", s.encode('utf-8') + b'X', c) + else: + ev = broker.zeek.Event("pong", 'done', c) - ep.shutdown() + ep.publish("/test", ev) if __name__ == '__main__': unittest.main(verbosity=3)