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 @@
#pragma once
#include "tokenized_integer_reader.hpp"
#include <string>
#include <vector>
......@@ -56,11 +54,11 @@ struct stream_reader_state {
/// Gives this actor a useful name in CAF logs.
const char* name;
/// Stream
/// Stream we are about to stream
// TODO: change after having raised the minimum GCC version to 5.
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;
};
......
......@@ -18,6 +18,8 @@
#pragma once
#include <cstdint>
#include <limits>
#include <string>
#include <vector>
......@@ -26,19 +28,11 @@
#include "caf/stateful_actor.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/unit.hpp"
#include "caf/pec.hpp"
namespace caf {
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
/// integers.
template <class ValueType = int32_t>
......@@ -56,11 +50,19 @@ public:
char* end = nullptr;
auto value = strtoll(i, &end, 10);
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;
out.push(value);
// TODO: check whether value fits into value_type
// Advance iterator.
i = end;
while (isspace(*i))
......
......@@ -19,6 +19,7 @@
#define CAF_SUITE stream_reader
#include "caf/bb/stream_reader.hpp"
#include "caf/bb/tokenized_integer_reader.hpp"
#include "caf/test/dsl.hpp"
......@@ -57,7 +58,13 @@ TESTEE(stream_reader_sink) {
self->state.vec.emplace_back(std::move(val));
},
// 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) {
TESTEE(stream_monitor) {
self->set_down_handler([=](const down_msg& dm) {
CAF_CHECK_EQUAL(dm.source, self->state.streamer);
if (dm.reason)
CAF_CHECK_EQUAL(dm.reason,
pec::unexpected_character);
});
return {[=](join_atom, actor streamer) {
......@@ -88,27 +98,17 @@ using fixture = test_coordinator_fixture<config>;
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) {
scoped_actor self{sys};
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{
new std::istringstream(test_stringvalues)};
std::unique_ptr<stream_type> ptr_test_stream{
new stream_type(test_stringvalues)};
std::vector<value_type> test_container{1, 2, 3, 4, 5, 6, 7, 78,
1254, 1, 20, 4, 56, 78, 95};
auto sink = sys.spawn(stream_reader_sink);
auto src
= sys.spawn(bb::stream_reader<bb::tokenized_integer_reader<value_type>,
std::istringstream, actor>,
stream_type, actor>,
std::move(ptr_test_stream), sink);
auto mon = sys.spawn(stream_monitor);
self->send(mon, join_atom::value, src);
......@@ -120,8 +120,8 @@ CAF_TEST(stream_to_sink) {
CAF_TEST(stream_to_sinks) {
scoped_actor self{sys};
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{
new std::istringstream(test_stringvalues)};
std::unique_ptr<stream_type> ptr_test_stream{
new stream_type(test_stringvalues)};
std::vector<value_type> test_container{1, 2, 3, 4, 5, 6, 7, 78,
1254, 1, 20, 4, 56, 78, 95};
auto snk1 = sys.spawn(stream_reader_sink);
......@@ -129,7 +129,7 @@ CAF_TEST(stream_to_sinks) {
auto snk3 = sys.spawn(stream_reader_sink);
auto src
= 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);
auto mon = sys.spawn(stream_monitor);
self->send(mon, join_atom::value, src);
......@@ -142,4 +142,19 @@ CAF_TEST(stream_to_sinks) {
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()
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| 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