2021-01-23 21:39:18 +01:00
|
|
|
#include "test_helpers.hpp"
|
2020-12-10 19:26:56 +01:00
|
|
|
#include <algorithm>
|
2021-01-23 21:39:18 +01:00
|
|
|
#include <ss/extract.hpp>
|
2021-01-21 01:29:07 +01:00
|
|
|
|
2024-02-26 02:37:30 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct numeric_limits : public std::numeric_limits<T> {};
|
|
|
|
|
2024-02-25 17:46:35 +01:00
|
|
|
template <typename T>
|
2024-02-26 02:37:30 +01:00
|
|
|
struct numeric_limits<ss::numeric_wrapper<T>> : public std::numeric_limits<T> {
|
|
|
|
};
|
2024-02-25 17:46:35 +01:00
|
|
|
|
|
|
|
template <typename T>
|
2024-02-26 02:37:30 +01:00
|
|
|
struct is_signed : public std::is_signed<T> {};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct is_signed<ss::int8> : public std::true_type {};
|
2024-02-25 17:46:35 +01:00
|
|
|
|
|
|
|
template <typename T>
|
2024-02-26 02:37:30 +01:00
|
|
|
struct is_unsigned : public std::is_unsigned<T> {};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct is_unsigned<ss::uint8> : public std::true_type {};
|
|
|
|
|
2024-03-12 10:22:10 +01:00
|
|
|
} /* anonymous namespace */
|
2024-02-26 02:37:30 +01:00
|
|
|
|
|
|
|
static_assert(is_signed<ss::int8>::value);
|
|
|
|
static_assert(is_unsigned<ss::uint8>::value);
|
2024-02-25 17:46:35 +01:00
|
|
|
|
2020-12-10 19:26:56 +01:00
|
|
|
TEST_CASE("testing extract functions for floating point values") {
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_FLOATING_CONVERSION(123.456, float);
|
|
|
|
CHECK_FLOATING_CONVERSION(123.456, double);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2023-08-05 12:05:17 +02:00
|
|
|
CHECK_FLOATING_CONVERSION(59, float);
|
|
|
|
CHECK_FLOATING_CONVERSION(59, double);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2023-08-05 12:05:17 +02:00
|
|
|
CHECK_FLOATING_CONVERSION(4210., float);
|
|
|
|
CHECK_FLOATING_CONVERSION(4210., double);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_FLOATING_CONVERSION(0.123, float);
|
|
|
|
CHECK_FLOATING_CONVERSION(0.123, double);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_FLOATING_CONVERSION(123e4, float);
|
|
|
|
CHECK_FLOATING_CONVERSION(123e4, double);
|
2020-12-10 19:26:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#define CHECK_DECIMAL_CONVERSION(input, type) \
|
2020-12-26 00:46:42 +01:00
|
|
|
{ \
|
|
|
|
std::string s = #input; \
|
2024-02-25 17:46:35 +01:00
|
|
|
type value; \
|
|
|
|
bool valid = ss::extract(s.c_str(), s.c_str() + s.size(), value); \
|
|
|
|
REQUIRE(valid); \
|
|
|
|
CHECK_EQ(value, type(input)); \
|
2020-12-26 00:46:42 +01:00
|
|
|
} \
|
2024-02-25 17:46:35 +01:00
|
|
|
/* check negative too */ \
|
2024-02-26 02:37:30 +01:00
|
|
|
if (is_signed<type>::value) { \
|
2024-02-25 17:46:35 +01:00
|
|
|
std::string s = std::string("-") + #input; \
|
|
|
|
type value; \
|
|
|
|
bool valid = ss::extract(s.c_str(), s.c_str() + s.size(), value); \
|
|
|
|
REQUIRE(valid); \
|
|
|
|
CHECK_EQ(value, type(-input)); \
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
2020-12-10 19:26:56 +01:00
|
|
|
|
|
|
|
using us = unsigned short;
|
|
|
|
using ui = unsigned int;
|
|
|
|
using ul = unsigned long;
|
|
|
|
using ll = long long;
|
|
|
|
using ull = unsigned long long;
|
|
|
|
|
2021-02-07 21:24:41 +01:00
|
|
|
TEST_CASE("extract test functions for decimal values") {
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_DECIMAL_CONVERSION(12, ss::int8);
|
|
|
|
CHECK_DECIMAL_CONVERSION(12, ss::uint8);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_DECIMAL_CONVERSION(1234, short);
|
|
|
|
CHECK_DECIMAL_CONVERSION(1234, us);
|
|
|
|
CHECK_DECIMAL_CONVERSION(1234, int);
|
|
|
|
CHECK_DECIMAL_CONVERSION(1234, ui);
|
|
|
|
CHECK_DECIMAL_CONVERSION(1234, long);
|
|
|
|
CHECK_DECIMAL_CONVERSION(1234, ul);
|
|
|
|
CHECK_DECIMAL_CONVERSION(1234, ll);
|
|
|
|
CHECK_DECIMAL_CONVERSION(1234567891011, ull);
|
2020-12-10 19:26:56 +01:00
|
|
|
}
|
|
|
|
|
2021-02-07 21:24:41 +01:00
|
|
|
TEST_CASE("extract test functions for numbers with invalid inputs") {
|
2024-02-25 17:46:35 +01:00
|
|
|
// negative unsigned value for numeric_wrapper
|
|
|
|
CHECK_INVALID_CONVERSION("-12", ss::uint8);
|
|
|
|
|
2020-12-26 00:46:42 +01:00
|
|
|
// negative unsigned value
|
|
|
|
CHECK_INVALID_CONVERSION("-1234", ul);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2020-12-26 00:46:42 +01:00
|
|
|
// floating pint for int
|
|
|
|
CHECK_INVALID_CONVERSION("123.4", int);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2020-12-26 00:46:42 +01:00
|
|
|
// random input for float
|
|
|
|
CHECK_INVALID_CONVERSION("xxx1", float);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2020-12-26 00:46:42 +01:00
|
|
|
// random input for int
|
|
|
|
CHECK_INVALID_CONVERSION("xxx1", int);
|
2020-12-10 19:26:56 +01:00
|
|
|
|
2020-12-26 00:46:42 +01:00
|
|
|
// empty field for int
|
|
|
|
CHECK_INVALID_CONVERSION("", int);
|
2020-12-10 19:26:56 +01:00
|
|
|
}
|
|
|
|
|
2024-02-25 17:46:35 +01:00
|
|
|
TEST_CASE_TEMPLATE(
|
|
|
|
"extract test functions for numbers with out of range inputs", T, short, us,
|
|
|
|
int, ui, long, ul, ll, ull, ss::uint8) {
|
|
|
|
{
|
2024-02-26 02:37:30 +01:00
|
|
|
std::string s = std::to_string(numeric_limits<T>::max());
|
2024-02-25 17:46:35 +01:00
|
|
|
auto t = ss::to_num<T>(s.c_str(), s.c_str() + s.size());
|
|
|
|
CHECK(t.has_value());
|
|
|
|
for (auto& i : s) {
|
|
|
|
if (i != '9' && i != '.') {
|
|
|
|
i = '9';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t = ss::to_num<T>(s.c_str(), s.c_str() + s.size());
|
|
|
|
CHECK_FALSE(t.has_value());
|
|
|
|
}
|
|
|
|
{
|
2024-02-26 02:37:30 +01:00
|
|
|
std::string s = std::to_string(numeric_limits<T>::min());
|
2024-02-25 17:46:35 +01:00
|
|
|
auto t = ss::to_num<T>(s.c_str(), s.c_str() + s.size());
|
|
|
|
CHECK(t.has_value());
|
|
|
|
for (auto& i : s) {
|
2024-02-26 02:37:30 +01:00
|
|
|
if (is_signed<T>::value && i != '9' && i != '.') {
|
2024-02-25 17:46:35 +01:00
|
|
|
i = '9';
|
|
|
|
break;
|
2024-02-26 02:37:30 +01:00
|
|
|
} else if (is_unsigned<T>::value) {
|
2024-02-25 17:46:35 +01:00
|
|
|
s = "-1";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t = ss::to_num<T>(s.c_str(), s.c_str() + s.size());
|
|
|
|
CHECK_FALSE(t.has_value());
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
2020-12-10 19:26:56 +01:00
|
|
|
}
|
|
|
|
|
2021-02-07 21:24:41 +01:00
|
|
|
TEST_CASE("extract test functions for boolean values") {
|
2020-12-26 00:46:42 +01:00
|
|
|
for (const auto& [b, s] : {std::pair<bool, std::string>{true, "1"},
|
|
|
|
{false, "0"},
|
|
|
|
{true, "true"},
|
|
|
|
{false, "false"}}) {
|
|
|
|
bool v;
|
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_EQ(v, b);
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
|
|
|
|
2022-03-27 21:04:02 +02:00
|
|
|
for (const std::string s : {"2", "tru", "truee", "xxx", ""}) {
|
2020-12-26 00:46:42 +01:00
|
|
|
bool v;
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
2020-12-10 19:26:56 +01:00
|
|
|
}
|
|
|
|
|
2021-02-07 21:24:41 +01:00
|
|
|
TEST_CASE("extract test functions for char values") {
|
2020-12-26 00:46:42 +01:00
|
|
|
for (const auto& [c, s] :
|
|
|
|
{std::pair<char, std::string>{'a', "a"}, {'x', "x"}, {' ', " "}}) {
|
|
|
|
char v;
|
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_EQ(v, c);
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
|
|
|
|
2022-03-27 21:04:02 +02:00
|
|
|
for (const std::string s : {"aa", "xxx", ""}) {
|
2020-12-26 00:46:42 +01:00
|
|
|
char v;
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
2020-12-10 19:26:56 +01:00
|
|
|
}
|
2020-12-20 19:00:45 +01:00
|
|
|
|
2024-02-25 17:46:35 +01:00
|
|
|
TEST_CASE_TEMPLATE("extract test functions for std::optional", T, int,
|
|
|
|
ss::int8) {
|
|
|
|
for (const auto& [i, s] : {std::pair<std::optional<T>, std::string>{1, "1"},
|
|
|
|
{69, "69"},
|
|
|
|
{-4, "-4"}}) {
|
|
|
|
std::optional<T> v;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
|
|
|
REQUIRE(v.has_value());
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_EQ(*v, i);
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto& [c, s] :
|
|
|
|
{std::pair<std::optional<char>, std::string>{'a', "a"},
|
|
|
|
{'x', "x"},
|
|
|
|
{' ', " "}}) {
|
|
|
|
std::optional<char> v;
|
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
|
|
|
REQUIRE(v.has_value());
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_EQ(*v, c);
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
|
|
|
|
2022-03-27 21:04:02 +02:00
|
|
|
for (const std::string s : {"aa", "xxx", ""}) {
|
2024-02-25 17:46:35 +01:00
|
|
|
std::optional<T> v;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_FALSE(v.has_value());
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
|
|
|
|
2022-03-27 21:04:02 +02:00
|
|
|
for (const std::string s : {"aa", "xxx", ""}) {
|
2020-12-26 00:46:42 +01:00
|
|
|
std::optional<char> v;
|
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), v));
|
2021-02-21 02:49:23 +01:00
|
|
|
CHECK_FALSE(v.has_value());
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
2020-12-20 19:00:45 +01:00
|
|
|
}
|
|
|
|
|
2024-02-25 17:46:35 +01:00
|
|
|
TEST_CASE_TEMPLATE("extract test functions for std::variant", T, int,
|
|
|
|
ss::uint8) {
|
2020-12-26 00:46:42 +01:00
|
|
|
{
|
|
|
|
std::string s = "22";
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<T, double, std::string> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
|
|
|
CHECK_NOT_VARIANT(var, double);
|
|
|
|
CHECK_NOT_VARIANT(var, std::string);
|
2024-02-25 17:46:35 +01:00
|
|
|
REQUIRE_VARIANT(var, 22, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
2020-12-20 19:00:45 +01:00
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<double, T, std::string> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, std::string);
|
|
|
|
REQUIRE_VARIANT(var, 22, double);
|
2020-12-20 19:00:45 +01:00
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<std::string, double, T> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, double);
|
|
|
|
REQUIRE_VARIANT(var, "22", std::string);
|
2020-12-20 19:00:45 +01:00
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<T> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
REQUIRE_VARIANT(var, 22, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::string s = "22.2";
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<T, double, std::string> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, std::string);
|
|
|
|
REQUIRE_VARIANT(var, 22.2, double);
|
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<double, T, std::string> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, std::string);
|
|
|
|
REQUIRE_VARIANT(var, 22.2, double);
|
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<std::string, double, T> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, double);
|
|
|
|
REQUIRE_VARIANT(var, "22.2", std::string);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
std::string s = "2.2.2";
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<T, double, std::string> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, double);
|
|
|
|
REQUIRE_VARIANT(var, "2.2.2", std::string);
|
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<double, std::string, T> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, double);
|
|
|
|
REQUIRE_VARIANT(var, "2.2.2", std::string);
|
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<std::string, double, T> var;
|
2020-12-26 00:46:42 +01:00
|
|
|
REQUIRE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, double);
|
|
|
|
REQUIRE_VARIANT(var, "2.2.2", std::string);
|
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<T, double> var;
|
2021-02-21 02:49:23 +01:00
|
|
|
REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2020-12-26 00:46:42 +01:00
|
|
|
|
2024-02-25 17:46:35 +01:00
|
|
|
REQUIRE_VARIANT(var, T{}, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
CHECK_NOT_VARIANT(var, double);
|
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<double, T> var;
|
2021-02-21 02:49:23 +01:00
|
|
|
REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2020-12-26 00:46:42 +01:00
|
|
|
|
|
|
|
REQUIRE_VARIANT(var, double{}, double);
|
2024-02-25 17:46:35 +01:00
|
|
|
CHECK_NOT_VARIANT(var, T);
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
|
|
|
{
|
2024-02-25 17:46:35 +01:00
|
|
|
std::variant<T> var;
|
2021-02-21 02:49:23 +01:00
|
|
|
REQUIRE_FALSE(ss::extract(s.c_str(), s.c_str() + s.size(), var));
|
2020-12-26 00:46:42 +01:00
|
|
|
|
2024-02-25 17:46:35 +01:00
|
|
|
REQUIRE_VARIANT(var, T{}, T);
|
2020-12-20 19:00:45 +01:00
|
|
|
}
|
2020-12-26 00:46:42 +01:00
|
|
|
}
|
2020-12-20 19:00:45 +01:00
|
|
|
}
|
2023-08-08 14:11:51 +02:00
|
|
|
|
|
|
|
TEST_CASE("extract test with long number string") {
|
|
|
|
{
|
|
|
|
std::string string_num =
|
|
|
|
std::string(20, '1') + "." + std::string(20, '2');
|
|
|
|
|
|
|
|
CHECK_FLOATING_CONVERSION_LONG_NUMBER(string_num, float, stof);
|
|
|
|
CHECK_FLOATING_CONVERSION_LONG_NUMBER(string_num, double, stod);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
std::string string_num =
|
|
|
|
std::string(50, '1') + "." + std::string(50, '2');
|
|
|
|
|
|
|
|
CHECK_FLOATING_CONVERSION_LONG_NUMBER(string_num, double, stod);
|
|
|
|
}
|
|
|
|
}
|