WIP: sequencer rework

This commit is contained in:
2021-09-26 22:30:36 +03:00
parent fd64d8726c
commit ca38dfa2f1
4 changed files with 694 additions and 372 deletions
+42 -40
View File
@@ -50,10 +50,10 @@ namespace test_bg95_base {
// BG95 implementer mock
template<size_t N>
class BG95 : public BG95_base<BG95<N>, equeue<char, N, true>, N> {
class BG95 : public BG95_base<BG95<N>, N> {
using Q = equeue<char, N, true>;
using base_type = BG95_base<BG95<N>, Q, N>;
using base_type = BG95_base<BG95<N>, N>;
public:
enum class event {
@@ -140,6 +140,11 @@ namespace test_bg95_base {
} while (wait);
return 0;
}
size_t contents(char* data) {
char* nullpos = std::copy(rx_q.begin(), rx_q.end(), data);
*nullpos =0;
return nullpos - data;
}
size_t put (const char* data, size_t n) {
std::cerr << " ";
const char* reply = cmd_responce (data);
@@ -147,9 +152,7 @@ namespace test_bg95_base {
rx_q << *reply++;
return n;
}
const range_t contents() const {
return range_t {rx_q.begin(), rx_q.end()};
}
clock_t clock() { static clock_t t=0; return ++t; }
// extra helper for testing purposes
@@ -179,8 +182,8 @@ namespace test_bg95_base {
char buffer[256];
const BG95<256>::inetd_handlers<2> async = {{
{"+QMTOPEN:", BG95<256>::match_t::STARTS_WITH, handler},
{"+QMT", BG95<256>::match_t::STARTS_WITH, handler},
{"+QMTOPEN:", BG95<256>::starts_with, handler},
{"+QMT", BG95<256>::starts_with, handler},
}};
clear_flag();
@@ -222,39 +225,38 @@ namespace test_bg95_base {
EXPECT_EQ (modem.receive(buffer), 0UL);
}
TEST(TBG95_base, run) {
BG95<256> modem;
using Control = BG95<256>::control_t;
using Match = BG95<256>::match_t;
using Action = BG95<256>::action_t;
const BG95<256>::inetd_handlers<2> async = {{
{"+QMTOPEN:", Match::STARTS_WITH, handler},
{"+QMT", Match::STARTS_WITH, handler},
}};
const BG95<256>::script_t<7> script = {{
{Control::NOP, "", Match::NO, nullptr, {Action::GOTO, 1}, 1000},
{Control::SEND, "ATE0\r\n", Match::NO, nullptr, {Action::NEXT, 0}, 0},
{Control::EXPECT, "OK\r\n", Match::ENDS_WITH, nullptr, {Action::NEXT, 0}, 1000},
{Control::OR_EXPECT,"ERROR", Match::CONTAINS, nullptr, {Action::EXIT_ERROR, 0}, 1000},
{Control::SEND, "AT+CSQ\r\n", Match::NO, nullptr, {Action::NEXT, 0}, 0},
{Control::EXPECT, "OK\r\n", Match::ENDS_WITH, nullptr, {Action::NEXT, 0}, 1000},
{Control::OR_EXPECT,"ERROR", Match::CONTAINS, nullptr, {Action::EXIT_ERROR, 0}, 1000},
}};
std::mutex m;
m.lock();
std::thread th1 ([&](){
do
modem.inetd(false, &async);
while (!m.try_lock());
m.unlock();
});
EXPECT_EQ (modem.run(script), true);
m.unlock(); // stop and join inetd
th1.join();
}
// TEST(TBG95_base, run) {
// BG95<256> modem;
//
// using Control = BG95<256>::control_t;
// using Action = BG95<256>::action_t;
//
// const BG95<256>::inetd_handlers<2> async = {{
// {"+QMTOPEN:", BG95<256>::starts_with, handler},
// {"+QMT", BG95<256>::starts_with, handler},
// }};
// const BG95<256>::script_t<7> script = {{
// {Control::NOP, "", BG95<256>::nil, BG95<256>::nil, {Action::GOTO, 1}, 1000},
// {Control::SEND, "ATE0\r\n", BG95<256>::nil, BG95<256>::nil, {Action::NEXT, 0}, 0},
// {Control::EXPECT, "OK\r\n", BG95<256>::ends_with, BG95<256>::nil, {Action::NEXT, 0}, 1000},
// {Control::OR_EXPECT,"ERROR", BG95<256>::contains, BG95<256>::nil, {Action::EXIT_ERROR, 0}, 0},
// {Control::SEND, "AT+CSQ\r\n",BG95<256>::nil, BG95<256>::nil, {Action::NEXT, 0}, 0},
// {Control::EXPECT, "OK\r\n", BG95<256>::ends_with, BG95<256>::nil, {Action::EXIT_OK, 0}, 1000},
// {Control::OR_EXPECT,"ERROR", BG95<256>::contains, BG95<256>::nil, {Action::EXIT_ERROR, 0}, 0},
// }};
//
// std::mutex m;
// m.lock();
// std::thread th1 ([&](){
// do
// modem.inetd(false, &async);
// while (!m.try_lock());
// m.unlock();
// });
// EXPECT_EQ (modem.run(script), true);
// m.unlock(); // stop and join inetd
// th1.join();
// }
TEST(TBG95_base, command) {
BG95<256> modem;
+358 -64
View File
@@ -29,103 +29,397 @@
#include <utils/sequencer.h>
#include <gtest/gtest.h>
#include <type_traits>
#include <cstring>
#include <ctime>
namespace test_sequencer {
using namespace tbx;
struct seq_cont_t {
const char *msg_[10] = {
"", "", "", "\r\nOK\r\n",
"", "", "+CCLK = \"21/08/26-12:16:30+12\"\r\nOK\r\n"
"", "", "\r\nERROR\r\n"
};
using value_type = char;
using range_t = range<const char*>;
};
seq_cont_t seq_cont;
// test settings
using data_type = char;
constexpr size_t size = 64;
// Sequencer implementer mock
class Seq : public sequencer<Seq, seq_cont_t, char, 128> {
using range_t = typename seq_cont_t::range_t;
class Seq : public sequencer<Seq, data_type, size> {
static constexpr int NrCommands =5;
static constexpr int NoCommand =-1;
std::array<const char*, NrCommands> command = {
"cmd1",
"cmd2\n",
"cmd3\r\n",
"cmd4\n\r",
"cmd5\n",
};
std::array<const char*, NrCommands> reply {
"reply1",
"reply2\n",
"reply3\n text \r text text\n",
"reply4\n text\n text \r text\r\n",
"reply5\n",
};
int cmd =NoCommand;
clock_t t =0;
public:
size_t get(char* data) {
static int msg =0;
size_t len = strlen(seq_cont.msg_[msg]);
strcpy(data, seq_cont.msg_[msg++]);
if (msg >= 10) msg =0;
return len;
static int ans = 0;
if ((++ans % 3) == 0)
return 0;
if (cmd == NoCommand) {
std::strcpy(data, "ERROR\n");
return 6;
} else {
std::strcpy(data, reply[cmd]);
size_t s = std::strlen(reply[cmd]);
cmd =NoCommand;
return s;
}
}
size_t contents (char* data) {
if (cmd == NoCommand) {
std::strcpy(data, "");
return 0;
} else {
std::strcpy(data, reply[cmd]);
return std::strlen(reply[cmd]);
}
}
size_t put (const char* data, size_t n) {
(void)*data;
for (size_t i =0 ; i<NrCommands ; ++i) {
if (!std::strcmp(data, command[i])) {
cmd =i;
return n;
}
}
cmd =NoCommand;
return n;
}
const range_t contents () const {
return range_t {&seq_cont.msg_[6][0], &seq_cont.msg_[6][5]};
}
clock_t clock() { static clock_t t=0; return ++t; }
static void my_handler (const char* data, size_t size) {
(void)*data;
(void)size;
}
clock_t clock() { return ++t; }
void clear_clock() { t =0; }
};
/*
* Test sequencer.run()
* Test sequencer object
*/
TEST(Tsequencer, run_delay) {
TEST (Tsequencer, traits) {
EXPECT_EQ ( std::is_default_constructible<Seq>::value, true);
EXPECT_EQ ( std::is_nothrow_default_constructible<Seq>::value, true);
EXPECT_EQ (!std::is_copy_constructible<Seq>::value, true);
EXPECT_EQ (!std::is_copy_assignable<Seq>::value, true);
EXPECT_EQ ((std::is_same_v<Seq::value_type, data_type>), true);
EXPECT_EQ ((std::is_same_v<Seq::pointer_type, data_type*>), true);
EXPECT_EQ ((std::is_same_v<Seq::size_type, size_t>), true);
EXPECT_EQ ((std::is_same_v<Seq::string_view, std::basic_string_view<data_type>>), true);
Seq s;
const Seq::script_t<1> script = {{
{Seq::control_t::NOP, "", Seq::match_t::NO, nullptr, {Seq::action_t::EXIT_OK, 0}, 1000}
}};
EXPECT_EQ (s.run(script), true);
EXPECT_EQ (s.size(), size);
}
TEST(Tsequencer, run_dummy_output) {
Seq s;
const Seq::script_t<2> script = {{
{Seq::control_t::SEND, "", Seq::match_t::NO, nullptr, {Seq::action_t::NEXT, 0}, 1000},
{Seq::control_t::SEND, "", Seq::match_t::NO, nullptr, {Seq::action_t::EXIT_OK, 0}, 1000}
}};
EXPECT_EQ (s.run(script), true);
TEST (Tsequencer, predicates) {
EXPECT_EQ ((std::is_invocable_r<bool, decltype(Seq::equals), Seq::string_view, Seq::string_view>::value), true);
EXPECT_EQ ((std::is_invocable_r<bool, decltype(Seq::starts_with), Seq::string_view, Seq::string_view>::value), true);
EXPECT_EQ ((std::is_invocable_r<bool, decltype(Seq::ends_with), Seq::string_view, Seq::string_view>::value), true);
EXPECT_EQ ((std::is_invocable_r<bool, decltype(Seq::contains), Seq::string_view, Seq::string_view>::value), true);
EXPECT_EQ ((std::is_invocable_r<bool, decltype(Seq::always_true), Seq::string_view, Seq::string_view>::value), true);
EXPECT_EQ ((std::is_invocable_r<bool, decltype(Seq::always_false), Seq::string_view, Seq::string_view>::value), true);
EXPECT_EQ (Seq::nil, nullptr);
}
TEST(Tsequencer, run_exits) {
TEST (Tsequencer, actions) {
EXPECT_EQ ( std::is_default_constructible<Seq::action_t>::value, true);
EXPECT_EQ ( std::is_nothrow_default_constructible<Seq::action_t>::value, true);
EXPECT_EQ ( std::is_copy_constructible<Seq::action_t>::value, true);
EXPECT_EQ ( std::is_copy_assignable<Seq::action_t>::value, true);
EXPECT_EQ ((std::is_same_v<const Seq::action_t, decltype(Seq::no_action)>), true);
EXPECT_EQ ((std::is_same_v<const Seq::action_t, decltype(Seq::next)>), true);
EXPECT_EQ ((std::is_same_v<const Seq::action_t, decltype(Seq::exit_ok)>), true);
EXPECT_EQ ((std::is_same_v<const Seq::action_t, decltype(Seq::exit_error)>), true);
EXPECT_EQ ((std::is_same_v<const Seq::action_t, decltype(Seq::go_to<0>)>), true);
EXPECT_EQ ((std::is_same_v<const Seq::action_t, decltype(Seq::exit<0>)>), true);
}
bool handler_flag = false;
const char* text = "abc";
//static bool check_handle (const str_view_t buffer, const str_view_t token, match_ft match, handler_ft handle)
TEST(Tsequencer, check_handle) {
Seq s;
// foo (5);
// bar (5);
using str_t = Seq::string_view;
using val_t = Seq::value_type;
auto match = [](const str_t x, const str_t y) ->bool { (void)x; (void)y; return true; };
auto no_match = [](const str_t x, const str_t y) ->bool { (void)x; (void)y; return false; };
auto check_match = [] (const str_t x, const str_t y) ->bool {
return x == y;
};
auto handler = [](const val_t* v, size_t s){ (void)*v; (void)s; handler_flag = true; };
auto set_if_abc = [](const val_t* v, size_t s){
(void)*v; (void)s;
handler_flag = (str_t(v, s) == "abc");
};
EXPECT_EQ (s.check_handle("", "", nullptr, nullptr), false);
EXPECT_EQ (s.check_handle("", "", no_match, nullptr), false);
EXPECT_EQ (s.check_handle("", "", match, nullptr), false);
handler_flag = false;
EXPECT_EQ (s.check_handle("", "", no_match, handler), false);
EXPECT_EQ (handler_flag, false);
handler_flag = false;
EXPECT_EQ (s.check_handle("", "", match, handler), true);
EXPECT_EQ (handler_flag, true);
handler_flag = false;
EXPECT_EQ (s.check_handle("abcd", "abc", check_match, set_if_abc), false);
EXPECT_EQ (handler_flag, false);
handler_flag = false;
EXPECT_EQ (s.check_handle("abc", "abc", check_match, set_if_abc), true);
EXPECT_EQ (handler_flag, true);
handler_flag = false;
EXPECT_EQ (s.check_handle("abc", "abcd", check_match, set_if_abc), false);
EXPECT_EQ (handler_flag, false);
}
TEST(Tsequencer, run_nop_and_exits) {
Seq s;
const Seq::script_t<1> script1 = {{
{Seq::control_t::SEND, "", Seq::match_t::NO, nullptr, {Seq::action_t::EXIT_OK, 0}, 1000},
{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::exit_ok, 1000}
}};
EXPECT_EQ (s.run(script1), true);
s.clear_clock();
EXPECT_EQ (s.run(script1), Seq::exit_ok.value);
EXPECT_GE (s.clock(), (clock_t)1000);
const Seq::script_t<1> script2 = {{
{Seq::control_t::SEND, "", Seq::match_t::NO, nullptr, {Seq::action_t::EXIT_ERROR, 0}, 1000},
{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::exit_error, 1000}
}};
EXPECT_EQ (s.run(script2), false);
s.clear_clock();
EXPECT_EQ (s.run(script2), Seq::exit_error.value);
EXPECT_GE (s.clock(), (clock_t)1000);
const Seq::script_t<3> script3 = {{
{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::next, 1000},
{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::next, 1000},
{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::exit_ok, 1000}
}};
s.clear_clock();
EXPECT_EQ (s.run(script3), Seq::exit_ok.value);
EXPECT_GE (s.clock(), (clock_t)3000);
}
TEST(Tsequencer, run_sequence) {
TEST(Tsequencer, run_send) {
Seq s;
const Seq::script_t<13> script = {{
/* 0 */{Seq::control_t::NOP, "", Seq::match_t::NO, nullptr, {Seq::action_t::GOTO, 1}, 1000},
/* 1 */{Seq::control_t::SEND, "ATE0\r\n", Seq::match_t::NO, nullptr, {Seq::action_t::NEXT, 0}, 1000},
/* 2 */{Seq::control_t::EXPECT, "OK\r\n", Seq::match_t::ENDS_WITH, nullptr, {Seq::action_t::NEXT, 0}, 1000},
/* 3 */{Seq::control_t::OR_EXPECT, "ERROR", Seq::match_t::CONTAINS, nullptr, {Seq::action_t::EXIT_ERROR, 0}, 1000},
auto send_wrapper = [](const data_type* d, size_t s){
(void)*d; (void)s; handler_flag = true;
};
auto send_chk_text = [](const data_type* d, size_t s){
handler_flag = (Seq::string_view(d,s) == Seq::string_view(text));
};
/* 4 */{Seq::control_t::DETECT, "+CCLK", Seq::match_t::CONTAINS, nullptr, {Seq::action_t::NEXT, 0}, 1000},
/* 5 */{Seq::control_t::OR_DETECT, "ERROR", Seq::match_t::CONTAINS, nullptr, {Seq::action_t::EXIT_ERROR, 0}, 1000},
/* 6 */{Seq::control_t::SEND, "AT+CCLK?", Seq::match_t::NO, nullptr, {Seq::action_t::NEXT, 0}, 1000},
/* 7 */{Seq::control_t::EXPECT, "OK\r\n", Seq::match_t::ENDS_WITH, Seq::my_handler, {Seq::action_t::NEXT, 0}, 1000},
/* 8 */{Seq::control_t::OR_EXPECT, "ERROR", Seq::match_t::CONTAINS, nullptr, {Seq::action_t::EXIT_ERROR, 0}, 1000},
/* 9 */{Seq::control_t::SEND, "AT+CT?", Seq::match_t::NO, nullptr, {Seq::action_t::NEXT, 0}, 1000},
/*10 */{Seq::control_t::EXPECT, "OK\r\n", Seq::match_t::ENDS_WITH, nullptr, {Seq::action_t::NEXT, 0}, 1000},
/*11 */{Seq::control_t::OR_EXPECT, "ERROR", Seq::match_t::CONTAINS, nullptr, {Seq::action_t::EXIT_ERROR, 0}, 1000},
/*12 */{Seq::control_t::SEND, "AT+POWD=0", Seq::match_t::NO, nullptr, {Seq::action_t::EXIT_OK, 0}, 1000}
const Seq::script_t<2> script1 = {{
{Seq::control_t::SEND, "", Seq::nil, Seq::nil, Seq::next, 0},
{Seq::control_t::SEND, "", Seq::nil, send_wrapper, Seq::exit_ok, 0}
}};
EXPECT_EQ (s.run(script), false);
handler_flag =false;
EXPECT_EQ (s.run(script1), Seq::exit_ok.value);
EXPECT_EQ (handler_flag, true);
const Seq::script_t<1> script2 = {{
{Seq::control_t::SEND, "abcd", Seq::nil, send_chk_text, Seq::exit_ok, 0}
}};
handler_flag =false;
EXPECT_EQ (s.run(script2), Seq::exit_ok.value);
EXPECT_EQ (handler_flag, false);
const Seq::script_t<2> script3 = {{
{Seq::control_t::SEND, text, Seq::nil, send_chk_text, Seq::exit_ok, 0}
}};
handler_flag =false;
EXPECT_EQ (s.run(script3), Seq::exit_ok.value);
EXPECT_EQ (handler_flag, true);
}
TEST(Tsequencer, run_expect) {
Seq s;
const Seq::script_t<7> script = {{
{Seq::control_t::EXPECT, "reply1", Seq::equals, Seq::nil, Seq::exit<1UL>, 1000},
{Seq::control_t::OR_EXPECT, "reply2", Seq::starts_with, Seq::nil, Seq::exit<2UL>, 0},
{Seq::control_t::OR_EXPECT, "reply3", Seq::starts_with, Seq::nil, Seq::exit<3UL>, 0},
{Seq::control_t::OR_EXPECT, "reply4\n", Seq::starts_with, Seq::nil, Seq::exit<4UL>, 0},
{Seq::control_t::OR_EXPECT, "reply5", Seq::starts_with, Seq::nil, Seq::exit<5UL>, 0},
{Seq::control_t::OR_EXPECT, "ERROR", Seq::contains, Seq::nil, Seq::exit<6UL>, 0},
{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::exit_error, 1000}
}};
s.clear_clock();
s.put("cmd1", std::strlen("cmd1"));
EXPECT_EQ (s.run(script), 1UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd2\n", std::strlen("cmd2\n"));
EXPECT_EQ (s.run(script), 2UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd3\r\n", std::strlen("cmd3\r\n"));
EXPECT_EQ (s.run(script), 3UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd4\n\r", std::strlen("cmd4\n\r"));
EXPECT_EQ (s.run(script), 4UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd5\n", std::strlen("cmd5\n"));
EXPECT_EQ (s.run(script), 5UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd", std::strlen("cmd"));
EXPECT_EQ (s.run(script), 6UL);
EXPECT_LT (s.clock(), (clock_t)1000);
}
TEST(Tsequencer, run_detect) {
Seq s;
const Seq::script_t<7> script = {{
{Seq::control_t::DETECT, "reply1", Seq::equals, Seq::nil, Seq::exit<1UL>, 1000},
{Seq::control_t::OR_DETECT, "reply2", Seq::starts_with, Seq::nil, Seq::exit<2UL>, 0},
{Seq::control_t::OR_DETECT, "reply3", Seq::starts_with, Seq::nil, Seq::exit<3UL>, 0},
{Seq::control_t::OR_DETECT, "reply4\n", Seq::starts_with, Seq::nil, Seq::exit<4UL>, 0},
{Seq::control_t::OR_DETECT, "reply5", Seq::starts_with, Seq::nil, Seq::exit<5UL>, 0},
{Seq::control_t::OR_DETECT, "ERROR", Seq::contains, Seq::nil, Seq::exit<6UL>, 0},
{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::exit_ok, 1000}
}};
s.clear_clock();
s.put("cmd1", std::strlen("cmd1"));
EXPECT_EQ (s.run(script), 1UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd2\n", std::strlen("cmd2\n"));
EXPECT_EQ (s.run(script), 2UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd3\r\n", std::strlen("cmd3\r\n"));
EXPECT_EQ (s.run(script), 3UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd4\n\r", std::strlen("cmd4\n\r"));
EXPECT_EQ (s.run(script), 4UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd5\n", std::strlen("cmd5\n"));
EXPECT_EQ (s.run(script), 5UL);
EXPECT_LT (s.clock(), (clock_t)1000);
s.clear_clock();
s.put("cmd", std::strlen("cmd"));
EXPECT_EQ (s.run(script), Seq::exit_error.value);
EXPECT_GT (s.clock(), (clock_t)1000);
}
TEST(Tsequencer, run_script_blocks_n_gotos) {
Seq s;
const Seq::script_t<15> script = {{
/* 0 */{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::go_to<1>, 1000},
/* 1 */{Seq::control_t::SEND, "cmd1", Seq::nil, Seq::nil, Seq::next, 0},
/* 2 */{Seq::control_t::EXPECT, "reply1", Seq::starts_with, Seq::nil, Seq::next, 1000},
/* 3 */{Seq::control_t::OR_EXPECT, "ERROR", Seq::contains, Seq::nil, Seq::exit_error, 0},
/* 4 */{Seq::control_t::SEND, "cmd2\n", Seq::nil, Seq::nil, Seq::next, 0},
/* 5 */{Seq::control_t::DETECT, "ERROR", Seq::contains, Seq::nil, Seq::exit_error, 1000},
/* 6 */{Seq::control_t::OR_DETECT, "reply2", Seq::contains, Seq::nil, Seq::go_to<11>, 0},
/* 7 */{Seq::control_t::SEND, "cmd3\r\n", Seq::nil, Seq::nil, Seq::next, 0},
/* 8 */{Seq::control_t::EXPECT, "ERROR", Seq::contains, Seq::nil, Seq::exit_error, 1000},
/* 9 */{Seq::control_t::OR_EXPECT, "lalala", Seq::starts_with, Seq::nil, Seq::exit_error, 0},
/*10 */{Seq::control_t::OR_EXPECT, "text\n", Seq::ends_with, Seq::nil, Seq::go_to<14>, 0},
/*11 */{Seq::control_t::SEND, "cmd4\n\r", Seq::nil, Seq::nil, Seq::next, 0},
/*12 */{Seq::control_t::EXPECT, "reply4\n", Seq::starts_with, Seq::nil, Seq::go_to<7>, 1000},
/*13 */{Seq::control_t::OR_EXPECT, "ERROR", Seq::contains, Seq::nil, Seq::exit_error, 0},
/*14 */{Seq::control_t::NOP, "", Seq::nil, Seq::nil, Seq::exit_ok, 1000}
}};
s.clear_clock();
EXPECT_EQ (s.run(script), Seq::exit_ok.value);
EXPECT_GT (s.clock(), (clock_t)2000);
}
TEST(Tsequencer, run_match_n_handler) {
Seq s;
using str_t = Seq::string_view;
using val_t = Seq::value_type;
auto match = [](const str_t x, const str_t y) ->bool { (void)x; (void)y; return true; };
auto check_match = [] (const str_t x, const str_t y) ->bool {
return x == y;
};
auto handler = [](const val_t* v, size_t s){ (void)*v; (void)s; handler_flag = true; };
auto set_if_rpl2 = [](const val_t* v, size_t s){
(void)*v; (void)s;
handler_flag = (str_t(v, s) == "reply2\n");
};
const Seq::script_t<4> script1 = {{
{Seq::control_t::SEND, "cmd1", Seq::nil, Seq::nil, Seq::next, 0},
{Seq::control_t::EXPECT, "", match, Seq::nil, Seq::next, 1000},
{Seq::control_t::OR_EXPECT, "ERROR", Seq::contains, Seq::nil, Seq::exit_error, 0},
{Seq::control_t::SEND, "cmd1", Seq::nil, handler, Seq::exit_ok, 0}
}};
handler_flag = false;
s.clear_clock();
EXPECT_EQ (s.run(script1), Seq::exit_ok.value);
EXPECT_LT (s.clock(), (clock_t)1000);
EXPECT_EQ (handler_flag, true);
const Seq::script_t<2> script2 = {{
{Seq::control_t::SEND, "cmd1", Seq::nil, Seq::nil, Seq::next, 0},
{Seq::control_t::EXPECT, "reply1", check_match, set_if_rpl2, Seq::exit_ok, 1000},
}};
handler_flag = false;
EXPECT_EQ (s.run(script2), Seq::exit_ok.value);
EXPECT_EQ (handler_flag, false);
const Seq::script_t<2> script3 = {{
{Seq::control_t::SEND, "cmd2\n", Seq::nil, Seq::nil, Seq::next, 0},
{Seq::control_t::EXPECT, "reply2\n", check_match, set_if_rpl2, Seq::exit_ok, 1000},
}};
handler_flag = false;
EXPECT_EQ (s.run(script3), Seq::exit_ok.value);
EXPECT_EQ (handler_flag, true);
const Seq::script_t<1> script4 = {{
{Seq::control_t::SEND, "cmd1", Seq::nil, handler, Seq::exit_ok, 0}
}};
handler_flag = false;
EXPECT_EQ (s.run(script4), Seq::exit_ok.value);
EXPECT_EQ (handler_flag, true);
}
}