Commit 4d9f8aca authored by Hauke Goldhammer's avatar Hauke Goldhammer

Add errors to bb::tokenized_integer_reader and tests for them

parent 14d694f0
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
#pragma once #pragma once
#include "tokenized_integer_reader.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -56,11 +54,11 @@ struct stream_reader_state { ...@@ -56,11 +54,11 @@ struct stream_reader_state {
/// Gives this actor a useful name in CAF logs. /// Gives this actor a useful name in CAF logs.
const char* name; const char* name;
/// Stream /// Stream we are about to stream
// TODO: change after having raised the minimum GCC version to 5. // TODO: change after having raised the minimum GCC version to 5.
std::unique_ptr<InputStream> stream; std::unique_ptr<InputStream> stream;
/// Caches the stream line we are about to stream. /// Caches the line we are about to parse.
std::string line; std::string line;
}; };
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#pragma once #pragma once
#include <cstdint>
#include <limits>
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -26,19 +28,11 @@ ...@@ -26,19 +28,11 @@
#include "caf/stateful_actor.hpp" #include "caf/stateful_actor.hpp"
#include "caf/string_algorithms.hpp" #include "caf/string_algorithms.hpp"
#include "caf/unit.hpp" #include "caf/unit.hpp"
#include "caf/pec.hpp"
namespace caf { namespace caf {
namespace bb { namespace bb {
/// @relates stream_reader
/// The error codes for the stream_reader policy.
enum class stream_reader_policy_error : uint8_t { out_of_range = 1 };
error make_error(stream_reader_policy_error x) {
return {static_cast<uint8_t>(x), atom("stream")};
}
/// @relates stream_reader
/// The Policy defines how the stream_reader pares a line of the given stream to /// The Policy defines how the stream_reader pares a line of the given stream to
/// integers. /// integers.
template <class ValueType = int32_t> template <class ValueType = int32_t>
...@@ -56,11 +50,19 @@ public: ...@@ -56,11 +50,19 @@ public:
char* end = nullptr; char* end = nullptr;
auto value = strtoll(i, &end, 10); auto value = strtoll(i, &end, 10);
if (errno == ERANGE) { if (errno == ERANGE) {
return make_error(stream_reader_policy_error::out_of_range); if (value < 0) {
return make_error(pec::exponent_underflow);
}
return make_error(pec::exponent_overflow);
} }
if (std::numeric_limits<value_type>::min() > value)
return make_error(pec::exponent_underflow);
if (value > std::numeric_limits<value_type>::max())
return make_error(pec::exponent_overflow);
if (value == 0 && !(*end == ' ' || *end == '\0'))
return make_error(pec::unexpected_character);
++count; ++count;
out.push(value); out.push(value);
// TODO: check whether value fits into value_type
// Advance iterator. // Advance iterator.
i = end; i = end;
while (isspace(*i)) while (isspace(*i))
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#define CAF_SUITE stream_reader #define CAF_SUITE stream_reader
#include "caf/bb/stream_reader.hpp" #include "caf/bb/stream_reader.hpp"
#include "caf/bb/tokenized_integer_reader.hpp"
#include "caf/test/dsl.hpp" #include "caf/test/dsl.hpp"
...@@ -57,7 +58,13 @@ TESTEE(stream_reader_sink) { ...@@ -57,7 +58,13 @@ TESTEE(stream_reader_sink) {
self->state.vec.emplace_back(std::move(val)); self->state.vec.emplace_back(std::move(val));
}, },
// cleanup and produce result message // cleanup and produce result message
[=](unit_t&, const error&) { CAF_MESSAGE(self->name() << " is done"); }); [=](unit_t&, const error& e) {
if (e) {
CAF_MESSAGE(self->name() << " " << e);
} else {
CAF_MESSAGE(self->name() << " is done");
}
});
}}; }};
} }
...@@ -68,6 +75,9 @@ TESTEE_STATE(stream_monitor) { ...@@ -68,6 +75,9 @@ TESTEE_STATE(stream_monitor) {
TESTEE(stream_monitor) { TESTEE(stream_monitor) {
self->set_down_handler([=](const down_msg& dm) { self->set_down_handler([=](const down_msg& dm) {
CAF_CHECK_EQUAL(dm.source, self->state.streamer); CAF_CHECK_EQUAL(dm.source, self->state.streamer);
if (dm.reason)
CAF_CHECK_EQUAL(dm.reason,
pec::unexpected_character);
}); });
return {[=](join_atom, actor streamer) { return {[=](join_atom, actor streamer) {
...@@ -88,27 +98,17 @@ using fixture = test_coordinator_fixture<config>; ...@@ -88,27 +98,17 @@ using fixture = test_coordinator_fixture<config>;
CAF_TEST_FIXTURE_SCOPE(stream_reader_tests, fixture) CAF_TEST_FIXTURE_SCOPE(stream_reader_tests, fixture)
CAF_TEST(int_policy) {
bb::tokenized_integer_reader<value_type> pol;
std::deque<value_type> q;
std::deque<value_type> test{1, 2, 3, 4};
downstream<value_type> out(q);
std::string test_line = "1 2 3 4";
pol(test_line, out);
CAF_CHECK_EQUAL(q, test);
}
CAF_TEST(stream_to_sink) { CAF_TEST(stream_to_sink) {
scoped_actor self{sys}; scoped_actor self{sys};
std::string test_stringvalues = "1 2 3 4 5 6 7 78 1254 1 20\n4 56 78 95"; std::string test_stringvalues = "1 2 3 4 5 6 7 78 1254 1 20\n4 56 78 95";
std::unique_ptr<std::istringstream> ptr_test_stream{ std::unique_ptr<stream_type> ptr_test_stream{
new std::istringstream(test_stringvalues)}; new stream_type(test_stringvalues)};
std::vector<value_type> test_container{1, 2, 3, 4, 5, 6, 7, 78, std::vector<value_type> test_container{1, 2, 3, 4, 5, 6, 7, 78,
1254, 1, 20, 4, 56, 78, 95}; 1254, 1, 20, 4, 56, 78, 95};
auto sink = sys.spawn(stream_reader_sink); auto sink = sys.spawn(stream_reader_sink);
auto src auto src
= sys.spawn(bb::stream_reader<bb::tokenized_integer_reader<value_type>, = sys.spawn(bb::stream_reader<bb::tokenized_integer_reader<value_type>,
std::istringstream, actor>, stream_type, actor>,
std::move(ptr_test_stream), sink); std::move(ptr_test_stream), sink);
auto mon = sys.spawn(stream_monitor); auto mon = sys.spawn(stream_monitor);
self->send(mon, join_atom::value, src); self->send(mon, join_atom::value, src);
...@@ -120,8 +120,8 @@ CAF_TEST(stream_to_sink) { ...@@ -120,8 +120,8 @@ CAF_TEST(stream_to_sink) {
CAF_TEST(stream_to_sinks) { CAF_TEST(stream_to_sinks) {
scoped_actor self{sys}; scoped_actor self{sys};
std::string test_stringvalues = "1 2 3 4 5 6 7 78 1254 1 20\n4 56 78 95"; std::string test_stringvalues = "1 2 3 4 5 6 7 78 1254 1 20\n4 56 78 95";
std::unique_ptr<std::istringstream> ptr_test_stream{ std::unique_ptr<stream_type> ptr_test_stream{
new std::istringstream(test_stringvalues)}; new stream_type(test_stringvalues)};
std::vector<value_type> test_container{1, 2, 3, 4, 5, 6, 7, 78, std::vector<value_type> test_container{1, 2, 3, 4, 5, 6, 7, 78,
1254, 1, 20, 4, 56, 78, 95}; 1254, 1, 20, 4, 56, 78, 95};
auto snk1 = sys.spawn(stream_reader_sink); auto snk1 = sys.spawn(stream_reader_sink);
...@@ -129,7 +129,7 @@ CAF_TEST(stream_to_sinks) { ...@@ -129,7 +129,7 @@ CAF_TEST(stream_to_sinks) {
auto snk3 = sys.spawn(stream_reader_sink); auto snk3 = sys.spawn(stream_reader_sink);
auto src auto src
= sys.spawn(bb::stream_reader<bb::tokenized_integer_reader<value_type>, = sys.spawn(bb::stream_reader<bb::tokenized_integer_reader<value_type>,
std::istringstream, actor, actor, actor>, stream_type, actor, actor, actor>,
std::move(ptr_test_stream), snk1, snk2, snk3); std::move(ptr_test_stream), snk1, snk2, snk3);
auto mon = sys.spawn(stream_monitor); auto mon = sys.spawn(stream_monitor);
self->send(mon, join_atom::value, src); self->send(mon, join_atom::value, src);
...@@ -142,4 +142,19 @@ CAF_TEST(stream_to_sinks) { ...@@ -142,4 +142,19 @@ CAF_TEST(stream_to_sinks) {
test_container); test_container);
} }
CAF_TEST(error_stream_to_sink) {
scoped_actor self{sys};
std::string test_stringvalues = "1 2 3 4 5 6 7 rr 1254";
std::unique_ptr<stream_type> ptr_test_stream{
new stream_type(test_stringvalues)};
auto sink = sys.spawn(stream_reader_sink);
auto src
= sys.spawn(bb::stream_reader<bb::tokenized_integer_reader<value_type>,
stream_type, actor>,
std::move(ptr_test_stream), sink);
auto mon = sys.spawn(stream_monitor);
self->send(mon, join_atom::value, src);
run();
}
CAF_TEST_FIXTURE_SCOPE_END() CAF_TEST_FIXTURE_SCOPE_END()
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 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. *
******************************************************************************/
#define CAF_SUITE tokenized_integer_reader
#include "caf/bb/tokenized_integer_reader.hpp"
#include "caf/test/dsl.hpp"
#include "caf/actor_system.hpp"
#include "caf/actor_system_config.hpp"
using namespace caf;
namespace {
using value_type = bb::tokenized_integer_reader<>::value_type;
struct fixture {};
} // namespace
CAF_TEST_FIXTURE_SCOPE(tokenized_integer_reader_tests, fixture)
CAF_TEST(int_policy) {
bb::tokenized_integer_reader<value_type> pol;
std::deque<value_type> q;
std::deque<value_type> test{1, 2, 3, 4};
downstream<value_type> out(q);
std::string test_line = "1 2 3 4";
pol(test_line, out);
CAF_CHECK_EQUAL(q, test);
}
CAF_TEST(error_int_policy) {
bb::tokenized_integer_reader<value_type> pol;
std::deque<value_type> q;
downstream<value_type> out(q);
std::string test_line = "1 r 3 4";
auto count = pol(test_line, out);
CAF_CHECK_EQUAL(count.error(),
pec::unexpected_character);
std::string test_line2 = "1 -2247483648 3 4";
count = pol(test_line2, out);
CAF_CHECK_EQUAL(count.error(), pec::exponent_underflow);
std::string test_line3 = "1 2147483648 3 4";
count = pol(test_line3, out);
CAF_CHECK_EQUAL(count.error(), pec::exponent_overflow);
}
CAF_TEST_FIXTURE_SCOPE_END()
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