Unverified Commit 7bcb25d0 authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #1462

Support string_view in make_message and make_error
parents 5d11121f 410e50b5
...@@ -16,6 +16,8 @@ is based on [Keep a Changelog](https://keepachangelog.com). ...@@ -16,6 +16,8 @@ is based on [Keep a Changelog](https://keepachangelog.com).
- The CLI argument parser now supports a space separator when using long - The CLI argument parser now supports a space separator when using long
argument names, e.g., `--foo bar`. This is in addition to the existing argument names, e.g., `--foo bar`. This is in addition to the existing
`--foo=bar` syntax. `--foo=bar` syntax.
- The functions `make_message` and `make_error` now support `std::string_view`
as input and automatically convert it to `std::string`.
### Changed ### Changed
......
...@@ -52,6 +52,11 @@ struct implicit_conversions<char*> { ...@@ -52,6 +52,11 @@ struct implicit_conversions<char*> {
using type = std::string; using type = std::string;
}; };
template <>
struct implicit_conversions<std::string_view> {
using type = std::string;
};
template <size_t N> template <size_t N>
struct implicit_conversions<char[N]> : implicit_conversions<char*> {}; struct implicit_conversions<char[N]> : implicit_conversions<char*> {};
......
...@@ -9,29 +9,40 @@ ...@@ -9,29 +9,40 @@
#include "core-test.hpp" #include "core-test.hpp"
using namespace caf; using namespace caf;
using namespace std::literals;
CAF_TEST(default constructed errors evaluate to false) { TEST_CASE("default-constructed errors evaluate to false") {
error err; error err;
CHECK(!err); CHECK(!err);
} }
CAF_TEST(error code zero is not an error) { TEST_CASE("error code zero is not an error") {
CHECK(!error(sec::none)); CHECK(!error(sec::none));
CHECK(!make_error(sec::none)); CHECK(!make_error(sec::none));
CHECK(!error{error_code<sec>(sec::none)}); CHECK(!error{error_code<sec>(sec::none)});
} }
CAF_TEST(error codes that are not zero are errors) { TEST_CASE("error codes that are not zero are errors") {
CHECK(error(sec::unexpected_message)); CHECK(error(sec::unexpected_message));
CHECK(make_error(sec::unexpected_message)); CHECK(make_error(sec::unexpected_message));
CHECK(error{error_code<sec>(sec::unexpected_message)}); CHECK(error{error_code<sec>(sec::unexpected_message)});
} }
CAF_TEST(errors convert enums to their integer value) { TEST_CASE("errors convert enums to their integer value") {
CHECK_EQ(make_error(sec::unexpected_message).code(), 1u); CHECK_EQ(make_error(sec::unexpected_message).code(), 1u);
CHECK_EQ(error{error_code<sec>(sec::unexpected_message)}.code(), 1u); CHECK_EQ(error{error_code<sec>(sec::unexpected_message)}.code(), 1u);
} }
TEST_CASE("make_error converts string-like arguments to strings") {
using std::string;
char foo1[] = "foo1";
auto err = make_error(sec::runtime_error, foo1, "foo2"sv, "foo3", "foo4"s);
if (CHECK(err)) {
CHECK_EQ(err.code(), static_cast<uint8_t>(sec::runtime_error));
CHECK((err.context().match_elements<string, string, string, string>()));
}
}
SCENARIO("errors provide human-readable to_string output") { SCENARIO("errors provide human-readable to_string output") {
auto err_str = [](auto... xs) { auto err_str = [](auto... xs) {
return to_string(make_error(std::move(xs)...)); return to_string(make_error(std::move(xs)...));
......
...@@ -24,8 +24,7 @@ using std::string; ...@@ -24,8 +24,7 @@ using std::string;
using std::vector; using std::vector;
using namespace caf; using namespace caf;
using namespace std::literals;
using namespace std::literals::string_literals;
namespace { namespace {
...@@ -36,8 +35,8 @@ std::string msg_as_string(Ts&&... xs) { ...@@ -36,8 +35,8 @@ std::string msg_as_string(Ts&&... xs) {
} // namespace } // namespace
CAF_TEST(messages allow index - based access) { TEST_CASE("messages allow index-based access") {
auto msg = make_message("abc", uint32_t{10}, 20.0); auto msg = make_message("abc"s, uint32_t{10}, 20.0);
CHECK_EQ(msg.size(), 3u); CHECK_EQ(msg.size(), 3u);
CHECK_EQ(msg.types(), (make_type_id_list<std::string, uint32_t, double>())); CHECK_EQ(msg.types(), (make_type_id_list<std::string, uint32_t, double>()));
CHECK_EQ(msg.get_as<std::string>(0), "abc"); CHECK_EQ(msg.get_as<std::string>(0), "abc");
...@@ -46,9 +45,9 @@ CAF_TEST(messages allow index - based access) { ...@@ -46,9 +45,9 @@ CAF_TEST(messages allow index - based access) {
CHECK_EQ(msg.cdata().get_reference_count(), 1u); CHECK_EQ(msg.cdata().get_reference_count(), 1u);
} }
CAF_TEST(message detach their content on mutating access) { TEST_CASE("message detach their content on mutating access") {
MESSAGE("Given to messages pointing to the same content."); MESSAGE("Given to messages pointing to the same content.");
auto msg1 = make_message("one", uint32_t{1}); auto msg1 = make_message("one"s, uint32_t{1});
auto msg2 = msg1; auto msg2 = msg1;
CHECK_EQ(msg1.cdata().get_reference_count(), 2u); CHECK_EQ(msg1.cdata().get_reference_count(), 2u);
CHECK_EQ(msg1.cptr(), msg2.cptr()); CHECK_EQ(msg1.cptr(), msg2.cptr());
...@@ -64,13 +63,13 @@ CAF_TEST(message detach their content on mutating access) { ...@@ -64,13 +63,13 @@ CAF_TEST(message detach their content on mutating access) {
CHECK_EQ(msg1.get_as<uint32_t>(1), msg2.get_as<uint32_t>(1)); CHECK_EQ(msg1.get_as<uint32_t>(1), msg2.get_as<uint32_t>(1));
} }
CAF_TEST(compare_custom_types) { TEST_CASE("messages can render custom types to strings") {
s2 tmp; s2 tmp;
tmp.value[0][1] = 100; tmp.value[0][1] = 100;
CHECK_NE(to_string(make_message(s2{})), to_string(make_message(tmp))); CHECK_NE(to_string(make_message(s2{})), to_string(make_message(tmp)));
} }
CAF_TEST(integers_to_string) { TEST_CASE("messages can render integers to strings") {
using ivec = vector<int32_t>; using ivec = vector<int32_t>;
using svec = vector<std::string>; using svec = vector<std::string>;
using sset = std::set<std::string>; using sset = std::set<std::string>;
...@@ -89,7 +88,7 @@ CAF_TEST(integers_to_string) { ...@@ -89,7 +88,7 @@ CAF_TEST(integers_to_string) {
CHECK_EQ(make_message(itup(1, 2, 3)).types()[0], type_id_v<itup>); CHECK_EQ(make_message(itup(1, 2, 3)).types()[0], type_id_v<itup>);
} }
CAF_TEST(to_string converts messages to strings) { TEST_CASE("to_string converts messages to strings") {
using svec = vector<string>; using svec = vector<string>;
CHECK_EQ(msg_as_string(), "message()"); CHECK_EQ(msg_as_string(), "message()");
CHECK_EQ(msg_as_string("hello", "world"), R"__(message("hello", "world"))__"); CHECK_EQ(msg_as_string("hello", "world"), R"__(message("hello", "world"))__");
...@@ -111,15 +110,7 @@ CAF_TEST(to_string converts messages to strings) { ...@@ -111,15 +110,7 @@ CAF_TEST(to_string converts messages to strings) {
CHECK_EQ(msg_as_string(s3{}), "message([1, 2, 3, 4])"); CHECK_EQ(msg_as_string(s3{}), "message([1, 2, 3, 4])");
} }
CAF_TEST(match_elements exposes element types) { TEST_CASE("messages are concatenable") {
auto msg = make_message(put_atom_v, "foo", int64_t{123});
CHECK((msg.match_element<put_atom>(0)));
CHECK((msg.match_element<string>(1)));
CHECK((msg.match_element<int64_t>(2)));
CHECK((msg.match_elements<put_atom, string, int64_t>()));
}
CAF_TEST(messages are concatenable) {
using std::make_tuple; using std::make_tuple;
CHECK(message::concat(make_tuple(int16_t{1}), make_tuple(uint8_t{2})) CHECK(message::concat(make_tuple(int16_t{1}), make_tuple(uint8_t{2}))
.matches(int16_t{1}, uint8_t{2})); .matches(int16_t{1}, uint8_t{2}));
...@@ -130,3 +121,24 @@ CAF_TEST(messages are concatenable) { ...@@ -130,3 +121,24 @@ CAF_TEST(messages are concatenable) {
CHECK(message::concat(make_tuple(int16_t{1}), make_message(uint8_t{2})) CHECK(message::concat(make_tuple(int16_t{1}), make_message(uint8_t{2}))
.matches(int16_t{1}, uint8_t{2})); .matches(int16_t{1}, uint8_t{2}));
} }
TEST_CASE("match_elements exposes element types") {
auto msg = make_message(put_atom_v, "foo", int64_t{123});
CHECK((msg.match_element<put_atom>(0)));
CHECK((msg.match_element<string>(1)));
CHECK((msg.match_element<int64_t>(2)));
CHECK((msg.match_elements<put_atom, string, int64_t>()));
}
TEST_CASE("messages implicitly convert string-like things to strings") {
auto is_hello_caf = [](const message& msg) {
return msg.match_elements<string>() && msg.get_as<string>(0) == "hello CAF";
};
// From character array.
char char_array[] = "hello CAF";
CHECK(is_hello_caf(make_message(char_array)));
// From string_view.
CHECK(is_hello_caf(make_message("hello CAF"sv)));
// From plain C-string literal.
CHECK(is_hello_caf(make_message("hello CAF")));
}
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