2016-04-05 11:06:01 +10:00
|
|
|
#include "tap.hpp"
|
|
|
|
#include "string.hpp"
|
|
|
|
#include "types.hpp"
|
2017-09-15 15:22:29 +10:00
|
|
|
#include "iterator.hpp"
|
|
|
|
|
|
|
|
#include <vector>
|
2016-03-17 18:13:19 +11:00
|
|
|
|
2017-11-22 17:03:00 +11:00
|
|
|
|
2018-10-17 11:48:03 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
|
|
test_position (cruft::TAP::logger &tap)
|
|
|
|
{
|
|
|
|
char const *string = "a\nb\nc\n";
|
|
|
|
|
|
|
|
struct {
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
int line;
|
|
|
|
int column;
|
|
|
|
} TESTS[] = {
|
|
|
|
{ 0, 0, 0 },
|
|
|
|
{ 1, 1, -1 },
|
|
|
|
{ 2, 1, 0 },
|
|
|
|
{ 3, 2, -1 },
|
|
|
|
{ 4, 2, 0 },
|
|
|
|
{ 5, 3, -1 },
|
|
|
|
};
|
|
|
|
|
|
|
|
for (auto const &t: TESTS) {
|
|
|
|
auto const pos = cruft::character_position ({string, strlen(string) }, string + t.offset);
|
|
|
|
|
|
|
|
tap.expect (
|
|
|
|
pos.line == t.line && pos.column == t.column,
|
|
|
|
"character_position %!:%!",
|
|
|
|
t.line,
|
|
|
|
t.column
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-16 18:06:45 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
|
|
test_tokeniser (cruft::TAP::logger &tap)
|
|
|
|
{
|
2017-11-22 17:03:00 +11:00
|
|
|
// the string_literal prefix is required to (easily) construct a string
|
|
|
|
// with an internal null character.
|
|
|
|
using namespace std::literals::string_literals;
|
|
|
|
const std::string csv = "\0,a,123,,this is a test,"s;
|
|
|
|
|
2017-09-15 15:22:29 +10:00
|
|
|
// expected test data must be a std::string so we can check embedded
|
|
|
|
// nulls (which are ambiguous when using a cstr).
|
|
|
|
struct foo {
|
|
|
|
const std::string value;
|
|
|
|
const char *message;
|
|
|
|
} TESTS[] = {
|
2017-11-23 17:24:11 +11:00
|
|
|
{ "\0"s, "null" },
|
2017-09-15 15:22:29 +10:00
|
|
|
{ "a", "single letter" },
|
|
|
|
{ "123", "three digits" },
|
|
|
|
{ "", "empty string" },
|
|
|
|
{ "this is a test", "string with spaces" },
|
|
|
|
{ "", "trailing empty" }
|
2016-03-17 18:13:19 +11:00
|
|
|
};
|
|
|
|
|
2018-08-05 14:42:02 +10:00
|
|
|
cruft::view src { csv.c_str (), csv.size () };
|
|
|
|
for (auto [tok, expected]: cruft::zip (cruft::tokeniser (src, ','), TESTS)) {
|
2018-01-31 19:33:42 +11:00
|
|
|
tap.expect (equal (tok, expected.value), "%s", expected.message);
|
2018-03-27 15:49:47 +11:00
|
|
|
}
|
2018-10-16 18:06:45 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-20 14:44:33 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
|
|
test_contains (cruft::TAP::logger &tap)
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
char const *haystack;
|
2019-02-20 15:51:54 +11:00
|
|
|
char separator;
|
2019-02-20 14:44:33 +11:00
|
|
|
char const *needle;
|
|
|
|
bool expected;
|
|
|
|
char const *message;
|
|
|
|
} const TESTS[] = {
|
2019-02-20 15:51:54 +11:00
|
|
|
{
|
|
|
|
.haystack = "foo",
|
|
|
|
.separator = ',',
|
|
|
|
.needle = "foo",
|
|
|
|
.expected = true,
|
|
|
|
.message = "needle is haystack"
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
.haystack = "",
|
|
|
|
.separator = ',',
|
|
|
|
.needle = "foo",
|
|
|
|
.expected = false,
|
|
|
|
.message = "haystack is empty",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
.haystack = "foo",
|
|
|
|
.separator = ',',
|
|
|
|
.needle = "",
|
|
|
|
.expected = false,
|
|
|
|
.message = "needle is empty",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
.haystack = "a,b,foo",
|
|
|
|
.separator = ',',
|
|
|
|
.needle = "foo",
|
|
|
|
.expected = true,
|
|
|
|
.message = "needle is last",
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
.haystack = "foo,b,c",
|
|
|
|
.separator = ',',
|
|
|
|
.needle = "foo",
|
|
|
|
.expected = true,
|
|
|
|
.message = "needle is first",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.haystack = "foo,b,c",
|
|
|
|
.separator = ';',
|
|
|
|
.needle = "foo",
|
|
|
|
.expected = false,
|
|
|
|
.message = "separator is mismatched",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.haystack = "a;b;foo",
|
|
|
|
.separator = ';',
|
|
|
|
.needle = "foo",
|
|
|
|
.expected = true,
|
|
|
|
.message = "separator isn't default"
|
|
|
|
}
|
2019-02-20 14:44:33 +11:00
|
|
|
};
|
2019-02-20 15:51:54 +11:00
|
|
|
|
|
|
|
for (auto const &t: TESTS) {
|
|
|
|
cruft::tokeniser tok (t.haystack, t.separator);
|
|
|
|
auto const found = tok.contains (t.needle);
|
|
|
|
tap.expect_eq (found, t.expected, "%!", t.message);
|
|
|
|
}
|
2019-02-20 14:44:33 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-16 18:06:45 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
int
|
|
|
|
main (int, char**)
|
|
|
|
{
|
|
|
|
cruft::TAP::logger tap;
|
|
|
|
|
|
|
|
test_tokeniser (tap);
|
2018-10-17 11:48:03 +11:00
|
|
|
test_position (tap);
|
2019-02-20 14:44:33 +11:00
|
|
|
test_contains (tap);
|
2016-03-17 18:13:19 +11:00
|
|
|
|
|
|
|
return tap.status ();
|
2018-01-30 11:31:40 +11:00
|
|
|
}
|