Skip to content
Snippets Groups Projects
Commit db92e549 authored by Leon Dietrich's avatar Leon Dietrich Committed by Benny Baumann
Browse files

add: Basic connection_line_buffer test

parent 86e28885
No related branches found
No related tags found
1 merge request!1First unit tests
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
namespace rmrf::net { namespace rmrf::net {
static std::string::size_type default_eol_search( std::string::size_type default_eol_search(
const std::string &data, const std::string &data,
std::string::size_type start_position std::string::size_type start_position
) { ) {
...@@ -50,7 +50,10 @@ connection_line_buffer::connection_line_buffer( ...@@ -50,7 +50,10 @@ connection_line_buffer::connection_line_buffer(
max(max_line_size), max(max_line_size),
data("") data("")
{ {
this->client->set_incomming_data_callback(std::bind(&connection_line_buffer::conn_data_in_cb, this, std::placeholders::_1)); this->client->set_incomming_data_callback(
[this](const std::string& data_in) {
conn_data_in_cb(data_in);
});
} }
connection_line_buffer::connection_line_buffer( connection_line_buffer::connection_line_buffer(
...@@ -63,26 +66,27 @@ connection_line_buffer::connection_line_buffer( ...@@ -63,26 +66,27 @@ connection_line_buffer::connection_line_buffer(
void connection_line_buffer::conn_data_in_cb(const std::string &data_in) { void connection_line_buffer::conn_data_in_cb(const std::string &data_in) {
/** // Iterate throug the incomming data as long as we find line breaks
* Known limitation: If the last received data ends with '\r' and the next incoming data would start with '\n' there is no way for (std::string::size_type strpos = 0, nextpos = -1; strpos != std::string::npos; strpos = nextpos++) {
* to detect this as the received message might indeed be a complete one ending with '\r' and one cannot wait for a potential // Search for the next line break
* continuation of said message to arrive. nextpos = this->search(data_in, strpos);
*/
std::string::size_type strpos = 0; // Advance, if the line would be empty
if (nextpos == strpos) {
while (strpos != std::string::npos) { nextpos = this->search(data_in, ++strpos);
std::string::size_type nextpos = this->search(data_in, strpos); }
if (nextpos == std::string::npos) { if (nextpos == std::string::npos) {
// If we didn't find one we store the remaining data in the buffer
this->data += data_in.substr(strpos, data_in.length() - strpos); this->data += data_in.substr(strpos, data_in.length() - strpos);
break; break;
} else { } else {
this->found_next_line_cb(this->data + data_in.substr(strpos, nextpos - strpos), true); // If we find one we send the buffer plus the incomming data up to the line break to the callback
const std::string data_to_send = this->data + data_in.substr(strpos, nextpos - strpos);
this->found_next_line_cb(data_to_send, true);
// and clear the buffer
this->data = std::string(""); this->data = std::string("");
} }
strpos = nextpos;
} }
if (this->data.length() > this->max) { if (this->data.length() > this->max) {
......
...@@ -17,7 +17,7 @@ namespace rmrf::net { ...@@ -17,7 +17,7 @@ namespace rmrf::net {
typedef std::function<std::string::size_type(const std::string&, std::string::size_type)> eol_search_t; typedef std::function<std::string::size_type(const std::string&, std::string::size_type)> eol_search_t;
static std::string::size_type default_eol_search(const std::string& data, std::string::size_type start_position); std::string::size_type default_eol_search(const std::string& data, std::string::size_type start_position);
class connection_line_buffer { class connection_line_buffer {
public: public:
...@@ -31,7 +31,7 @@ private: ...@@ -31,7 +31,7 @@ private:
std::string data; std::string data;
public: public:
connection_line_buffer(std::shared_ptr<connection_client> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size, eol_search_t search_lb = default_eol_search); connection_line_buffer(std::shared_ptr<connection_client> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size, eol_search_t search_lb);
connection_line_buffer(std::shared_ptr<connection_client> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size); connection_line_buffer(std::shared_ptr<connection_client> c, found_next_line_cb_t found_next_line_cb_, std::string::size_type max_line_size);
private: private:
......
#define BOOST_AUTO_TEST_MAIN
#define BOOST_TEST_MODULE RMRF_TESTS
#include <boost/test/included/unit_test.hpp>
#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include "loopback_connection_client.hpp"
#include "net/connection_line_buffer.hpp"
using namespace rmrf::net;
using namespace rmrf::test;
//BOOST_AUTO_TEST_SUITE( LINE_BUFFER )
int mut_send_stage = 0;
bool extra_failed = false;
const bool display_dbg_msg = false;
void mut_send_data_cb(const std::string& data) {
std::cout << "This method should never have been called yet we've got:" << std::endl;
std::cout << data << std::endl;
BOOST_CHECK(false);
}
void next_line_cb(const std::string& data, bool complete) {
if constexpr (display_dbg_msg) std::cout << mut_send_stage << ": " << data << std::endl;
switch (mut_send_stage++) {
case 0:
BOOST_CHECK_EQUAL(data, "The first line");
BOOST_CHECK(complete);
break;
case 1:
BOOST_CHECK_EQUAL(data, "The second line");
BOOST_CHECK(complete);
break;
case 2:
BOOST_CHECK_EQUAL(data, "The third line");
BOOST_CHECK(complete);
break;
case 3:
BOOST_CHECK_EQUAL(data.length(), 151);
BOOST_CHECK(!complete);
BOOST_CHECK(std::find_if(data.cbegin(), data.cend(), [](char c) {
return c != 'a';
}) == data.cend());
break;
default:
extra_failed = true;
}
}
BOOST_AUTO_TEST_CASE(Default_EoL_Search_Test) {
BOOST_CHECK_EQUAL(default_eol_search("This line contains no line break", 0), std::string::npos);
std::string data = "This\r line contains line\r\n breaks";
BOOST_CHECK_EQUAL(default_eol_search(data, 0), 4);
BOOST_CHECK_EQUAL(data.substr(0, 4), "This");
BOOST_CHECK_EQUAL(default_eol_search(data, 5), 25);
BOOST_CHECK_EQUAL(data.substr(5, 25 - 5), " line contains line\r");
}
BOOST_AUTO_TEST_CASE(Connection_Line_Buffer_Test) {
mut_send_stage = 0;
auto ll_client = std::make_shared<loopback_connection_client>(mut_send_data_cb, false);
connection_line_buffer clb(ll_client, next_line_cb, 150);
if constexpr (display_dbg_msg) std::cout << "Testing legit lines" << std::endl;
ll_client->send_data_to_incomming_data_cb("The first");
ll_client->send_data_to_incomming_data_cb(" line\r");
ll_client->send_data_to_incomming_data_cb("The second line\r");
ll_client->send_data_to_incomming_data_cb("\nThe third line\n");
if constexpr (display_dbg_msg) std::cout << "Testing line overflow" << std::endl;
for (int i = 0; i < 151; i++) {
ll_client->send_data_to_incomming_data_cb("a");
}
BOOST_CHECK_EQUAL(mut_send_stage, 4);
BOOST_CHECK(!extra_failed);
}
//BOOST_AUTO_TEST_SUITE_END()
...@@ -14,6 +14,7 @@ class loopback_connection_client : public rmrf::net::connection_client { ...@@ -14,6 +14,7 @@ class loopback_connection_client : public rmrf::net::connection_client {
private: private:
const rmrf::net::connection_client::incomming_data_cb send_data_cb; const rmrf::net::connection_client::incomming_data_cb send_data_cb;
std::vector<std::string> data_archive; std::vector<std::string> data_archive;
const bool echo_data_transfer;
public: public:
/** /**
...@@ -21,11 +22,13 @@ public: ...@@ -21,11 +22,13 @@ public:
* send data. * send data.
*/ */
loopback_connection_client( loopback_connection_client(
rmrf::net::connection_client::incomming_data_cb send_data_cb_ rmrf::net::connection_client::incomming_data_cb send_data_cb_,
bool echo_data
) : ) :
rmrf::net::connection_client{}, rmrf::net::connection_client{},
send_data_cb(send_data_cb_), send_data_cb(send_data_cb_),
data_archive{} data_archive{},
echo_data_transfer(echo_data)
{ {
// Does nothing special // Does nothing special
} }
...@@ -43,7 +46,12 @@ public: ...@@ -43,7 +46,12 @@ public:
*/ */
virtual void write_data(const std::string& data) { virtual void write_data(const std::string& data) {
// TODO fixme // TODO fixme
if (this->echo_data_transfer) {
std::cout << "<-- " << data << std::endl;
}
this->data_archive.push_back(data); this->data_archive.push_back(data);
if (this->send_data_cb) { if (this->send_data_cb) {
this->send_data_cb(data); this->send_data_cb(data);
} }
...@@ -56,6 +64,10 @@ public: ...@@ -56,6 +64,10 @@ public:
* @param data The data to send. * @param data The data to send.
*/ */
void send_data_to_incomming_data_cb(const std::string& data) { void send_data_to_incomming_data_cb(const std::string& data) {
if (this->echo_data_transfer) {
std::cout << "--> " << data << std::endl;
}
if (this->in_data_cb) { if (this->in_data_cb) {
this->in_data_cb(data); this->in_data_cb(data);
} }
...@@ -67,6 +79,10 @@ public: ...@@ -67,6 +79,10 @@ public:
std::vector<std::string> get_send_data() { std::vector<std::string> get_send_data() {
return this->data_archive; return this->data_archive;
} }
void clear_sent_data() {
this->data_archive.clear();
}
}; };
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment