Commit b403c75e authored by Dominik Charousset's avatar Dominik Charousset

Add compiler flag for opting into type ID checking

When enabled, the flag adds a static assertion in `make_message` that
makes sure each type has a message ID assigned to it.
parent f102a1b1
...@@ -514,10 +514,22 @@ endif() ...@@ -514,10 +514,22 @@ endif()
# all projects need the headers of the core components # all projects need the headers of the core components
include_directories("${CAF_INCLUDE_DIRS}") include_directories("${CAF_INCLUDE_DIRS}")
# -- unit tests setup ----------------------------------------------------------
################################################################################ if(NOT CAF_NO_UNIT_TESTS)
# add targets # enable_testing()
################################################################################ function(caf_add_test_suites target)
foreach(suiteName ${ARGN})
string(REPLACE "." "/" suitePath ${suiteName})
target_sources(${target} PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/test/${suitePath}.cpp")
add_test(NAME ${suiteName}
COMMAND ${target} -r300 -n -v5 -s"^${suiteName}$")
endforeach()
endfunction()
endif()
# -- add targets ---------------------------------------------------------------
macro(add_caf_lib name) macro(add_caf_lib name)
string(TOUPPER ${name} upper_name) string(TOUPPER ${name} upper_name)
...@@ -653,48 +665,6 @@ add_optional_caf_binaries(examples) ...@@ -653,48 +665,6 @@ add_optional_caf_binaries(examples)
# build tools if not being told otherwise # build tools if not being told otherwise
add_optional_caf_binaries(tools) add_optional_caf_binaries(tools)
################################################################################
# unit tests setup #
################################################################################
if(NOT CAF_NO_UNIT_TESTS)
# setup unit test binary
add_executable(caf-test
libcaf_test/src/caf-test.cpp
libcaf_test/caf/test/unit_test.hpp
libcaf_test/caf/test/unit_test_impl.hpp
${CAF_ALL_UNIT_TESTS})
target_link_libraries(caf-test
${CAF_EXTRA_LDFLAGS}
${CAF_LIBRARIES}
${PTHREAD_LIBRARIES})
add_custom_target(all_unit_tests)
add_dependencies(caf-test all_unit_tests)
# enumerate all test suites.
foreach(test ${CAF_ALL_UNIT_TESTS})
file(STRINGS ${test} contents)
foreach(line ${contents})
if ("${line}" MATCHES "CAF_SUITE (.*)")
string(REGEX REPLACE ".* CAF_SUITE (.*)" "\\1" suite ${line})
list(APPEND suites ${suite})
endif()
endforeach()
endforeach()
list(REMOVE_DUPLICATES suites)
# creates one CMake test per test suite.
macro (make_test suite)
string(REPLACE " " "_" test_name ${suite})
set(caf_test ${EXECUTABLE_OUTPUT_PATH}/caf-test)
add_test(${test_name} ${caf_test} -r 300 -n -v 5 -s "${suite}" ${ARGN})
endmacro ()
list(LENGTH suites num_suites)
message(STATUS "Found ${num_suites} test suites")
foreach(suite ${suites})
make_test("${suite}")
endforeach ()
endif()
# -- Setup for building manual and API documentation --------------------------- # -- Setup for building manual and API documentation ---------------------------
if(NOT caf_is_subproject) if(NOT caf_is_subproject)
......
...@@ -7,6 +7,7 @@ defaultReleaseBuildFlags = [ ...@@ -7,6 +7,7 @@ defaultReleaseBuildFlags = [
'CAF_ENABLE_RUNTIME_CHECKS:BOOL=yes', 'CAF_ENABLE_RUNTIME_CHECKS:BOOL=yes',
'CAF_NO_OPENCL:BOOL=yes', 'CAF_NO_OPENCL:BOOL=yes',
'CAF_INSTALL_UNIT_TESTS:BOOL=yes', 'CAF_INSTALL_UNIT_TESTS:BOOL=yes',
'CAF_ENABLE_TYPE_ID_CHECKS:BOOL=yes',
] ]
// Default CMake flags for debug builds. // Default CMake flags for debug builds.
...@@ -14,6 +15,7 @@ defaultDebugBuildFlags = defaultReleaseBuildFlags + [ ...@@ -14,6 +15,7 @@ defaultDebugBuildFlags = defaultReleaseBuildFlags + [
'CAF_ENABLE_ADDRESS_SANITIZER:BOOL=yes', 'CAF_ENABLE_ADDRESS_SANITIZER:BOOL=yes',
'CAF_LOG_LEVEL:STRING=TRACE', 'CAF_LOG_LEVEL:STRING=TRACE',
'CAF_ENABLE_ACTOR_PROFILER:BOOL=yes', 'CAF_ENABLE_ACTOR_PROFILER:BOOL=yes',
'CAF_ENABLE_TYPE_ID_CHECKS:BOOL=yes',
] ]
// Configures the behavior of our stages. // Configures the behavior of our stages.
...@@ -25,7 +27,6 @@ config = [ ...@@ -25,7 +27,6 @@ config = [
'build', 'build',
'style', 'style',
'tests', 'tests',
'coverage',
], ],
// Our build matrix. Keys are the operating system labels and values are build configurations. // Our build matrix. Keys are the operating system labels and values are build configurations.
buildMatrix: [ buildMatrix: [
...@@ -36,7 +37,6 @@ config = [ ...@@ -36,7 +37,6 @@ config = [
['Linux', [ ['Linux', [
builds: ['debug'], builds: ['debug'],
tools: ['gcc8'], tools: ['gcc8'],
extraSteps: ['coverageReport'],
]], ]],
['Linux', [ ['Linux', [
builds: ['debug'], builds: ['debug'],
...@@ -92,20 +92,6 @@ config = [ ...@@ -92,20 +92,6 @@ config = [
], ],
], ],
], ],
// Configures what binary the coverage report uses and what paths to exclude.
coverage: [
binary: 'build/bin/caf-test',
relativeExcludePaths: [
'examples',
'tools',
'libcaf_test',
'libcaf_core/test',
'libcaf_io/test',
'libcaf_openssl/test',
'libcaf_opencl',
'libcaf_core/caf/scheduler/profiled_coordinator.hpp',
],
],
] ]
// Declarative pipeline for triggering all stages. // Declarative pipeline for triggering all stages.
......
...@@ -32,3 +32,5 @@ ...@@ -32,3 +32,5 @@
#cmakedefine CAF_NO_EXCEPTIONS #cmakedefine CAF_NO_EXCEPTIONS
#cmakedefine CAF_ENABLE_ACTOR_PROFILER #cmakedefine CAF_ENABLE_ACTOR_PROFILER
#cmakedefine CAF_ENABLE_TYPE_ID_CHECKS
...@@ -213,3 +213,126 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/caf" ...@@ -213,3 +213,126 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/caf"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.hpp" FILES_MATCHING PATTERN "*.hpp"
) )
# -- build unit tests ----------------------------------------------------------
if(CAF_NO_UNIT_TESTS)
return()
endif()
add_executable(caf-core-test test/core-test.cpp)
target_include_directories(caf-core-test PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/test")
if (CAF_BUILD_STATIC_ONLY OR CAF_BUILD_STATIC)
target_link_libraries(caf-core-test libcaf_core_static ${CAF_EXTRA_LDFLAGS})
else()
target_link_libraries(caf-core-test libcaf_core_shared ${CAF_EXTRA_LDFLAGS})
endif()
caf_add_test_suites(caf-core-test
actor_clock
actor_factory
actor_lifetime
actor_pool
actor_profiler
actor_registry
actor_system_config
actor_termination
aout
behavior
blocking_actor
broadcast_downstream_manager
byte
composition
config_option
config_option_set
config_value
config_value_adaptor
constructor_attach
continuous_streaming
cow_tuple
decorator.sequencer
deep_to_string
detached_actors
detail.bounds_checker
detail.ini_consumer
detail.limited_vector
detail.parse
detail.parser.read_bool
detail.parser.read_floating_point
detail.parser.read_ini
detail.parser.read_number
detail.parser.read_number_or_timespan
detail.parser.read_signed_integer
detail.parser.read_string
detail.parser.read_timespan
detail.parser.read_unsigned_integer
detail.ringbuffer
detail.ripemd_160
detail.serialized_size
detail.tick_emitter
detail.unique_function
detail.unordered_flat_map
dictionary
dynamic_spawn
expected
function_view
fused_downstream_manager
handles
inspector
intrusive.drr_cached_queue
intrusive.drr_queue
intrusive.fifo_inbox
intrusive.lifo_inbox
intrusive.task_queue
intrusive.wdrr_dynamic_multiplexed_queue
intrusive.wdrr_fixed_multiplexed_queue
intrusive_ptr
ipv4_address
ipv4_endpoint
ipv4_subnet
ipv6_address
ipv6_endpoint
ipv6_subnet
local_group
logger
mailbox_element
make_config_value_field
message
message_id
message_lifetime
metaprogramming
mixin.requester
mixin.sender
mock_streaming_classes
native_streaming_classes
node_id
optional
or_else
pipeline_streaming
policy.categorized
request_timeout
result
selective_streaming
serialization
settings
simple_timeout
span
stateful_actor
string_algorithms
string_view
sum_type
thread_hook
typed_behavior
typed_response_promise
typed_spawn
unit
uri
variant
)
if(NOT CAF_NO_EXCEPTIONS)
caf_add_test_suites(caf-core-test custom_exception_handler)
endif()
...@@ -168,12 +168,7 @@ public: ...@@ -168,12 +168,7 @@ public:
/// Adds message type `T` with runtime type info `name`. /// Adds message type `T` with runtime type info `name`.
template <class T> template <class T>
actor_system_config& add_message_type(std::string name) { actor_system_config& add_message_type(std::string name) {
static_assert(std::is_empty<T>::value assert_message_type_eligible<T>();
|| std::is_same<T, actor>::value // silence add_actor_type err
|| is_typed_actor<T>::value
|| (std::is_default_constructible<T>::value
&& std::is_copy_constructible<T>::value),
"T must provide default and copy constructors");
std::string stream_name = "stream<"; std::string stream_name = "stream<";
stream_name += name; stream_name += name;
stream_name += ">"; stream_name += ">";
...@@ -421,6 +416,17 @@ protected: ...@@ -421,6 +416,17 @@ protected:
config_option_set custom_options_; config_option_set custom_options_;
private: private:
template <class T>
static void assert_message_type_eligible() {
static_assert(
std::is_empty<T>::value
|| std::is_same<T, actor>::value // silence add_actor_type err
|| is_typed_actor<T>::value
|| (std::is_default_constructible<T>::value
&& std::is_copy_constructible<T>::value),
"T must provide default and copy constructors");
}
template <class T> template <class T>
void add_message_type_impl(std::string name) { void add_message_type_impl(std::string name) {
type_names_by_rtti.emplace(std::type_index(typeid(T)), name); type_names_by_rtti.emplace(std::type_index(typeid(T)), name);
...@@ -435,7 +441,9 @@ private: ...@@ -435,7 +441,9 @@ private:
template <long I, long... Is> template <long I, long... Is>
void add_message_types(detail::int_list<I, Is...>) { void add_message_types(detail::int_list<I, Is...>) {
add_message_type<typename type_by_id<I>::type>(type_name_by_id<I>::value); using type = typename type_by_id<I>::type;
assert_message_type_eligible<type>();
add_message_type_impl<type>(type_name_by_id<I>::value);
add_message_types(detail::int_list<Is...>{}); add_message_types(detail::int_list<Is...>{});
} }
......
...@@ -22,106 +22,144 @@ ...@@ -22,106 +22,144 @@
#include <type_traits> #include <type_traits>
#include "caf/actor_traits.hpp" #include "caf/actor_traits.hpp"
#include "caf/fwd.hpp" #include "caf/detail/squashed_int.hpp"
#include "caf/detail/type_list.hpp" #include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/error.hpp"
#include "caf/fwd.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
template <class T, constexpr int integral_type_flag = 0x01;
bool IsDyn = std::is_base_of<dynamically_typed_actor_base, T>::value, constexpr int error_type_flag = 0x02;
bool IsStat = std::is_base_of<statically_typed_actor_base, T>::value> constexpr int dynamically_typed_actor_flag = 0x04;
struct implicit_actor_conversions { constexpr int statically_typed_actor_flag = 0x08;
template <bool, int>
struct conversion_flag {
static constexpr int value = 0;
};
template <int Value>
struct conversion_flag<true, Value> {
static constexpr int value = Value;
};
template <class T>
struct implicit_conversion_oracle {
static constexpr int value
= conversion_flag<std::is_integral<T>::value, integral_type_flag>::value
| conversion_flag<std::is_convertible<T, error>::value,
error_type_flag>::value
| conversion_flag<std::is_base_of<dynamically_typed_actor_base, T>::value,
dynamically_typed_actor_flag>::value
| conversion_flag<std::is_base_of<statically_typed_actor_base, T>::value,
statically_typed_actor_flag>::value;
};
template <class T, int = implicit_conversion_oracle<T>::value>
struct implicit_conversions;
template <class T>
struct implicit_conversions<T, 0> {
using type = T; using type = T;
}; };
template <>
struct implicit_conversions<bool, integral_type_flag> {
using type = bool;
};
template <class T>
struct implicit_conversions<T, integral_type_flag> {
using type = squashed_int_t<T>;
};
template <class T> template <class T>
struct implicit_actor_conversions<T, true, false> { struct implicit_conversions<T, dynamically_typed_actor_flag> {
using type = actor; using type = actor;
}; };
template <class T> template <class T>
struct implicit_actor_conversions<T, false, true> { struct implicit_conversions<T, statically_typed_actor_flag> {
using type = using type =
typename detail::tl_apply< typename detail::tl_apply<typename T::signatures, typed_actor>::type;
typename T::signatures,
typed_actor
>::type;
}; };
template <> template <>
struct implicit_actor_conversions<actor_control_block, false, false> { struct implicit_conversions<actor_control_block*, 0> {
using type = strong_actor_ptr; using type = strong_actor_ptr;
}; };
template <class T> template <class T>
struct implicit_conversions { struct implicit_conversions<T, error_type_flag> {
using type = using type = error;
typename std::conditional<
std::is_convertible<T, error>::value,
error,
T
>::type;
}; };
template <class T> template <class T>
struct implicit_conversions<T*> : implicit_actor_conversions<T> {}; struct implicit_conversions<T*, 0> {
static constexpr int oracle = implicit_conversion_oracle<T>::value;
static constexpr int is_actor_mask = dynamically_typed_actor_flag
| statically_typed_actor_flag;
static_assert((oracle & is_actor_mask) != 0,
"messages must not contain pointers");
using type = typename implicit_conversions<T, oracle>::type;
};
template <> template <>
struct implicit_conversions<char*> { struct implicit_conversions<char*, 0> {
using type = std::string; using type = std::string;
}; };
template <size_t N> template <size_t N>
struct implicit_conversions<char[N]> struct implicit_conversions<char[N], 0>
: implicit_conversions<char*> {}; : implicit_conversions<char*> {};
template <> template <>
struct implicit_conversions<const char*> struct implicit_conversions<const char*, 0>
: implicit_conversions<char*> {}; : implicit_conversions<char*> {};
template <size_t N> template <size_t N>
struct implicit_conversions<const char[N]> struct implicit_conversions<const char[N], 0>
: implicit_conversions<char*> {}; : implicit_conversions<char*> {};
template <> template <>
struct implicit_conversions<char16_t*> { struct implicit_conversions<char16_t*, 0> {
using type = std::u16string; using type = std::u16string;
}; };
template <size_t N> template <size_t N>
struct implicit_conversions<char16_t[N]> struct implicit_conversions<char16_t[N], 0>
: implicit_conversions<char16_t*> {}; : implicit_conversions<char16_t*> {};
template <> template <>
struct implicit_conversions<const char16_t*> struct implicit_conversions<const char16_t*, 0>
: implicit_conversions<char16_t*> {}; : implicit_conversions<char16_t*> {};
template <size_t N> template <size_t N>
struct implicit_conversions<const char16_t[N]> struct implicit_conversions<const char16_t[N], 0>
: implicit_conversions<char16_t*> {}; : implicit_conversions<char16_t*> {};
template <> template <>
struct implicit_conversions<char32_t*> { struct implicit_conversions<char32_t*, 0> {
using type = std::u16string; using type = std::u16string;
}; };
template <size_t N> template <size_t N>
struct implicit_conversions<char32_t[N]> struct implicit_conversions<char32_t[N], 0>
: implicit_conversions<char32_t*> {}; : implicit_conversions<char32_t*> {};
template <> template <>
struct implicit_conversions<const char32_t*> struct implicit_conversions<const char32_t*, 0>
: implicit_conversions<char32_t*> {}; : implicit_conversions<char32_t*> {};
template <size_t N> template <size_t N>
struct implicit_conversions<const char32_t[N]> struct implicit_conversions<const char32_t[N], 0>
: implicit_conversions<char32_t*> {}; : implicit_conversions<char32_t*> {};
template <> template <>
struct implicit_conversions<scoped_actor> { struct implicit_conversions<scoped_actor, 0> {
using type = actor; using type = actor;
}; };
...@@ -145,4 +183,3 @@ using strip_and_convert_t = typename strip_and_convert<T>::type; ...@@ -145,4 +183,3 @@ using strip_and_convert_t = typename strip_and_convert<T>::type;
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <cstddef>
#include <type_traits>
namespace caf {
namespace detail {
template <class T, size_t = sizeof(T)>
std::true_type is_complete_impl(T*);
std::false_type is_complete_impl(...);
/// Checks whether T is a complete type. For example, passing a forward
/// declaration or undefined template specialization evaluates to `false`.
template <class T>
struct is_complete
{
static constexpr bool value
= decltype(is_complete_impl(std::declval<T*>()))::value;
};
} // namespace detail
} // namespace caf
...@@ -220,8 +220,9 @@ public: ...@@ -220,8 +220,9 @@ public:
} }
template <class InputIterator> template <class InputIterator>
void insert(iterator pos, InputIterator first, InputIterator last) { iterator insert(iterator pos, InputIterator first, InputIterator last) {
CAF_ASSERT(first <= last); if (first == last)
return pos;
auto num_elements = static_cast<size_t>(std::distance(first, last)); auto num_elements = static_cast<size_t>(std::distance(first, last));
if ((size() + num_elements) > MaxSize) { if ((size() + num_elements) > MaxSize) {
CAF_RAISE_ERROR("limited_vector::insert: too much elements"); CAF_RAISE_ERROR("limited_vector::insert: too much elements");
...@@ -238,6 +239,13 @@ public: ...@@ -238,6 +239,13 @@ public:
// insert new elements // insert new elements
std::copy(first, last, pos); std::copy(first, last, pos);
} }
// Iterator to the first element inserted.
return pos + 1;
}
iterator insert(iterator pos, value_type value) {
T tmp[] = {value};
return insert(pos, std::begin(tmp), std::end(tmp));
} }
private: private:
......
...@@ -23,13 +23,11 @@ ...@@ -23,13 +23,11 @@
#include <utility> #include <utility>
#include "caf/atom.hpp" #include "caf/atom.hpp"
#include "caf/detail/comparable.hpp"
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/none.hpp"
#include "caf/meta/omittable_if_empty.hpp" #include "caf/meta/omittable_if_empty.hpp"
#include "caf/meta/type_name.hpp" #include "caf/meta/type_name.hpp"
#include "caf/none.hpp"
#include "caf/detail/comparable.hpp"
namespace caf { namespace caf {
......
...@@ -22,11 +22,13 @@ ...@@ -22,11 +22,13 @@
#include <sstream> #include <sstream>
#include <type_traits> #include <type_traits>
#include "caf/message.hpp"
#include "caf/allowed_unsafe_message_type.hpp" #include "caf/allowed_unsafe_message_type.hpp"
#include "caf/detail/build_config.hpp"
#include "caf/detail/is_complete.hpp"
#include "caf/detail/tuple_vals.hpp" #include "caf/detail/tuple_vals.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
#include "caf/message.hpp"
#include "caf/type_id.hpp"
namespace caf { namespace caf {
...@@ -52,13 +54,21 @@ struct unbox_message_element<actor_control_block*, 0> { ...@@ -52,13 +54,21 @@ struct unbox_message_element<actor_control_block*, 0> {
using type = strong_actor_ptr; using type = strong_actor_ptr;
}; };
/// /// @private
template <class T> template <class T>
struct is_serializable_or_whitelisted { struct is_serializable_or_whitelisted {
static constexpr bool value = detail::is_serializable<T>::value static constexpr bool value = detail::is_serializable<T>::value
|| allowed_unsafe_message_type<T>::value; || allowed_unsafe_message_type<T>::value;
}; };
/// @private
template <class T>
struct has_type_id {
static constexpr bool value = detail::is_complete<type_id<T>>::value
|| is_atom_constant<T>::value
|| allowed_unsafe_message_type<T>::value;
};
/// Returns a new `message` containing the values `(x, xs...)`. /// Returns a new `message` containing the values `(x, xs...)`.
/// @relates message /// @relates message
template <class T, class... Ts> template <class T, class... Ts>
...@@ -86,6 +96,12 @@ make_message(T&& x, Ts&&... xs) { ...@@ -86,6 +96,12 @@ make_message(T&& x, Ts&&... xs) {
"you can whitelist individual types by " "you can whitelist individual types by "
"specializing `caf::allowed_unsafe_message_type<T>` " "specializing `caf::allowed_unsafe_message_type<T>` "
"or using the macro CAF_ALLOW_UNSAFE_MESSAGE_TYPE"); "or using the macro CAF_ALLOW_UNSAFE_MESSAGE_TYPE");
#ifdef CAF_ENABLE_TYPE_ID_CHECKS
static_assert(tl_forall<stored_types, has_type_id>::value,
"at least one type has no type ID: please assign type IDs "
"to all of your types via CAF_ADD_TYPE_ID (this check was "
"enabled via CAF_ENABLE_TYPE_ID_CHECKS)");
#endif
using storage = typename tl_apply<stored_types, tuple_vals>::type; using storage = typename tl_apply<stored_types, tuple_vals>::type;
auto ptr = make_counted<storage>(std::forward<T>(x), std::forward<Ts>(xs)...); auto ptr = make_counted<storage>(std::forward<T>(x), std::forward<Ts>(xs)...);
return message{detail::message_data::cow_ptr{std::move(ptr)}}; return message{detail::message_data::cow_ptr{std::move(ptr)}};
...@@ -118,4 +134,3 @@ message make_message_from_tuple(std::tuple<Ts...> xs) { ...@@ -118,4 +134,3 @@ message make_message_from_tuple(std::tuple<Ts...> xs) {
} }
} // namespace caf } // namespace caf
...@@ -183,10 +183,12 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_module, 0) ...@@ -183,10 +183,12 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_module, 0)
CAF_ADD_TYPE_ID(core_module, (caf::actor)) CAF_ADD_TYPE_ID(core_module, (caf::actor))
CAF_ADD_TYPE_ID(core_module, (caf::actor_addr)) CAF_ADD_TYPE_ID(core_module, (caf::actor_addr))
CAF_ADD_TYPE_ID(core_module, (caf::atom_value))
CAF_ADD_TYPE_ID(core_module, (caf::config_value)) CAF_ADD_TYPE_ID(core_module, (caf::config_value))
CAF_ADD_TYPE_ID(core_module, (caf::dictionary<caf::config_value>) ) CAF_ADD_TYPE_ID(core_module, (caf::dictionary<caf::config_value>) )
CAF_ADD_TYPE_ID(core_module, (caf::down_msg)) CAF_ADD_TYPE_ID(core_module, (caf::down_msg))
CAF_ADD_TYPE_ID(core_module, (caf::downstream_msg)) CAF_ADD_TYPE_ID(core_module, (caf::downstream_msg))
CAF_ADD_TYPE_ID(core_module, (caf::duration))
CAF_ADD_TYPE_ID(core_module, (caf::error)) CAF_ADD_TYPE_ID(core_module, (caf::error))
CAF_ADD_TYPE_ID(core_module, (caf::exit_msg)) CAF_ADD_TYPE_ID(core_module, (caf::exit_msg))
CAF_ADD_TYPE_ID(core_module, (caf::exit_reason)) CAF_ADD_TYPE_ID(core_module, (caf::exit_reason))
......
...@@ -16,10 +16,9 @@ ...@@ -16,10 +16,9 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE actor_pool #define CAF_SUITE actor_pool
#include "caf/test/unit_test.hpp"
#include "core-test.hpp"
#include "caf/all.hpp" #include "caf/all.hpp"
...@@ -42,13 +41,10 @@ public: ...@@ -42,13 +41,10 @@ public:
behavior make_behavior() override { behavior make_behavior() override {
auto nested = exit_handler_; auto nested = exit_handler_;
set_exit_handler([=](scheduled_actor* self, exit_msg& em) { set_exit_handler(
nested(self, em); [=](scheduled_actor* self, exit_msg& em) { nested(self, em); });
});
return { return {
[](int x, int y) { [](int32_t x, int32_t y) { return x + y; },
return x + y;
}
}; };
} }
}; };
...@@ -56,17 +52,20 @@ public: ...@@ -56,17 +52,20 @@ public:
struct fixture { struct fixture {
// allows us to check s_dtors after dtor of actor_system // allows us to check s_dtors after dtor of actor_system
actor_system_config cfg; actor_system_config cfg;
union { actor_system system; }; union {
union { scoped_execution_unit context; }; actor_system system;
};
union {
scoped_execution_unit context;
};
std::function<actor ()> spawn_worker; std::function<actor()> spawn_worker;
fixture() { fixture() {
cfg.add_message_types<id_block::core_test>();
new (&system) actor_system(cfg); new (&system) actor_system(cfg);
new (&context) scoped_execution_unit(&system); new (&context) scoped_execution_unit(&system);
spawn_worker = [&] { spawn_worker = [&] { return system.spawn<worker>(); };
return system.spawn<worker>();
};
} }
~fixture() { ~fixture() {
...@@ -91,28 +90,28 @@ CAF_TEST(round_robin_actor_pool) { ...@@ -91,28 +90,28 @@ CAF_TEST(round_robin_actor_pool) {
actor_pool::round_robin()); actor_pool::round_robin());
self->send(pool, sys_atom::value, put_atom::value, spawn_worker()); self->send(pool, sys_atom::value, put_atom::value, spawn_worker());
std::vector<actor> workers; std::vector<actor> workers;
for (int i = 0; i < 6; ++i) { for (int32_t i = 0; i < 6; ++i) {
self->request(pool, infinite, i, i).receive( self->request(pool, infinite, i, i)
[&](int res) { .receive(
[&](int32_t res) {
CAF_CHECK_EQUAL(res, i + i); CAF_CHECK_EQUAL(res, i + i);
auto sender = actor_cast<strong_actor_ptr>(self->current_sender()); auto sender = actor_cast<strong_actor_ptr>(self->current_sender());
CAF_REQUIRE(sender); CAF_REQUIRE(sender);
workers.push_back(actor_cast<actor>(std::move(sender))); workers.push_back(actor_cast<actor>(std::move(sender)));
}, },
handle_err handle_err);
);
} }
CAF_CHECK_EQUAL(workers.size(), 6u); CAF_CHECK_EQUAL(workers.size(), 6u);
CAF_CHECK(std::unique(workers.begin(), workers.end()) == workers.end()); CAF_CHECK(std::unique(workers.begin(), workers.end()) == workers.end());
self->request(pool, infinite, sys_atom::value, get_atom::value).receive( self->request(pool, infinite, sys_atom::value, get_atom::value)
.receive(
[&](std::vector<actor>& ws) { [&](std::vector<actor>& ws) {
std::sort(workers.begin(), workers.end()); std::sort(workers.begin(), workers.end());
std::sort(ws.begin(), ws.end()); std::sort(ws.begin(), ws.end());
CAF_REQUIRE_EQUAL(workers.size(), ws.size()); CAF_REQUIRE_EQUAL(workers.size(), ws.size());
CAF_CHECK(std::equal(workers.begin(), workers.end(), ws.begin())); CAF_CHECK(std::equal(workers.begin(), workers.end(), ws.begin()));
}, },
handle_err handle_err);
);
CAF_MESSAGE("await last worker"); CAF_MESSAGE("await last worker");
anon_send_exit(workers.back(), exit_reason::user_shutdown); anon_send_exit(workers.back(), exit_reason::user_shutdown);
self->wait_for(workers.back()); self->wait_for(workers.back());
...@@ -122,7 +121,8 @@ CAF_TEST(round_robin_actor_pool) { ...@@ -122,7 +121,8 @@ CAF_TEST(round_robin_actor_pool) {
bool success = false; bool success = false;
size_t i = 0; size_t i = 0;
while (!success && ++i <= 10) { while (!success && ++i <= 10) {
self->request(pool, infinite, sys_atom::value, get_atom::value).receive( self->request(pool, infinite, sys_atom::value, get_atom::value)
.receive(
[&](std::vector<actor>& ws) { [&](std::vector<actor>& ws) {
success = workers.size() == ws.size(); success = workers.size() == ws.size();
if (success) { if (success) {
...@@ -133,8 +133,7 @@ CAF_TEST(round_robin_actor_pool) { ...@@ -133,8 +133,7 @@ CAF_TEST(round_robin_actor_pool) {
std::this_thread::sleep_for(std::chrono::milliseconds(5)); std::this_thread::sleep_for(std::chrono::milliseconds(5));
} }
}, },
handle_err handle_err);
);
} }
CAF_REQUIRE_EQUAL(success, true); CAF_REQUIRE_EQUAL(success, true);
CAF_MESSAGE("about to send exit to workers"); CAF_MESSAGE("about to send exit to workers");
...@@ -152,32 +151,23 @@ CAF_TEST(broadcast_actor_pool) { ...@@ -152,32 +151,23 @@ CAF_TEST(broadcast_actor_pool) {
auto pool = actor_pool::make(&context, 5, spawn5, actor_pool::broadcast()); auto pool = actor_pool::make(&context, 5, spawn5, actor_pool::broadcast());
CAF_CHECK_EQUAL(system.registry().running(), 32u); CAF_CHECK_EQUAL(system.registry().running(), 32u);
self->send(pool, 1, 2); self->send(pool, 1, 2);
std::vector<int> results; std::vector<int32_t> results;
int i = 0; int32_t i = 0;
self->receive_for(i, 25)( self->receive_for(i, 25)([&](int32_t res) { results.push_back(res); },
[&](int res) { after(std::chrono::milliseconds(250)) >>
results.push_back(res); [] { CAF_ERROR("didn't receive a result"); });
},
after(std::chrono::milliseconds(250)) >> [] {
CAF_ERROR("didn't receive a result");
}
);
CAF_CHECK_EQUAL(results.size(), 25u); CAF_CHECK_EQUAL(results.size(), 25u);
CAF_CHECK(std::all_of(results.begin(), results.end(), CAF_CHECK(std::all_of(results.begin(), results.end(),
[](int res) { return res == 3; })); [](int32_t res) { return res == 3; }));
self->send_exit(pool, exit_reason::user_shutdown); self->send_exit(pool, exit_reason::user_shutdown);
} }
CAF_TEST(random_actor_pool) { CAF_TEST(random_actor_pool) {
scoped_actor self{system}; scoped_actor self{system};
auto pool = actor_pool::make(&context, 5, spawn_worker, actor_pool::random()); auto pool = actor_pool::make(&context, 5, spawn_worker, actor_pool::random());
for (int i = 0; i < 5; ++i) { for (int32_t i = 0; i < 5; ++i) {
self->request(pool, std::chrono::milliseconds(250), 1, 2).receive( self->request(pool, std::chrono::milliseconds(250), 1, 2)
[&](int res) { .receive([&](int32_t res) { CAF_CHECK_EQUAL(res, 3); }, handle_err);
CAF_CHECK_EQUAL(res, 3);
},
handle_err
);
} }
self->send_exit(pool, exit_reason::user_shutdown); self->send_exit(pool, exit_reason::user_shutdown);
} }
...@@ -186,10 +176,7 @@ CAF_TEST(split_join_actor_pool) { ...@@ -186,10 +176,7 @@ CAF_TEST(split_join_actor_pool) {
auto spawn_split_worker = [&] { auto spawn_split_worker = [&] {
return system.spawn<lazy_init>([]() -> behavior { return system.spawn<lazy_init>([]() -> behavior {
return { return {
[](size_t pos, const std::vector<int>& xs) { [](size_t pos, const std::vector<int32_t>& xs) { return xs[pos]; }};
return xs[pos];
}
};
}); });
}; };
auto split_fun = [](std::vector<std::pair<actor, message>>& xs, message& y) { auto split_fun = [](std::vector<std::pair<actor, message>>& xs, message& y) {
...@@ -197,27 +184,18 @@ CAF_TEST(split_join_actor_pool) { ...@@ -197,27 +184,18 @@ CAF_TEST(split_join_actor_pool) {
xs[i].second = make_message(i) + y; xs[i].second = make_message(i) + y;
} }
}; };
auto join_fun = [](int& res, message& msg) { auto join_fun = [](int32_t& res, message& msg) {
msg.apply([&](int x) { msg.apply([&](int32_t x) { res += x; });
res += x;
});
}; };
scoped_actor self{system}; scoped_actor self{system};
CAF_MESSAGE("create actor pool"); CAF_MESSAGE("create actor pool");
auto pool = actor_pool::make(&context, 5, spawn_split_worker, auto pool
actor_pool::split_join<int>(join_fun, split_fun)); = actor_pool::make(&context, 5, spawn_split_worker,
self->request(pool, infinite, std::vector<int>{1, 2, 3, 4, 5}).receive( actor_pool::split_join<int32_t>(join_fun, split_fun));
[&](int res) { self->request(pool, infinite, std::vector<int32_t>{1, 2, 3, 4, 5})
CAF_CHECK_EQUAL(res, 15); .receive([&](int32_t res) { CAF_CHECK_EQUAL(res, 15); }, handle_err);
}, self->request(pool, infinite, std::vector<int32_t>{6, 7, 8, 9, 10})
handle_err .receive([&](int32_t res) { CAF_CHECK_EQUAL(res, 40); }, handle_err);
);
self->request(pool, infinite, std::vector<int>{6, 7, 8, 9, 10}).receive(
[&](int res) {
CAF_CHECK_EQUAL(res, 40);
},
handle_err
);
self->send_exit(pool, exit_reason::user_shutdown); self->send_exit(pool, exit_reason::user_shutdown);
} }
......
...@@ -19,23 +19,22 @@ ...@@ -19,23 +19,22 @@
#define CAF_SUITE broadcast_downstream_manager #define CAF_SUITE broadcast_downstream_manager
#include "core-test.hpp"
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include "caf/actor_system.hpp" #include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp" #include "caf/actor_system_config.hpp"
#include "caf/broadcast_downstream_manager.hpp" #include "caf/broadcast_downstream_manager.hpp"
#include "caf/scheduled_actor.hpp"
#include "caf/mixin/sender.hpp" #include "caf/mixin/sender.hpp"
#include "caf/scheduled_actor.hpp"
#include "caf/test/unit_test.hpp"
using namespace caf; using namespace caf;
namespace { namespace {
using bcast_manager = broadcast_downstream_manager<int>; using bcast_manager = broadcast_downstream_manager<int32_t>;
// Mocks just enough of a stream manager to serve our entity. // Mocks just enough of a stream manager to serve our entity.
class mock_stream_manager : public stream_manager { class mock_stream_manager : public stream_manager {
...@@ -130,7 +129,7 @@ public: ...@@ -130,7 +129,7 @@ public:
return static_cast<size_t>((*i)->open_credit); return static_cast<size_t>((*i)->open_credit);
} }
void new_round(int num, bool force_emit) { void new_round(int32_t num, bool force_emit) {
for (auto& ptr : paths) for (auto& ptr : paths)
ptr->open_credit += num; ptr->open_credit += num;
if (force_emit) if (force_emit)
...@@ -165,9 +164,15 @@ struct not_empty_t {}; ...@@ -165,9 +164,15 @@ struct not_empty_t {};
constexpr auto some = not_empty_t{}; constexpr auto some = not_empty_t{};
struct config : actor_system_config {
config() {
add_message_types<id_block::core_test>();
}
};
// Provides the setup with alice, bob, and carl. // Provides the setup with alice, bob, and carl.
struct fixture { struct fixture {
actor_system_config cfg; config cfg;
actor_system sys; actor_system sys;
...@@ -205,7 +210,7 @@ struct fixture { ...@@ -205,7 +210,7 @@ struct fixture {
// nop // nop
} }
using batch_type = std::vector<int>; using batch_type = std::vector<int32_t>;
using batches_type = std::vector<batch_type>; using batches_type = std::vector<batch_type>;
...@@ -224,7 +229,7 @@ struct fixture { ...@@ -224,7 +229,7 @@ struct fixture {
return result; return result;
} }
batch_type make_batch(int first, int last) { batch_type make_batch(int32_t first, int32_t last) {
batch_type result; batch_type result;
result.resize(static_cast<size_t>((last + 1) - first)); result.resize(static_cast<size_t>((last + 1) - first));
std::iota(result.begin(), result.end(), first); std::iota(result.begin(), result.end(), first);
...@@ -351,7 +356,7 @@ CAF_TEST(one_path_force) { ...@@ -351,7 +356,7 @@ CAF_TEST(one_path_force) {
// Give alice 100 elements to send and a path to bob with desired batch size // Give alice 100 elements to send and a path to bob with desired batch size
// of 10. // of 10.
alice.add_path_to(bob, 10); alice.add_path_to(bob, 10);
for (int i = 1; i <= 100; ++i) for (int32_t i = 1; i <= 100; ++i)
alice.mgr.out().push(i); alice.mgr.out().push(i);
// Give 3 credit (less than 10). // Give 3 credit (less than 10).
AFTER ENTITY alice TRIED FORCE_SENDING 3 ELEMENTS { AFTER ENTITY alice TRIED FORCE_SENDING 3 ELEMENTS {
...@@ -390,7 +395,7 @@ CAF_TEST(one_path_without_force) { ...@@ -390,7 +395,7 @@ CAF_TEST(one_path_without_force) {
// Give alice 100 elements to send and a path to bob with desired batch size // Give alice 100 elements to send and a path to bob with desired batch size
// of 10. // of 10.
alice.add_path_to(bob, 10); alice.add_path_to(bob, 10);
for (int i = 1; i <= 100; ++i) for (int32_t i = 1; i <= 100; ++i)
alice.mgr.out().push(i); alice.mgr.out().push(i);
// Give 3 credit (less than 10). // Give 3 credit (less than 10).
AFTER ENTITY alice TRIED SENDING 3 ELEMENTS { AFTER ENTITY alice TRIED SENDING 3 ELEMENTS {
...@@ -430,7 +435,7 @@ CAF_TEST(two_paths_different_sizes_force) { ...@@ -430,7 +435,7 @@ CAF_TEST(two_paths_different_sizes_force) {
// 10, and a path to carl with desired batch size of 7. // 10, and a path to carl with desired batch size of 7.
alice.add_path_to(bob, 10); alice.add_path_to(bob, 10);
alice.add_path_to(carl, 7); alice.add_path_to(carl, 7);
for (int i = 1; i <= 100; ++i) for (int32_t i = 1; i <= 100; ++i)
alice.mgr.out().push(i); alice.mgr.out().push(i);
// Give 3 credit (less than 10). // Give 3 credit (less than 10).
AFTER ENTITY alice TRIED FORCE_SENDING 3 ELEMENTS { AFTER ENTITY alice TRIED FORCE_SENDING 3 ELEMENTS {
...@@ -481,7 +486,7 @@ CAF_TEST(two_paths_different_sizes_without_force) { ...@@ -481,7 +486,7 @@ CAF_TEST(two_paths_different_sizes_without_force) {
// 10, and a path to carl with desired batch size of 7. // 10, and a path to carl with desired batch size of 7.
alice.add_path_to(bob, 10); alice.add_path_to(bob, 10);
alice.add_path_to(carl, 7); alice.add_path_to(carl, 7);
for (int i = 1; i <= 100; ++i) for (int32_t i = 1; i <= 100; ++i)
alice.mgr.out().push(i); alice.mgr.out().push(i);
// Give 3 credit (less than 10). // Give 3 credit (less than 10).
AFTER ENTITY alice TRIED SENDING 3 ELEMENTS { AFTER ENTITY alice TRIED SENDING 3 ELEMENTS {
......
This diff is collapsed.
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#define CAF_SUITE continuous_streaming #define CAF_SUITE continuous_streaming
#include "caf/test/dsl.hpp" #include "core-test.hpp"
#include <memory> #include <memory>
#include <numeric> #include <numeric>
...@@ -37,18 +37,19 @@ using namespace caf; ...@@ -37,18 +37,19 @@ using namespace caf;
namespace { namespace {
/// Returns the sum of natural numbers up until `n`, i.e., 1 + 2 + ... + n. /// Returns the sum of natural numbers up until `n`, i.e., 1 + 2 + ... + n.
int sum(int n) { int32_t sum(int32_t n) {
return (n * (n + 1)) / 2; return (n * (n + 1)) / 2;
} }
TESTEE_SETUP(); TESTEE_SETUP();
TESTEE_STATE(file_reader) { TESTEE_STATE(file_reader) {
std::vector<int> buf; std::vector<int32_t> buf;
}; };
VARARGS_TESTEE(file_reader, size_t buf_size) { VARARGS_TESTEE(file_reader, size_t buf_size) {
return {[=](string& fname) -> result<stream<int>, string> { return {
[=](string& fname) -> result<stream<int32_t>, string> {
CAF_CHECK_EQUAL(fname, "numbers.txt"); CAF_CHECK_EQUAL(fname, "numbers.txt");
CAF_CHECK_EQUAL(self->mailbox().empty(), true); CAF_CHECK_EQUAL(self->mailbox().empty(), true);
return attach_stream_source( return attach_stream_source(
...@@ -62,7 +63,7 @@ VARARGS_TESTEE(file_reader, size_t buf_size) { ...@@ -62,7 +63,7 @@ VARARGS_TESTEE(file_reader, size_t buf_size) {
std::iota(xs.begin(), xs.end(), 1); std::iota(xs.begin(), xs.end(), 1);
}, },
// get next element // get next element
[=](unit_t&, downstream<int>& out, size_t num) { [=](unit_t&, downstream<int32_t>& out, size_t num) {
auto& xs = self->state.buf; auto& xs = self->state.buf;
CAF_MESSAGE("push " << num << " messages downstream"); CAF_MESSAGE("push " << num << " messages downstream");
auto n = std::min(num, xs.size()); auto n = std::min(num, xs.size());
...@@ -78,17 +79,19 @@ VARARGS_TESTEE(file_reader, size_t buf_size) { ...@@ -78,17 +79,19 @@ VARARGS_TESTEE(file_reader, size_t buf_size) {
} }
return false; return false;
}); });
}}; },
};
} }
TESTEE_STATE(sum_up) { TESTEE_STATE(sum_up) {
int x = 0; int32_t x = 0;
}; };
TESTEE(sum_up) { TESTEE(sum_up) {
return {[=](stream<int>& in, const string& fname) { return {
[=](stream<int32_t>& in, const string& fname) {
CAF_CHECK_EQUAL(fname, "numbers.txt"); CAF_CHECK_EQUAL(fname, "numbers.txt");
using int_ptr = int*; using int_ptr = int32_t*;
return attach_stream_sink( return attach_stream_sink(
self, self,
// input stream // input stream
...@@ -96,7 +99,7 @@ TESTEE(sum_up) { ...@@ -96,7 +99,7 @@ TESTEE(sum_up) {
// initialize state // initialize state
[=](int_ptr& x) { x = &self->state.x; }, [=](int_ptr& x) { x = &self->state.x; },
// processing step // processing step
[](int_ptr& x, int y) { *x += y; }, [](int_ptr& x, int32_t y) { *x += y; },
// cleanup // cleanup
[=](int_ptr&, const error&) { [=](int_ptr&, const error&) {
CAF_MESSAGE(self->name() << " is done"); CAF_MESSAGE(self->name() << " is done");
...@@ -105,11 +108,12 @@ TESTEE(sum_up) { ...@@ -105,11 +108,12 @@ TESTEE(sum_up) {
[=](join_atom atm, actor src) { [=](join_atom atm, actor src) {
CAF_MESSAGE(self->name() << " joins a stream"); CAF_MESSAGE(self->name() << " joins a stream");
self->send(self * src, atm); self->send(self * src, atm);
}}; },
};
} }
TESTEE_STATE(stream_multiplexer) { TESTEE_STATE(stream_multiplexer) {
stream_stage_ptr<int, broadcast_downstream_manager<int>> stage; stream_stage_ptr<int32_t, broadcast_downstream_manager<int32_t>> stage;
}; };
TESTEE(stream_multiplexer) { TESTEE(stream_multiplexer) {
...@@ -120,7 +124,7 @@ TESTEE(stream_multiplexer) { ...@@ -120,7 +124,7 @@ TESTEE(stream_multiplexer) {
// nop // nop
}, },
// processing step // processing step
[](unit_t&, downstream<int>& out, int x) { out.push(x); }, [](unit_t&, downstream<int32_t>& out, int32_t x) { out.push(x); },
// cleanup // cleanup
[=](unit_t&, const error&) { CAF_MESSAGE(self->name() << " is done"); }); [=](unit_t&, const error&) { CAF_MESSAGE(self->name() << " is done"); });
return { return {
...@@ -129,18 +133,24 @@ TESTEE(stream_multiplexer) { ...@@ -129,18 +133,24 @@ TESTEE(stream_multiplexer) {
return self->state.stage->add_outbound_path( return self->state.stage->add_outbound_path(
std::make_tuple("numbers.txt")); std::make_tuple("numbers.txt"));
}, },
[=](const stream<int>& in, std::string& fname) { [=](const stream<int32_t>& in, std::string& fname) {
CAF_CHECK_EQUAL(fname, "numbers.txt"); CAF_CHECK_EQUAL(fname, "numbers.txt");
return self->state.stage->add_inbound_path(in); return self->state.stage->add_inbound_path(in);
}, },
[=](close_atom, int sink_index) { [=](close_atom, int32_t sink_index) {
auto& out = self->state.stage->out(); auto& out = self->state.stage->out();
out.close(out.path_slots().at(static_cast<size_t>(sink_index))); out.close(out.path_slots().at(static_cast<size_t>(sink_index)));
}, },
}; };
} }
using fixture = test_coordinator_fixture<>; struct config : actor_system_config {
config() {
add_message_types<id_block::core_test>();
}
};
using fixture = test_coordinator_fixture<config>;
} // namespace } // namespace
...@@ -224,7 +234,7 @@ CAF_TEST(closing_downstreams_before_end_of_stream) { ...@@ -224,7 +234,7 @@ CAF_TEST(closing_downstreams_before_end_of_stream) {
auto sink1_result = sum(next_pending - 1); auto sink1_result = sum(next_pending - 1);
CAF_MESSAGE("gracefully close sink 1, next pending: " << next_pending); CAF_MESSAGE("gracefully close sink 1, next pending: " << next_pending);
self->send(stg, close_atom::value, 0); self->send(stg, close_atom::value, 0);
expect((atom_value, int), from(self).to(stg)); expect((atom_value, int32_t), from(self).to(stg));
CAF_MESSAGE("ship remaining elements"); CAF_MESSAGE("ship remaining elements");
run(); run();
CAF_CHECK_EQUAL(st.stage->out().num_paths(), 1u); CAF_CHECK_EQUAL(st.stage->out().num_paths(), 1u);
......
#include "core-test.hpp"
#include "caf/test/unit_test_impl.hpp"
fail_on_copy::fail_on_copy(const fail_on_copy&) {
CAF_FAIL("fail_on_copy: copy constructor called");
}
fail_on_copy& fail_on_copy::operator=(const fail_on_copy&) {
CAF_FAIL("fail_on_copy: copy assign operator called");
}
size_t i32_wrapper::instances = 0;
size_t i64_wrapper::instances = 0;
void test_empty_non_pod::foo() {
// nop
}
test_empty_non_pod::~test_empty_non_pod() {
// nop
}
namespace {
const char* test_enum_strings[] = {
"a",
"b",
"c",
};
} // namespace
std::string to_string(test_enum x) {
return test_enum_strings[static_cast<uint32_t>(x)];
}
#include "caf/fwd.hpp"
#include "caf/test/dsl.hpp"
#include "caf/type_id.hpp"
#include "caf/typed_actor.hpp"
#include <cstdint>
#include <numeric>
#include <string>
#include <utility>
// -- forward declarations for all unit test suites ----------------------------
using float_actor = caf::typed_actor<caf::reacts_to<float>>;
using int_actor = caf::typed_actor<caf::replies_to<int32_t>::with<int32_t>>;
using foo_actor
= caf::typed_actor<caf::replies_to<int32_t, int32_t, int32_t>::with<int32_t>,
caf::replies_to<double>::with<double, double>>;
// A simple POD type.
struct dummy_struct {
int a;
std::string b;
friend bool operator==(const dummy_struct& x, const dummy_struct& y) {
return x.a == y.a && x.b == y.b;
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, dummy_struct& x) {
return f(caf::meta::type_name("dummy_struct"), x.a, x.b);
}
// An empty type.
struct dummy_tag_type {};
constexpr bool operator==(dummy_tag_type, dummy_tag_type) {
return true;
}
struct fail_on_copy {
int value;
fail_on_copy() : value(0) {
// nop
}
explicit fail_on_copy(int x) : value(x) {
// nop
}
fail_on_copy(fail_on_copy&&) = default;
fail_on_copy& operator=(fail_on_copy&&) = default;
fail_on_copy(const fail_on_copy&);
fail_on_copy& operator=(const fail_on_copy&);
template <class Inspector>
friend typename Inspector::result_type
inspect(Inspector& f, fail_on_copy& x) {
return f(x.value);
}
};
struct i32_wrapper {
static size_t instances;
int32_t value;
i32_wrapper() : value(0) {
++instances;
}
~i32_wrapper() {
--instances;
}
template <class Inspector>
friend typename Inspector::result_type inspect(Inspector& f, i32_wrapper& x) {
return f(x.value);
}
};
struct i64_wrapper {
static size_t instances;
int64_t value;
i64_wrapper() : value(0) {
++instances;
}
~i64_wrapper() {
--instances;
}
template <class Inspector>
friend typename Inspector::result_type inspect(Inspector& f, i64_wrapper& x) {
return f(x.value);
}
};
struct my_request {
int32_t a;
int32_t b;
friend bool operator==(const my_request& x, const my_request& y) {
return std::tie(x.a, x.b) == std::tie(y.a, y.b);
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, my_request& x) {
return f(x.a, x.b);
}
struct raw_struct {
std::string str;
friend bool operator==(const raw_struct& lhs, const raw_struct& rhs) {
return lhs.str == rhs.str;
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, raw_struct& x) {
return f(x.str);
}
struct s1 {
int value[3] = {10, 20, 30};
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, s1& x) {
return f(x.value);
}
struct s2 {
int value[4][2] = {{1, 10}, {2, 20}, {3, 30}, {4, 40}};
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, s2& x) {
return f(x.value);
}
struct s3 {
std::array<int, 4> value;
s3() {
std::iota(value.begin(), value.end(), 1);
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, s3& x) {
return f(x.value);
}
struct test_array {
int32_t value[4];
int32_t value2[2][4];
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, test_array& x) {
return f(x.value, x.value2);
}
struct test_empty_non_pod {
test_empty_non_pod() = default;
test_empty_non_pod(const test_empty_non_pod&) = default;
test_empty_non_pod& operator=(const test_empty_non_pod&) = default;
virtual void foo();
virtual ~test_empty_non_pod();
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, test_empty_non_pod&) {
return f();
}
enum class test_enum : int32_t {
a,
b,
c,
};
std::string to_string(test_enum x);
struct test_data {
int32_t i32;
int64_t i64;
float f32;
double f64;
caf::timestamp ts;
test_enum te;
std::string str;
friend bool operator==(const test_data& x, const test_data& y) {
return std::tie(x.i32, x.i64, x.f32, x.f64, x.ts, x.te, x.str)
== std::tie(y.i32, y.i64, y.f32, y.f64, y.ts, y.te, y.str);
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, test_data& x) {
return f(caf::meta::type_name("test_data"), x.i32, x.i64, x.f32, x.f64, x.ts,
x.te, x.str);
}
enum class dummy_enum_class : short { foo, bar };
inline std::string to_string(dummy_enum_class x) {
return x == dummy_enum_class::foo ? "foo" : "bar";
}
enum class level { all, trace, debug, warning, error };
enum dummy_enum { de_foo, de_bar };
// -- type IDs for for all unit test suites ------------------------------------
#define ADD_TYPE_ID(type) CAF_ADD_TYPE_ID(core_test, type)
#define ADD_ATOM(atom_name, atom_text) \
CAF_ADD_ATOM(core_test, core_test_atoms, atom_name, atom_text)
CAF_BEGIN_TYPE_ID_BLOCK(core_test, caf::first_custom_type_id)
ADD_TYPE_ID((caf::stream<int32_t>) )
ADD_TYPE_ID((caf::stream<std::string>) )
ADD_TYPE_ID((caf::stream<std::pair<level, std::string>>) )
ADD_TYPE_ID((dummy_enum))
ADD_TYPE_ID((dummy_enum_class))
ADD_TYPE_ID((dummy_struct))
ADD_TYPE_ID((dummy_tag_type))
ADD_TYPE_ID((fail_on_copy))
ADD_TYPE_ID((float_actor))
ADD_TYPE_ID((foo_actor))
ADD_TYPE_ID((i32_wrapper))
ADD_TYPE_ID((i64_wrapper))
ADD_TYPE_ID((int_actor))
ADD_TYPE_ID((level))
ADD_TYPE_ID((my_request))
ADD_TYPE_ID((raw_struct))
ADD_TYPE_ID((s1))
ADD_TYPE_ID((s2))
ADD_TYPE_ID((s3))
ADD_TYPE_ID((std::map<int32_t, int32_t>) )
ADD_TYPE_ID((std::map<std::string, std::u16string>) )
ADD_TYPE_ID((std::pair<level, std::string>) )
ADD_TYPE_ID((std::tuple<int32_t, int32_t, int32_t>) )
ADD_TYPE_ID((std::tuple<std::string, int32_t, uint32_t>) )
ADD_TYPE_ID((std::vector<bool>) )
ADD_TYPE_ID((std::vector<int32_t>) )
ADD_TYPE_ID((std::vector<std::pair<level, std::string>>) )
ADD_TYPE_ID((std::vector<std::string>) )
ADD_TYPE_ID((test_array))
ADD_TYPE_ID((test_empty_non_pod))
ADD_TYPE_ID((test_enum))
ADD_ATOM(abc_atom, "abc")
ADD_ATOM(get_state_atom, "get_state")
ADD_ATOM(name_atom, "name")
CAF_END_TYPE_ID_BLOCK(core_test)
using namespace core_test_atoms;
#undef ADD_TYPE_ID
#undef ADD_ATOM
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "caf/all.hpp" #include "caf/all.hpp"
#define ERROR_HANDLER [&](error& err) { CAF_FAIL(system.render(err)); } #define ERROR_HANDLER [&](error& err) { CAF_FAIL(err); }
using namespace caf; using namespace caf;
...@@ -42,7 +42,9 @@ using second_stage = typed_actor<replies_to<double, double>::with<double>>; ...@@ -42,7 +42,9 @@ using second_stage = typed_actor<replies_to<double, double>::with<double>>;
first_stage::behavior_type typed_first_stage() { first_stage::behavior_type typed_first_stage() {
return { return {
[](int i) { return std::make_tuple(i * 2.0, i * 4.0); }, [](int i) -> result<double, double> {
return {i * 2.0, i * 4.0};
},
}; };
} }
......
...@@ -88,11 +88,11 @@ CAF_TEST(shutdown_delayed_send_loop) { ...@@ -88,11 +88,11 @@ CAF_TEST(shutdown_delayed_send_loop) {
CAF_MESSAGE("does sys shut down after spawning a detached actor that used " CAF_MESSAGE("does sys shut down after spawning a detached actor that used "
"a delayed send loop and was interrupted via exit message?"); "a delayed send loop and was interrupted via exit message?");
auto f = [](event_based_actor* self) -> behavior { auto f = [](event_based_actor* self) -> behavior {
self->send(self, std::chrono::milliseconds(1), ok_atom::value); self->delayed_send(self, std::chrono::milliseconds(1), ok_atom::value);
return { return {
[=](ok_atom) { [=](ok_atom) {
self->send(self, std::chrono::milliseconds(1), ok_atom::value); self->delayed_send(self, std::chrono::milliseconds(1), ok_atom::value);
} },
}; };
}; };
auto a = sys.spawn<detached>(f); auto a = sys.spawn<detached>(f);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "caf/fused_downstream_manager.hpp" #include "caf/fused_downstream_manager.hpp"
#include "caf/test/dsl.hpp" #include "core-test.hpp"
#include <memory> #include <memory>
#include <numeric> #include <numeric>
...@@ -250,11 +250,11 @@ TESTEE(stream_multiplexer) { ...@@ -250,11 +250,11 @@ TESTEE(stream_multiplexer) {
struct config : actor_system_config { struct config : actor_system_config {
config() { config() {
add_message_type<std::deque<std::string>>("deque<string>"); add_message_types<id_block::core_test>();
} }
}; };
using fixture = test_coordinator_fixture<>; using fixture = test_coordinator_fixture<config>;
} // namespace } // namespace
......
...@@ -16,26 +16,24 @@ ...@@ -16,26 +16,24 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#define CAF_SUITE message_operations
#include "core-test.hpp"
#include <iostream>
#include <map> #include <map>
#include <vector>
#include <string>
#include <numeric> #include <numeric>
#include <iostream>
#include <set> #include <set>
#include <string>
#include <unordered_set> #include <unordered_set>
#include <vector>
#include "caf/config.hpp"
#define CAF_SUITE message_operations
#include "caf/test/unit_test.hpp"
#include "caf/all.hpp" #include "caf/all.hpp"
using std::map; using std::map;
using std::string; using std::string;
using std::tuple;
using std::vector; using std::vector;
using std::make_tuple;
using namespace caf; using namespace caf;
...@@ -185,45 +183,11 @@ CAF_TEST(concat) { ...@@ -185,45 +183,11 @@ CAF_TEST(concat) {
CAF_CHECK_EQUAL(to_string(message::concat(m3, message{}, m1, m2)), to_string(m4)); CAF_CHECK_EQUAL(to_string(message::concat(m3, message{}, m1, m2)), to_string(m4));
} }
namespace {
struct s1 {
int value[3] = {10, 20, 30};
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, s1& x) {
return f(x.value);
}
struct s2 {
int value[4][2] = {{1, 10}, {2, 20}, {3, 30}, {4, 40}};
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, s2& x) {
return f(x.value);
}
struct s3 {
std::array<int, 4> value;
s3() {
std::iota(value.begin(), value.end(), 1);
}
};
template <class Inspector>
typename Inspector::result_type inspect(Inspector& f, s3& x) {
return f(x.value);
}
template <class... Ts> template <class... Ts>
std::string msg_as_string(Ts&&... xs) { std::string msg_as_string(Ts&&... xs) {
return to_string(make_message(std::forward<Ts>(xs)...)); return to_string(make_message(std::forward<Ts>(xs)...));
} }
} // namespace
CAF_TEST(compare_custom_types) { CAF_TEST(compare_custom_types) {
s2 tmp; s2 tmp;
tmp.value[0][1] = 100; tmp.value[0][1] = 100;
...@@ -237,7 +201,7 @@ CAF_TEST(empty_to_string) { ...@@ -237,7 +201,7 @@ CAF_TEST(empty_to_string) {
} }
CAF_TEST(integers_to_string) { CAF_TEST(integers_to_string) {
using ivec = vector<int>; using ivec = vector<int32_t>;
CAF_CHECK_EQUAL(msg_as_string(1, 2, 3), "(1, 2, 3)"); CAF_CHECK_EQUAL(msg_as_string(1, 2, 3), "(1, 2, 3)");
CAF_CHECK_EQUAL(msg_as_string(ivec{1, 2, 3}), "([1, 2, 3])"); CAF_CHECK_EQUAL(msg_as_string(ivec{1, 2, 3}), "([1, 2, 3])");
CAF_CHECK_EQUAL(msg_as_string(ivec{1, 2}, 3, 4, ivec{5, 6, 7}), CAF_CHECK_EQUAL(msg_as_string(ivec{1, 2}, 3, 4, ivec{5, 6, 7}),
...@@ -259,15 +223,16 @@ CAF_TEST(strings_to_string) { ...@@ -259,15 +223,16 @@ CAF_TEST(strings_to_string) {
} }
CAF_TEST(maps_to_string) { CAF_TEST(maps_to_string) {
map<int, int> m1{{1, 10}, {2, 20}, {3, 30}}; map<int32_t, int32_t> m1{{1, 10}, {2, 20}, {3, 30}};
auto msg1 = make_message(move(m1)); auto msg1 = make_message(move(m1));
CAF_CHECK_EQUAL(to_string(msg1), "({1 = 10, 2 = 20, 3 = 30})"); CAF_CHECK_EQUAL(to_string(msg1), "({1 = 10, 2 = 20, 3 = 30})");
} }
CAF_TEST(tuples_to_string) { CAF_TEST(tuples_to_string) {
auto msg1 = make_message(make_tuple(1, 2, 3), 4, 5); auto msg1 = make_message(tuple<int32_t, int32_t, int32_t>{1, 2, 3}, 4, 5);
CAF_CHECK_EQUAL(to_string(msg1), "((1, 2, 3), 4, 5)"); CAF_CHECK_EQUAL(to_string(msg1), "((1, 2, 3), 4, 5)");
auto msg2 = make_message(make_tuple(string{"one"}, 2, uint32_t{3}), 4, true); using msg2_type = tuple<string, int32_t, uint32_t>;
auto msg2 = make_message(msg2_type{"one", 2, 3}, 4, true);
CAF_CHECK_EQUAL(to_string(msg2), "((\"one\", 2, 3), 4, true)"); CAF_CHECK_EQUAL(to_string(msg2), "((\"one\", 2, 3), 4, true)");
} }
......
...@@ -16,10 +16,9 @@ ...@@ -16,10 +16,9 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE message_lifetime #define CAF_SUITE message_lifetime
#include "caf/test/unit_test.hpp"
#include "core-test.hpp"
#include <atomic> #include <atomic>
#include <iostream> #include <iostream>
...@@ -81,35 +80,16 @@ private: ...@@ -81,35 +80,16 @@ private:
message msg_; message msg_;
}; };
struct fixture { struct config : actor_system_config {
actor_system_config cfg; config() {
actor_system system{cfg}; add_message_types<id_block::core_test>();
};
struct fail_on_copy {
int value;
fail_on_copy(int x = 0) : value(x) {
// nop
}
fail_on_copy(fail_on_copy&&) = default;
fail_on_copy& operator=(fail_on_copy&&) = default;
fail_on_copy(const fail_on_copy&) {
CAF_FAIL("fail_on_copy: copy constructor called");
}
fail_on_copy& operator=(const fail_on_copy&) {
CAF_FAIL("fail_on_copy: copy assign operator called");
} }
}; };
template <class Inspector> struct fixture {
typename Inspector::result_type inspect(Inspector& f, fail_on_copy& x) { config cfg;
return f(x.value); actor_system system{cfg};
} };
} // namespace } // namespace
......
...@@ -81,6 +81,13 @@ ...@@ -81,6 +81,13 @@
#include "caf/detail/stream_stage_impl.hpp" #include "caf/detail/stream_stage_impl.hpp"
#include "caf/detail/tick_emitter.hpp" #include "caf/detail/tick_emitter.hpp"
CAF_BEGIN_TYPE_ID_BLOCK(native_streaming_classes, first_custom_type_id)
CAF_ADD_TYPE_ID(native_streaming_classes, (caf::stream<int32_t>) )
CAF_ADD_TYPE_ID(native_streaming_classes, (std::vector<int32_t>) )
CAF_END_TYPE_ID_BLOCK(native_streaming_classes)
using std::vector; using std::vector;
using namespace caf; using namespace caf;
...@@ -228,9 +235,9 @@ public: ...@@ -228,9 +235,9 @@ public:
return nullptr; return nullptr;
} }
void start_streaming(entity& ref, int num_messages) { void start_streaming(entity& ref, int32_t num_messages) {
CAF_REQUIRE_NOT_EQUAL(num_messages, 0); CAF_REQUIRE_NOT_EQUAL(num_messages, 0);
using downstream_manager = broadcast_downstream_manager<int>; using downstream_manager = broadcast_downstream_manager<int32_t>;
struct driver final : public stream_source_driver<downstream_manager> { struct driver final : public stream_source_driver<downstream_manager> {
public: public:
driver(int32_t sentinel) : x_(0), sentinel_(sentinel) { driver(int32_t sentinel) : x_(0), sentinel_(sentinel) {
...@@ -540,6 +547,7 @@ struct fixture { ...@@ -540,6 +547,7 @@ struct fixture {
caf::test::engine::argv())) caf::test::engine::argv()))
CAF_FAIL("parsing the config failed: " << to_string(err)); CAF_FAIL("parsing the config failed: " << to_string(err));
cfg.set("scheduler.policy", caf::atom("testing")); cfg.set("scheduler.policy", caf::atom("testing"));
cfg.add_message_types<id_block::native_streaming_classes>();
return cfg; return cfg;
} }
......
...@@ -30,6 +30,13 @@ ...@@ -30,6 +30,13 @@
#include "caf/event_based_actor.hpp" #include "caf/event_based_actor.hpp"
#include "caf/stateful_actor.hpp" #include "caf/stateful_actor.hpp"
CAF_BEGIN_TYPE_ID_BLOCK(pipeline_streaming, first_custom_type_id)
CAF_ADD_TYPE_ID(pipeline_streaming, (caf::stream<int32_t>) )
CAF_ADD_TYPE_ID(pipeline_streaming, (std::vector<int32_t>) )
CAF_END_TYPE_ID_BLOCK(pipeline_streaming)
using std::string; using std::string;
using namespace caf; using namespace caf;
...@@ -83,16 +90,16 @@ TESTEE_STATE(infinite_source) { ...@@ -83,16 +90,16 @@ TESTEE_STATE(infinite_source) {
TESTEE(infinite_source) { TESTEE(infinite_source) {
return { return {
[=](string& fname) -> result<stream<int>> { [=](string& fname) -> result<stream<int32_t>> {
CAF_CHECK_EQUAL(fname, "numbers.txt"); CAF_CHECK_EQUAL(fname, "numbers.txt");
CAF_CHECK_EQUAL(self->mailbox().empty(), true); CAF_CHECK_EQUAL(self->mailbox().empty(), true);
return attach_stream_source( return attach_stream_source(
self, [](int& x) { x = 0; }, self, [](int32_t& x) { x = 0; },
[](int& x, downstream<int>& out, size_t num) { [](int32_t& x, downstream<int32_t>& out, size_t num) {
for (size_t i = 0; i < num; ++i) for (size_t i = 0; i < num; ++i)
out.push(x++); out.push(x++);
}, },
[](const int&) { return false; }, fin<int>(self)); [](const int32_t&) { return false; }, fin<int>(self));
}, },
}; };
} }
...@@ -103,7 +110,7 @@ TESTEE_STATE(file_reader) { ...@@ -103,7 +110,7 @@ TESTEE_STATE(file_reader) {
VARARGS_TESTEE(file_reader, size_t buf_size) { VARARGS_TESTEE(file_reader, size_t buf_size) {
return { return {
[=](string& fname) -> result<stream<int>> { [=](string& fname) -> result<stream<int32_t>> {
CAF_CHECK_EQUAL(fname, "numbers.txt"); CAF_CHECK_EQUAL(fname, "numbers.txt");
CAF_CHECK_EQUAL(self->mailbox().empty(), true); CAF_CHECK_EQUAL(self->mailbox().empty(), true);
return attach_stream_source(self, init(buf_size), push_from_buf, return attach_stream_source(self, init(buf_size), push_from_buf,
...@@ -119,14 +126,14 @@ VARARGS_TESTEE(file_reader, size_t buf_size) { ...@@ -119,14 +126,14 @@ VARARGS_TESTEE(file_reader, size_t buf_size) {
} }
TESTEE_STATE(sum_up) { TESTEE_STATE(sum_up) {
int x = 0; int32_t x = 0;
int fin_called = 0; int32_t fin_called = 0;
}; };
TESTEE(sum_up) { TESTEE(sum_up) {
using intptr = int*; using intptr = int32_t*;
return { return {
[=](stream<int>& in) { [=](stream<int32_t>& in) {
return attach_stream_sink( return attach_stream_sink(
self, self,
// input stream // input stream
...@@ -134,22 +141,22 @@ TESTEE(sum_up) { ...@@ -134,22 +141,22 @@ TESTEE(sum_up) {
// initialize state // initialize state
[=](intptr& x) { x = &self->state.x; }, [=](intptr& x) { x = &self->state.x; },
// processing step // processing step
[](intptr& x, int y) { *x += y; }, fin<intptr>(self)); [](intptr& x, int32_t y) { *x += y; }, fin<intptr>(self));
}, },
}; };
} }
TESTEE_STATE(delayed_sum_up) { TESTEE_STATE(delayed_sum_up) {
int x = 0; int32_t x = 0;
int fin_called = 0; int32_t fin_called = 0;
}; };
TESTEE(delayed_sum_up) { TESTEE(delayed_sum_up) {
using intptr = int*; using intptr = int32_t*;
self->set_default_handler(skip); self->set_default_handler(skip);
return { return {
[=](ok_atom) { [=](ok_atom) {
self->become([=](stream<int>& in) { self->become([=](stream<int32_t>& in) {
self->set_default_handler(print_and_drop); self->set_default_handler(print_and_drop);
return attach_stream_sink( return attach_stream_sink(
self, self,
...@@ -158,7 +165,7 @@ TESTEE(delayed_sum_up) { ...@@ -158,7 +165,7 @@ TESTEE(delayed_sum_up) {
// initialize state // initialize state
[=](intptr& x) { x = &self->state.x; }, [=](intptr& x) { x = &self->state.x; },
// processing step // processing step
[](intptr& x, int y) { *x += y; }, [](intptr& x, int32_t y) { *x += y; },
// cleanup // cleanup
fin<intptr>(self)); fin<intptr>(self));
}); });
...@@ -167,26 +174,26 @@ TESTEE(delayed_sum_up) { ...@@ -167,26 +174,26 @@ TESTEE(delayed_sum_up) {
} }
TESTEE_STATE(broken_sink) { TESTEE_STATE(broken_sink) {
int fin_called = 0; int32_t fin_called = 0;
}; };
TESTEE(broken_sink) { TESTEE(broken_sink) {
CAF_IGNORE_UNUSED(self); CAF_IGNORE_UNUSED(self);
return { return {
[=](stream<int>&, const actor&) { [=](stream<int32_t>&, const actor&) {
// nop // nop
}, },
}; };
} }
TESTEE_STATE(filter) { TESTEE_STATE(filter) {
int fin_called = 0; int32_t fin_called = 0;
}; };
TESTEE(filter) { TESTEE(filter) {
CAF_IGNORE_UNUSED(self); CAF_IGNORE_UNUSED(self);
return { return {
[=](stream<int>& in) { [=](stream<int32_t>& in) {
return attach_stream_stage( return attach_stream_stage(
self, self,
// input stream // input stream
...@@ -196,7 +203,7 @@ TESTEE(filter) { ...@@ -196,7 +203,7 @@ TESTEE(filter) {
// nop // nop
}, },
// processing step // processing step
[](unit_t&, downstream<int>& out, int x) { [](unit_t&, downstream<int32_t>& out, int32_t x) {
if ((x & 0x01) != 0) if ((x & 0x01) != 0)
out.push(x); out.push(x);
}, },
...@@ -207,13 +214,13 @@ TESTEE(filter) { ...@@ -207,13 +214,13 @@ TESTEE(filter) {
} }
TESTEE_STATE(doubler) { TESTEE_STATE(doubler) {
int fin_called = 0; int32_t fin_called = 0;
}; };
TESTEE(doubler) { TESTEE(doubler) {
CAF_IGNORE_UNUSED(self); CAF_IGNORE_UNUSED(self);
return { return {
[=](stream<int>& in) { [=](stream<int32_t>& in) {
return attach_stream_stage( return attach_stream_stage(
self, self,
// input stream // input stream
...@@ -223,14 +230,20 @@ TESTEE(doubler) { ...@@ -223,14 +230,20 @@ TESTEE(doubler) {
// nop // nop
}, },
// processing step // processing step
[](unit_t&, downstream<int>& out, int x) { out.push(x * 2); }, [](unit_t&, downstream<int32_t>& out, int32_t x) { out.push(x * 2); },
// cleanup // cleanup
fin<unit_t>(self)); fin<unit_t>(self));
}, },
}; };
} }
struct fixture : test_coordinator_fixture<> { struct config : actor_system_config {
config() {
add_message_types<id_block::pipeline_streaming>();
}
};
struct fixture : test_coordinator_fixture<config> {
void tick() { void tick() {
advance_time(cfg.stream_credit_round_interval); advance_time(cfg.stream_credit_round_interval);
} }
......
...@@ -68,14 +68,14 @@ struct consumer { ...@@ -68,14 +68,14 @@ struct consumer {
intrusive::task_result operator()(const Key&, const Queue&, intrusive::task_result operator()(const Key&, const Queue&,
const mailbox_element& x) { const mailbox_element& x) {
if (!x.content().match_elements<int>()) if (!x.content().match_elements<int>())
CAF_FAIL("unexepected message: " << x.content()); CAF_FAIL("unexpected message: " << x.content());
ints.emplace_back(x.content().get_as<int>(0)); ints.emplace_back(x.content().get_as<int>(0));
return intrusive::task_result::resume; return intrusive::task_result::resume;
} }
template <class Key, class Queue, class... Ts> template <class Key, class Queue, class... Ts>
intrusive::task_result operator()(const Key&, const Queue&, const Ts&...) { intrusive::task_result operator()(const Key&, const Queue&, const Ts&...) {
CAF_FAIL("unexepected message type"); // << typeid(Ts).name()); CAF_FAIL("unexpected message type"); // << typeid(Ts).name());
return intrusive::task_result::resume; return intrusive::task_result::resume;
} }
}; };
......
...@@ -33,6 +33,21 @@ ...@@ -33,6 +33,21 @@
#include "caf/event_based_actor.hpp" #include "caf/event_based_actor.hpp"
#include "caf/stateful_actor.hpp" #include "caf/stateful_actor.hpp"
namespace {
enum class level;
} // namespace
CAF_BEGIN_TYPE_ID_BLOCK(selective_streaming, first_custom_type_id)
CAF_ADD_TYPE_ID(selective_streaming, (caf::stream<std::pair<level, std::string>>) )
CAF_ADD_TYPE_ID(selective_streaming, (level))
CAF_ADD_TYPE_ID(selective_streaming, (std::pair<level, std::string>) )
CAF_ADD_TYPE_ID(selective_streaming, (std::vector<std::pair<level, std::string>>) )
CAF_END_TYPE_ID_BLOCK(selective_streaming)
using std::string; using std::string;
using namespace caf; using namespace caf;
...@@ -73,7 +88,8 @@ buf make_log(level lvl) { ...@@ -73,7 +88,8 @@ buf make_log(level lvl) {
TESTEE_SETUP(); TESTEE_SETUP();
TESTEE(log_producer) { TESTEE(log_producer) {
return {[=](level lvl) -> result<stream<value_type>> { return {
[=](level lvl) -> result<stream<value_type>> {
auto res = attach_stream_source( auto res = attach_stream_source(
self, self,
// initialize state // initialize state
...@@ -100,7 +116,8 @@ TESTEE(log_producer) { ...@@ -100,7 +116,8 @@ TESTEE(log_producer) {
"source has wrong manager_type type"); "source has wrong manager_type type");
out.set_filter(res.outbound_slot(), lvl); out.set_filter(res.outbound_slot(), lvl);
return res; return res;
}}; },
};
} }
TESTEE_STATE(log_dispatcher) { TESTEE_STATE(log_dispatcher) {
...@@ -158,7 +175,7 @@ TESTEE(log_consumer) { ...@@ -158,7 +175,7 @@ TESTEE(log_consumer) {
struct config : actor_system_config { struct config : actor_system_config {
config() { config() {
add_message_type<value_type>("value_type"); add_message_types<id_block::selective_streaming>();
} }
}; };
......
...@@ -68,6 +68,25 @@ ...@@ -68,6 +68,25 @@
#include "caf/detail/safe_equal.hpp" #include "caf/detail/safe_equal.hpp"
#include "caf/detail/type_traits.hpp" #include "caf/detail/type_traits.hpp"
namespace {
enum class test_enum : uint32_t;
struct raw_struct;
struct test_array;
struct test_empty_non_pod;
} // namespace
CAF_BEGIN_TYPE_ID_BLOCK(serialization, first_custom_type_id)
CAF_ADD_TYPE_ID(serialization, (raw_struct))
CAF_ADD_TYPE_ID(serialization, (std::vector<bool>))
CAF_ADD_TYPE_ID(serialization, (test_array))
CAF_ADD_TYPE_ID(serialization, (test_empty_non_pod))
CAF_ADD_TYPE_ID(serialization, (test_enum))
CAF_END_TYPE_ID_BLOCK(serialization)
using namespace std; using namespace std;
using namespace caf; using namespace caf;
using caf::detail::type_erased_value_impl; using caf::detail::type_erased_value_impl;
...@@ -135,11 +154,8 @@ typename Inspector::result_type inspect(Inspector& f, test_empty_non_pod&) { ...@@ -135,11 +154,8 @@ typename Inspector::result_type inspect(Inspector& f, test_empty_non_pod&) {
class config : public actor_system_config { class config : public actor_system_config {
public: public:
config() { config() {
add_message_type<test_enum>("test_enum"); puts("add_message_types");
add_message_type<raw_struct>("raw_struct"); add_message_types<id_block::serialization>();
add_message_type<test_array>("test_array");
add_message_type<test_empty_non_pod>("test_empty_non_pod");
add_message_type<std::vector<bool>>("bool_vector");
} }
}; };
......
...@@ -31,6 +31,39 @@ ...@@ -31,6 +31,39 @@
# define ERROR_HANDLER [&](error& err) { CAF_FAIL(system.render(err)); } # define ERROR_HANDLER [&](error& err) { CAF_FAIL(system.render(err)); }
namespace {
struct get_state_msg;
struct my_request;
using server_type = caf::typed_actor<caf::replies_to<my_request>::with<bool>>;
using event_testee_type
= caf::typed_actor<caf::replies_to<get_state_msg>::with<std::string>,
caf::replies_to<std::string>::with<void>,
caf::replies_to<float>::with<void>,
caf::replies_to<int32_t>::with<int32_t>>;
using string_actor
= caf::typed_actor<caf::replies_to<std::string>::with<std::string>>;
using int_actor = caf::typed_actor<caf::replies_to<int32_t>::with<int32_t>>;
using float_actor = caf::typed_actor<caf::reacts_to<float>>;
} // namespace
CAF_BEGIN_TYPE_ID_BLOCK(typed_spawn, first_custom_type_id)
CAF_ADD_TYPE_ID(typed_spawn, (event_testee_type))
CAF_ADD_TYPE_ID(typed_spawn, (float_actor))
CAF_ADD_TYPE_ID(typed_spawn, (get_state_msg))
CAF_ADD_TYPE_ID(typed_spawn, (int_actor))
CAF_ADD_TYPE_ID(typed_spawn, (my_request))
CAF_ADD_TYPE_ID(typed_spawn, (string_actor))
CAF_END_TYPE_ID_BLOCK(typed_spawn)
using std::string; using std::string;
using namespace caf; using namespace caf;
...@@ -48,7 +81,7 @@ error make_error(mock_errc x) { ...@@ -48,7 +81,7 @@ error make_error(mock_errc x) {
} }
// check invariants of type system // check invariants of type system
using dummy1 = typed_actor<reacts_to<int, int>, using dummy1 = typed_actor<reacts_to<int32_t, int32_t>,
replies_to<double>::with<double>>; replies_to<double>::with<double>>;
using dummy2 = dummy1::extend<reacts_to<ok_atom>>; using dummy2 = dummy1::extend<reacts_to<ok_atom>>;
...@@ -56,8 +89,8 @@ using dummy2 = dummy1::extend<reacts_to<ok_atom>>; ...@@ -56,8 +89,8 @@ using dummy2 = dummy1::extend<reacts_to<ok_atom>>;
static_assert(std::is_convertible<dummy2, dummy1>::value, static_assert(std::is_convertible<dummy2, dummy1>::value,
"handle not assignable to narrower definition"); "handle not assignable to narrower definition");
using dummy3 = typed_actor<reacts_to<float, int>>; using dummy3 = typed_actor<reacts_to<float, int32_t>>;
using dummy4 = typed_actor<replies_to<int>::with<double>>; using dummy4 = typed_actor<replies_to<int32_t>::with<double>>;
using dummy5 = dummy4::extend_with<dummy3>; using dummy5 = dummy4::extend_with<dummy3>;
static_assert(std::is_convertible<dummy5, dummy3>::value, static_assert(std::is_convertible<dummy5, dummy3>::value,
...@@ -71,8 +104,8 @@ static_assert(std::is_convertible<dummy5, dummy4>::value, ...@@ -71,8 +104,8 @@ static_assert(std::is_convertible<dummy5, dummy4>::value,
******************************************************************************/ ******************************************************************************/
struct my_request { struct my_request {
int a; int32_t a;
int b; int32_t b;
}; };
template <class Inspector> template <class Inspector>
...@@ -80,8 +113,6 @@ typename Inspector::result_type inspect(Inspector& f, my_request& x) { ...@@ -80,8 +113,6 @@ typename Inspector::result_type inspect(Inspector& f, my_request& x) {
return f(x.a, x.b); return f(x.a, x.b);
} }
using server_type = typed_actor<replies_to<my_request>::with<bool>>;
server_type::behavior_type typed_server1() { server_type::behavior_type typed_server1() {
return { return {
[](const my_request& req) { return req.a == req.b; }, [](const my_request& req) { return req.a == req.b; },
...@@ -121,10 +152,6 @@ void client(event_based_actor* self, const actor& parent, ...@@ -121,10 +152,6 @@ void client(event_based_actor* self, const actor& parent,
struct get_state_msg {}; struct get_state_msg {};
using event_testee_type = typed_actor<
replies_to<get_state_msg>::with<string>, replies_to<string>::with<void>,
replies_to<float>::with<void>, replies_to<int>::with<int>>;
class event_testee : public event_testee_type::base { class event_testee : public event_testee_type::base {
public: public:
event_testee(actor_config& cfg) : event_testee_type::base(cfg) { event_testee(actor_config& cfg) : event_testee_type::base(cfg) {
...@@ -170,8 +197,6 @@ public: ...@@ -170,8 +197,6 @@ public:
* simple 'forwarding' chain * * simple 'forwarding' chain *
******************************************************************************/ ******************************************************************************/
using string_actor = typed_actor<replies_to<string>::with<string>>;
string_actor::behavior_type string_reverter() { string_actor::behavior_type string_reverter() {
return { return {
[](string& str) -> string { [](string& str) -> string {
...@@ -222,10 +247,6 @@ maybe_string_delegator(maybe_string_actor::pointer self, ...@@ -222,10 +247,6 @@ maybe_string_delegator(maybe_string_actor::pointer self,
* sending typed actor handles * * sending typed actor handles *
******************************************************************************/ ******************************************************************************/
using int_actor = typed_actor<replies_to<int>::with<int>>;
using float_actor = typed_actor<reacts_to<float>>;
int_actor::behavior_type int_fun() { int_actor::behavior_type int_fun() {
return { return {
[](int i) { return i * i; }, [](int i) { return i * i; },
...@@ -286,7 +307,7 @@ struct fixture { ...@@ -286,7 +307,7 @@ struct fixture {
scoped_actor self; scoped_actor self;
static actor_system_config& init(actor_system_config& cfg) { static actor_system_config& init(actor_system_config& cfg) {
cfg.add_message_type<get_state_msg>("get_state_msg"); cfg.add_message_types<id_block::typed_spawn>();
cfg.parse(test::engine::argc(), test::engine::argv()); cfg.parse(test::engine::argc(), test::engine::argv());
return cfg; return cfg;
} }
......
...@@ -90,3 +90,41 @@ endif () ...@@ -90,3 +90,41 @@ endif ()
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/caf install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/caf
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.hpp") FILES_MATCHING PATTERN "*.hpp")
# -- build unit tests ----------------------------------------------------------
if(CAF_NO_UNIT_TESTS)
return()
endif()
add_executable(caf-io-test test/io-test.cpp)
target_include_directories(caf-io-test PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/test")
if (CAF_BUILD_STATIC_ONLY OR CAF_BUILD_STATIC)
target_link_libraries(caf-io-test
libcaf_io_static
libcaf_core_static
${CAF_EXTRA_LDFLAGS})
else()
target_link_libraries(caf-io-test
libcaf_io_shared
libcaf_core_shared
${CAF_EXTRA_LDFLAGS})
endif()
caf_add_test_suites(caf-io-test
io.basp.message_queue
io.basp_broker
io.broker
io.http_broker
io.network.default_multiplexer
io.network.ip_endpoint
io.receive_buffer
io.remote_actor
io.remote_group
io.remote_spawn
io.unpublish
io.worker
)
...@@ -58,8 +58,3 @@ using doorman_ptr = intrusive_ptr<doorman>; ...@@ -58,8 +58,3 @@ using doorman_ptr = intrusive_ptr<doorman>;
} // namespace io } // namespace io
} // namespace caf } // namespace caf
// Allows the `middleman_actor` to create a `doorman` and then send it to the
// BASP broker.
CAF_ALLOW_UNSAFE_MESSAGE_TYPE(caf::io::doorman_ptr)
...@@ -18,6 +18,18 @@ ...@@ -18,6 +18,18 @@
#pragma once #pragma once
#include <map>
#include <string>
#include <vector>
#include "caf/allowed_unsafe_message_type.hpp"
#include "caf/type_id.hpp"
// Unfortunately required, because we cannot add a forward declaration for the
// enum protol::network that we need for assigning a type ID to
// io::network::address_listing.
#include "caf/io/network/protocol.hpp"
namespace caf { namespace caf {
// -- templates from the parent namespace necessary for defining aliases ------- // -- templates from the parent namespace necessary for defining aliases -------
...@@ -33,14 +45,30 @@ class typed_broker; ...@@ -33,14 +45,30 @@ class typed_broker;
// -- classes ------------------------------------------------------------------ // -- classes ------------------------------------------------------------------
class scribe; class abstract_broker;
class accept_handle;
class basp_broker;
class broker; class broker;
class connection_handle;
class datagram_servant;
class doorman; class doorman;
class middleman; class middleman;
class basp_broker;
class receive_policy; class receive_policy;
class abstract_broker; class scribe;
class datagram_servant;
// -- structs ------------------------------------------------------------------
struct acceptor_closed_msg;
struct acceptor_passivated_msg;
struct connection_closed_msg;
struct connection_passivated_msg;
struct data_transferred_msg;
struct datagram_sent_msg;
struct datagram_servant_closed_msg;
struct datagram_servant_passivated_msg;
struct new_connection_msg;
struct new_data_msg;
struct new_datagram_msg;
// -- aliases ------------------------------------------------------------------ // -- aliases ------------------------------------------------------------------
...@@ -52,11 +80,43 @@ using datagram_servant_ptr = intrusive_ptr<datagram_servant>; ...@@ -52,11 +80,43 @@ using datagram_servant_ptr = intrusive_ptr<datagram_servant>;
namespace network { namespace network {
class multiplexer;
class default_multiplexer; class default_multiplexer;
class multiplexer;
class receive_buffer;
using address_listing = std::map<protocol::network, std::vector<std::string>>;
} // namespace network } // namespace network
} // namespace io } // namespace io
} // namespace caf } // namespace caf
CAF_BEGIN_TYPE_ID_BLOCK(io_module, detail::io_module_begin)
CAF_ADD_TYPE_ID(io_module, (caf::io::accept_handle))
CAF_ADD_TYPE_ID(io_module, (caf::io::acceptor_closed_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::acceptor_passivated_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::connection_closed_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::connection_handle))
CAF_ADD_TYPE_ID(io_module, (caf::io::connection_passivated_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::data_transferred_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::datagram_sent_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::datagram_servant_closed_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::datagram_servant_passivated_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::datagram_servant_ptr))
CAF_ADD_TYPE_ID(io_module, (caf::io::doorman_ptr))
CAF_ADD_TYPE_ID(io_module, (caf::io::network::address_listing))
CAF_ADD_TYPE_ID(io_module, (caf::io::network::protocol))
CAF_ADD_TYPE_ID(io_module, (caf::io::network::receive_buffer))
CAF_ADD_TYPE_ID(io_module, (caf::io::new_connection_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::new_data_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::new_datagram_msg))
CAF_ADD_TYPE_ID(io_module, (caf::io::scribe_ptr))
CAF_END_TYPE_ID_BLOCK(io_module)
CAF_ALLOW_UNSAFE_MESSAGE_TYPE(caf::io::doorman_ptr)
CAF_ALLOW_UNSAFE_MESSAGE_TYPE(caf::io::scribe_ptr)
static_assert(caf::id_block::io_module::end == caf::detail::io_module_end,
"caf::id_block::io_module::end != caf::detail::io_module_end");
...@@ -69,8 +69,3 @@ using scribe_ptr = intrusive_ptr<scribe>; ...@@ -69,8 +69,3 @@ using scribe_ptr = intrusive_ptr<scribe>;
} // namespace io } // namespace io
} // namespace caf } // namespace caf
// Allows the `middleman_actor` to create a `scribe` and then send it to the
// BASP broker.
CAF_ALLOW_UNSAFE_MESSAGE_TYPE(caf::io::scribe_ptr)
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
#include "caf/sec.hpp" #include "caf/sec.hpp"
#include "caf/send.hpp" #include "caf/send.hpp"
CAF_ALLOW_UNSAFE_MESSAGE_TYPE(caf::actor_clock::duration_type)
CAF_ALLOW_UNSAFE_MESSAGE_TYPE(caf::actor_clock::time_point)
namespace { namespace {
#ifdef CAF_MSVC #ifdef CAF_MSVC
......
#include "io-test.hpp"
#include "caf/test/unit_test_impl.hpp"
#include "caf/test/io_dsl.hpp"
using calculator = caf::typed_actor<
caf::replies_to<caf::add_atom, int32_t, int32_t>::with<int32_t>,
caf::replies_to<caf::sub_atom, int32_t, int32_t>::with<int32_t>>;
CAF_BEGIN_TYPE_ID_BLOCK(io_test, caf::first_custom_type_id)
CAF_ADD_TYPE_ID(io_test, (calculator))
CAF_END_TYPE_ID_BLOCK(io_test)
...@@ -18,9 +18,7 @@ ...@@ -18,9 +18,7 @@
#define CAF_SUITE io.remote_spawn #define CAF_SUITE io.remote_spawn
#include "caf/config.hpp" #include "io-test.hpp"
#include "caf/test/io_dsl.hpp"
#include <cstring> #include <cstring>
#include <functional> #include <functional>
...@@ -36,17 +34,11 @@ using namespace caf; ...@@ -36,17 +34,11 @@ using namespace caf;
namespace { namespace {
using add_atom = atom_constant<atom("add")>;
using sub_atom = atom_constant<atom("sub")>;
using calculator = typed_actor<replies_to<add_atom, int, int>::with<int>,
replies_to<sub_atom, int, int>::with<int>>;
// function-based, dynamically typed, event-based API // function-based, dynamically typed, event-based API
behavior calculator_fun(event_based_actor*) { behavior calculator_fun(event_based_actor*) {
return { return {
[](add_atom, int a, int b) { return a + b; }, [](add_atom, int32_t a, int32_t b) { return a + b; },
[](sub_atom, int a, int b) { return a - b; }, [](sub_atom, int32_t a, int32_t b) { return a - b; },
}; };
} }
...@@ -58,8 +50,8 @@ public: ...@@ -58,8 +50,8 @@ public:
behavior make_behavior() override { behavior make_behavior() override {
return { return {
[](add_atom, int a, int b) { return a + b; }, [](add_atom, int32_t a, int32_t b) { return a + b; },
[](sub_atom, int a, int b) { return a - b; }, [](sub_atom, int32_t a, int32_t b) { return a - b; },
}; };
} }
}; };
...@@ -67,14 +59,15 @@ public: ...@@ -67,14 +59,15 @@ public:
// function-based, statically typed, event-based API // function-based, statically typed, event-based API
calculator::behavior_type typed_calculator_fun() { calculator::behavior_type typed_calculator_fun() {
return { return {
[](add_atom, int a, int b) { return a + b; }, [](add_atom, int32_t a, int32_t b) { return a + b; },
[](sub_atom, int a, int b) { return a - b; }, [](sub_atom, int32_t a, int32_t b) { return a - b; },
}; };
} }
struct config : actor_system_config { struct config : actor_system_config {
config() { config() {
load<io::middleman>(); load<io::middleman>();
add_message_types<id_block::io_test>();
add_actor_type<calculator_class>("calculator-class"); add_actor_type<calculator_class>("calculator-class");
add_actor_type("calculator", calculator_fun); add_actor_type("calculator", calculator_fun);
add_actor_type("typed_calculator", typed_calculator_fun); add_actor_type("typed_calculator", typed_calculator_fun);
......
...@@ -25,6 +25,8 @@ namespace opencl { ...@@ -25,6 +25,8 @@ namespace opencl {
class nd_range { class nd_range {
public: public:
nd_range() = default;
nd_range(const opencl::dim_vec& dimensions, nd_range(const opencl::dim_vec& dimensions,
const opencl::dim_vec& offsets = {}, const opencl::dim_vec& offsets = {},
const opencl::dim_vec& local_dimensions = {}) const opencl::dim_vec& local_dimensions = {})
...@@ -61,6 +63,11 @@ public: ...@@ -61,6 +63,11 @@ public:
return local_dims_; return local_dims_;
} }
template <class Inspector>
friend typename Inspector::result_type inspect(Inspector& f, nd_range& x) {
return f(x.dims_, x.offset_, x.local_dims_);
}
private: private:
opencl::dim_vec dims_; opencl::dim_vec dims_;
opencl::dim_vec offset_; opencl::dim_vec offset_;
...@@ -69,4 +76,3 @@ private: ...@@ -69,4 +76,3 @@ private:
} // namespace opencl } // namespace opencl
} // namespace caf } // namespace caf
...@@ -27,6 +27,18 @@ ...@@ -27,6 +27,18 @@
#include "caf/opencl/all.hpp" #include "caf/opencl/all.hpp"
template <size_t Size>
class square_matrix;
constexpr size_t matrix_size = 8;
CAF_BEGIN_TYPE_ID_BLOCK(proper_matrix, first_custom_type_id)
CAF_ADD_TYPE_ID(proper_matrix, (square_matrix<matrix_size>) )
CAF_ADD_TYPE_ID(proper_matrix, (std::vector<float>) )
CAF_END_TYPE_ID_BLOCK(proper_matrix)
using namespace caf; using namespace caf;
using namespace caf::opencl; using namespace caf::opencl;
...@@ -41,7 +53,6 @@ namespace { ...@@ -41,7 +53,6 @@ namespace {
using fvec = vector<float>; using fvec = vector<float>;
constexpr size_t matrix_size = 8;
constexpr const char* kernel_name = "matrix_mult"; constexpr const char* kernel_name = "matrix_mult";
// opencl kernel, multiplies matrix1 and matrix2 // opencl kernel, multiplies matrix1 and matrix2
...@@ -196,9 +207,7 @@ int main() { ...@@ -196,9 +207,7 @@ int main() {
// matrix_type ist not a simple type, // matrix_type ist not a simple type,
// it must be annouced to libcaf // it must be annouced to libcaf
actor_system_config cfg; actor_system_config cfg;
cfg.load<opencl::manager>() cfg.load<opencl::manager>().add_message_types<id_block::proper_matrix>();
.add_message_type<fvec>("float_vector")
.add_message_type<matrix_type>("square_matrix");
actor_system system{cfg}; actor_system system{cfg};
system.spawn(multiplier); system.spawn(multiplier);
system.await_all_actors_done(); system.await_all_actors_done();
......
...@@ -26,6 +26,14 @@ ...@@ -26,6 +26,14 @@
#include "caf/all.hpp" #include "caf/all.hpp"
#include "caf/opencl/all.hpp" #include "caf/opencl/all.hpp"
CAF_BEGIN_TYPE_ID_BLOCK(scan, first_custom_type_id)
CAF_ADD_TYPE_ID(scan, (caf::opencl::dim_vec))
CAF_ADD_TYPE_ID(scan, (caf::opencl::nd_range))
CAF_ADD_TYPE_ID(scan, (std::vector<uint32_t>))
CAF_END_TYPE_ID_BLOCK(scan)
using namespace caf; using namespace caf;
using namespace caf::opencl; using namespace caf::opencl;
...@@ -39,7 +47,7 @@ using caf::detail::limited_vector; ...@@ -39,7 +47,7 @@ using caf::detail::limited_vector;
namespace { namespace {
using uval = unsigned; using uval = uint32_t;
using uvec = std::vector<uval>; using uvec = std::vector<uval>;
using uref = mem_ref<uval>; using uref = mem_ref<uval>;
...@@ -178,8 +186,7 @@ T round_up(T numToRound, T multiple) { ...@@ -178,8 +186,7 @@ T round_up(T numToRound, T multiple) {
int main() { int main() {
actor_system_config cfg; actor_system_config cfg;
cfg.load<opencl::manager>() cfg.load<opencl::manager>().add_message_types<id_block::scan>();
.add_message_type<uvec>("uint_vector");
actor_system system{cfg}; actor_system system{cfg};
cout << "Calculating exclusive scan of '" << problem_size cout << "Calculating exclusive scan of '" << problem_size
<< "' values." << endl; << "' values." << endl;
......
...@@ -24,6 +24,13 @@ ...@@ -24,6 +24,13 @@
#include "caf/all.hpp" #include "caf/all.hpp"
#include "caf/opencl/all.hpp" #include "caf/opencl/all.hpp"
CAF_BEGIN_TYPE_ID_BLOCK(simple_matrix, first_custom_type_id)
CAF_ADD_TYPE_ID(simple_matrix, (std::vector<float>) )
CAF_END_TYPE_ID_BLOCK(simple_matrix)
using namespace std; using namespace std;
using namespace caf; using namespace caf;
using namespace caf::opencl; using namespace caf::opencl;
...@@ -109,8 +116,7 @@ void multiplier(event_based_actor* self) { ...@@ -109,8 +116,7 @@ void multiplier(event_based_actor* self) {
int main() { int main() {
actor_system_config cfg; actor_system_config cfg;
cfg.load<opencl::manager>() cfg.load<opencl::manager>().add_message_types<id_block::simple_matrix>();
.add_message_type<fvec>("float_vector");
actor_system system{cfg}; actor_system system{cfg};
system.spawn(multiplier); system.spawn(multiplier);
system.await_all_actors_done(); system.await_all_actors_done();
......
This diff is collapsed.
...@@ -64,3 +64,32 @@ if(NOT WIN32) ...@@ -64,3 +64,32 @@ if(NOT WIN32)
install(DIRECTORY caf/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/caf FILES_MATCHING PATTERN "*.hpp") install(DIRECTORY caf/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/caf FILES_MATCHING PATTERN "*.hpp")
endif() endif()
# -- build unit tests ----------------------------------------------------------
if(CAF_NO_UNIT_TESTS)
return()
endif()
add_executable(caf-openssl-test test/openssl-test.cpp)
target_include_directories(caf-openssl-test PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/test")
if (CAF_BUILD_STATIC_ONLY OR CAF_BUILD_STATIC)
target_link_libraries(caf-openssl-test
libcaf_openssl_static
libcaf_io_static
libcaf_core_static
${CAF_EXTRA_LDFLAGS})
else()
target_link_libraries(caf-openssl-test
libcaf_openssl_shared
libcaf_io_shared
libcaf_core_shared
${CAF_EXTRA_LDFLAGS})
endif()
caf_add_test_suites(caf-openssl-test
openssl.authentication
openssl.remote_actor
)
#include "openssl-test.hpp"
#include "caf/test/unit_test_impl.hpp"
#include "caf/test/dsl.hpp"
#include <cstdint>
CAF_BEGIN_TYPE_ID_BLOCK(openssl_test, caf::first_custom_type_id)
CAF_ADD_TYPE_ID(openssl_test, (std::vector<int32_t>) )
CAF_END_TYPE_ID_BLOCK(openssl_test)
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include "caf/openssl/all.hpp" #include "caf/openssl/all.hpp"
#include "caf/test/dsl.hpp" #include "openssl-test.hpp"
#include "caf/config.hpp" #include "caf/config.hpp"
...@@ -54,11 +54,10 @@ public: ...@@ -54,11 +54,10 @@ public:
config() { config() {
load<io::middleman>(); load<io::middleman>();
load<openssl::manager>(); load<openssl::manager>();
add_message_type<std::vector<int>>("std::vector<int>");
actor_system_config::parse(test::engine::argc(), test::engine::argv()); actor_system_config::parse(test::engine::argc(), test::engine::argv());
set("middleman.manual-multiplexing", true); set("middleman.manual-multiplexing", true);
set("middleman.attach-utility-actors", true); set("middleman.attach-utility-actors", true);
set("scheduler.policy", atom("testing")); set("scheduler.policy", "testing");
} }
static std::string data_dir() { static std::string data_dir() {
......
...@@ -16,14 +16,12 @@ ...@@ -16,14 +16,12 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#include "caf/config.hpp" #define CAF_SUITE openssl.dynamic_remote_actor
#include <signal.h> #include "openssl-test.hpp"
#define CAF_SUITE openssl_dynamic_remote_actor
#include "caf/test/dsl.hpp"
#include <algorithm> #include <algorithm>
#include <signal.h>
#include <sstream> #include <sstream>
#include <utility> #include <utility>
#include <vector> #include <vector>
...@@ -43,7 +41,7 @@ public: ...@@ -43,7 +41,7 @@ public:
config() { config() {
load<io::middleman>(); load<io::middleman>();
load<openssl::manager>(); load<openssl::manager>();
add_message_type<std::vector<int>>("std::vector<int>"); add_message_types<id_block::openssl_test>();
actor_system_config::parse(test::engine::argc(), test::engine::argv()); actor_system_config::parse(test::engine::argc(), test::engine::argv());
// Setting the "max consecutive reads" to 1 is highly likely to cause // Setting the "max consecutive reads" to 1 is highly likely to cause
// OpenSSL to buffer data internally and report "pending" data after a read // OpenSSL to buffer data internally and report "pending" data after a read
...@@ -67,7 +65,7 @@ struct fixture { ...@@ -67,7 +65,7 @@ struct fixture {
behavior make_pong_behavior() { behavior make_pong_behavior() {
return { return {
[](int val) -> int { [](int32_t val) -> int32_t {
++val; ++val;
CAF_MESSAGE("pong with " << val); CAF_MESSAGE("pong with " << val);
return val; return val;
...@@ -79,7 +77,7 @@ behavior make_ping_behavior(event_based_actor* self, const actor& pong) { ...@@ -79,7 +77,7 @@ behavior make_ping_behavior(event_based_actor* self, const actor& pong) {
CAF_MESSAGE("ping with " << 0); CAF_MESSAGE("ping with " << 0);
self->send(pong, 0); self->send(pong, 0);
return { return {
[=](int val) -> int { [=](int32_t val) -> int32_t {
if (val == 3) { if (val == 3) {
CAF_MESSAGE("ping with exit"); CAF_MESSAGE("ping with exit");
self->send_exit(self->current_sender(), exit_reason::user_shutdown); self->send_exit(self->current_sender(), exit_reason::user_shutdown);
...@@ -92,7 +90,7 @@ behavior make_ping_behavior(event_based_actor* self, const actor& pong) { ...@@ -92,7 +90,7 @@ behavior make_ping_behavior(event_based_actor* self, const actor& pong) {
}; };
} }
std::string to_string(const std::vector<int>& vec) { std::string to_string(const std::vector<int32_t>& vec) {
std::ostringstream os; std::ostringstream os;
for (size_t i = 0; i + 1 < vec.size(); ++i) for (size_t i = 0; i + 1 < vec.size(); ++i)
os << vec[i] << ", "; os << vec[i] << ", ";
...@@ -102,7 +100,7 @@ std::string to_string(const std::vector<int>& vec) { ...@@ -102,7 +100,7 @@ std::string to_string(const std::vector<int>& vec) {
behavior make_sort_behavior() { behavior make_sort_behavior() {
return { return {
[](std::vector<int>& vec) -> std::vector<int> { [](std::vector<int32_t>& vec) -> std::vector<int32_t> {
CAF_MESSAGE("sorter received: " << to_string(vec)); CAF_MESSAGE("sorter received: " << to_string(vec));
std::sort(vec.begin(), vec.end()); std::sort(vec.begin(), vec.end());
CAF_MESSAGE("sorter sent: " << to_string(vec)); CAF_MESSAGE("sorter sent: " << to_string(vec));
...@@ -113,12 +111,12 @@ behavior make_sort_behavior() { ...@@ -113,12 +111,12 @@ behavior make_sort_behavior() {
behavior make_sort_requester_behavior(event_based_actor* self, behavior make_sort_requester_behavior(event_based_actor* self,
const actor& sorter) { const actor& sorter) {
self->send(sorter, std::vector<int>{5, 4, 3, 2, 1}); self->send(sorter, std::vector<int32_t>{5, 4, 3, 2, 1});
return { return {
[=](const std::vector<int>& vec) { [=](const std::vector<int32_t>& vec) {
CAF_MESSAGE("sort requester received: " << to_string(vec)); CAF_MESSAGE("sort requester received: " << to_string(vec));
for (size_t i = 1; i < vec.size(); ++i) for (size_t i = 1; i < vec.size(); ++i)
CAF_CHECK_EQUAL(static_cast<int>(i), vec[i - 1]); CAF_CHECK_EQUAL(static_cast<int32_t>(i), vec[i - 1]);
self->send_exit(sorter, exit_reason::user_shutdown); self->send_exit(sorter, exit_reason::user_shutdown);
self->quit(); self->quit();
}, },
...@@ -127,7 +125,7 @@ behavior make_sort_requester_behavior(event_based_actor* self, ...@@ -127,7 +125,7 @@ behavior make_sort_requester_behavior(event_based_actor* self,
behavior fragile_mirror(event_based_actor* self) { behavior fragile_mirror(event_based_actor* self) {
return { return {
[=](int i) { [=](int32_t i) {
self->quit(exit_reason::user_shutdown); self->quit(exit_reason::user_shutdown);
return i; return i;
}, },
...@@ -139,7 +137,7 @@ behavior linking_actor(event_based_actor* self, const actor& buddy) { ...@@ -139,7 +137,7 @@ behavior linking_actor(event_based_actor* self, const actor& buddy) {
self->link_to(buddy); self->link_to(buddy);
self->send(buddy, 42); self->send(buddy, 42);
return { return {
[](int i) { CAF_CHECK_EQUAL(i, 42); }, [](int32_t i) { CAF_CHECK_EQUAL(i, 42); },
}; };
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment