mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-30 11:44:29 +03:00
First release of open-appsec source code
This commit is contained in:
5
core/core_ut/CMakeLists.txt
Normal file
5
core/core_ut/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
add_unit_test(
|
||||
core_ut
|
||||
"tostring_ut.cc;maybe_res_ut.cc;enum_range_ut.cc;enum_array_ut.cc;cache_ut.cc;common_ut.cc;virtual_container_ut.cc;"
|
||||
"singleton;rest"
|
||||
)
|
172
core/core_ut/cache_ut.cc
Normal file
172
core/core_ut/cache_ut.cc
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "cache.h"
|
||||
|
||||
#include "cptest.h"
|
||||
|
||||
#include "mock/mock_mainloop.h"
|
||||
#include "mock/mock_time_get.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace chrono;
|
||||
using namespace testing;
|
||||
|
||||
class Int
|
||||
{
|
||||
public:
|
||||
Int() {}
|
||||
Int(const int &_val) : val(_val) {}
|
||||
Int(int &&_val) : val(move(_val)) {}
|
||||
|
||||
operator int() { return val; }
|
||||
Int & operator=(const int _val) { val = _val; return *this; }
|
||||
bool operator==(const int _val) const { return val == _val; }
|
||||
|
||||
private:
|
||||
int val = 0;
|
||||
};
|
||||
|
||||
TEST(TempCaching, value_existing)
|
||||
{
|
||||
TemporaryCache<int, Int> cache;
|
||||
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
|
||||
cache.createEntry(0);
|
||||
EXPECT_TRUE(cache.doesKeyExists(0));
|
||||
|
||||
cache.deleteEntry(0);
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
}
|
||||
|
||||
TEST(TempCaching, void_existing)
|
||||
{
|
||||
TemporaryCache<int, void> cache;
|
||||
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
|
||||
cache.createEntry(0);
|
||||
EXPECT_TRUE(cache.doesKeyExists(0));
|
||||
|
||||
cache.deleteEntry(0);
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
}
|
||||
|
||||
TEST(TempCaching, value_get)
|
||||
{
|
||||
TemporaryCache<int, Int> cache;
|
||||
cache.createEntry(0);
|
||||
|
||||
EXPECT_EQ(cache.getEntry(0), 0);
|
||||
|
||||
cache.getEntry(0) = 9;
|
||||
|
||||
EXPECT_EQ(cache.getEntry(0), 9);
|
||||
}
|
||||
|
||||
TEST(TempCaching, value_emplace)
|
||||
{
|
||||
TemporaryCache<int, Int> cache;
|
||||
int val = 9;
|
||||
|
||||
cache.emplaceEntry(0, val);
|
||||
EXPECT_EQ(cache.getEntry(0), 9);
|
||||
EXPECT_EQ(val, 9);
|
||||
|
||||
|
||||
cache.emplaceEntry(1, move(val));
|
||||
EXPECT_EQ(cache.getEntry(0), 9);
|
||||
EXPECT_EQ(cache.getEntry(1), 9);
|
||||
EXPECT_EQ(val, 9);
|
||||
}
|
||||
|
||||
TEST(TempCaching, get_uninitialized_value)
|
||||
{
|
||||
TemporaryCache<int, Int> cache;
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
|
||||
EXPECT_EQ(cache.getEntry(0), 0);
|
||||
|
||||
EXPECT_TRUE(cache.doesKeyExists(0));
|
||||
}
|
||||
|
||||
TEST(TempCaching, expiration)
|
||||
{
|
||||
StrictMock<MockMainLoop> mock_ml;
|
||||
auto i_mainloop = Singleton::Consume<I_MainLoop>::from<MockProvider<I_MainLoop>>();
|
||||
StrictMock<MockTimeGet> mock_time;
|
||||
auto i_time_get = Singleton::Consume<I_TimeGet>::from<MockProvider<I_TimeGet>>();
|
||||
TemporaryCache<int, Int> cache;
|
||||
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
cache.createEntry(0);
|
||||
EXPECT_TRUE(cache.doesKeyExists(0));
|
||||
|
||||
EXPECT_CALL(mock_ml, doesRoutineExist(0)).WillOnce(Return(false));
|
||||
I_MainLoop::Routine routine;
|
||||
EXPECT_CALL(mock_ml, addRecurringRoutine(_, _, _, _, _)).WillOnce(DoAll(SaveArg<2>(&routine), Return(1)));
|
||||
cache.startExpiration(seconds(10), i_mainloop, i_time_get);
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
|
||||
EXPECT_CALL(mock_time, getMonotonicTime()).WillOnce(Return(seconds(2)));
|
||||
cache.createEntry(0);
|
||||
EXPECT_TRUE(cache.doesKeyExists(0));
|
||||
|
||||
EXPECT_CALL(mock_time, getMonotonicTime()).WillOnce(Return(seconds(6)));
|
||||
cache.createEntry(1);
|
||||
EXPECT_TRUE(cache.doesKeyExists(0));
|
||||
EXPECT_TRUE(cache.doesKeyExists(1));
|
||||
|
||||
EXPECT_CALL(mock_time, getMonotonicTime()).WillOnce(Return(seconds(14)));
|
||||
routine();
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
EXPECT_TRUE(cache.doesKeyExists(1));
|
||||
|
||||
EXPECT_CALL(mock_time, getMonotonicTime()).WillOnce(Return(seconds(24)));
|
||||
routine();
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
EXPECT_FALSE(cache.doesKeyExists(1));
|
||||
|
||||
EXPECT_CALL(mock_ml, doesRoutineExist(1)).WillOnce(Return(true));
|
||||
EXPECT_CALL(mock_ml, stop(1));
|
||||
cache.endExpiration();
|
||||
}
|
||||
|
||||
TEST(TempCaching, capacity)
|
||||
{
|
||||
TemporaryCache<int, Int> cache;
|
||||
cache.createEntry(0);
|
||||
cache.createEntry(1);
|
||||
cache.createEntry(2);
|
||||
cache.createEntry(3);
|
||||
cache.createEntry(4);
|
||||
|
||||
EXPECT_EQ(cache.size(), 5);
|
||||
EXPECT_EQ(cache.capacity(), 0);
|
||||
cache.capacity(3);
|
||||
EXPECT_EQ(cache.size(), 3);
|
||||
EXPECT_FALSE(cache.doesKeyExists(0));
|
||||
EXPECT_FALSE(cache.doesKeyExists(1));
|
||||
EXPECT_TRUE(cache.doesKeyExists(2));
|
||||
EXPECT_TRUE(cache.doesKeyExists(3));
|
||||
EXPECT_TRUE(cache.doesKeyExists(4));
|
||||
|
||||
cache.createEntry(5);
|
||||
EXPECT_EQ(cache.size(), 3);
|
||||
EXPECT_FALSE(cache.doesKeyExists(2));
|
||||
EXPECT_TRUE(cache.doesKeyExists(3));
|
||||
EXPECT_TRUE(cache.doesKeyExists(4));
|
||||
EXPECT_TRUE(cache.doesKeyExists(5));
|
||||
|
||||
cache.capacity(0);
|
||||
cache.createEntry(6);
|
||||
EXPECT_EQ(cache.size(), 4);
|
||||
EXPECT_TRUE(cache.doesKeyExists(3));
|
||||
EXPECT_TRUE(cache.doesKeyExists(4));
|
||||
EXPECT_TRUE(cache.doesKeyExists(5));
|
||||
EXPECT_TRUE(cache.doesKeyExists(6));
|
||||
|
||||
cache.deleteEntry(5);
|
||||
cache.capacity(2);
|
||||
EXPECT_EQ(cache.size(), 2);
|
||||
EXPECT_TRUE(cache.doesKeyExists(4));
|
||||
EXPECT_TRUE(cache.doesKeyExists(6));
|
||||
}
|
233
core/core_ut/common_ut.cc
Normal file
233
core/core_ut/common_ut.cc
Normal file
@@ -0,0 +1,233 @@
|
||||
#include "common.h"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "cptest.h"
|
||||
#include "customized_cereal_map.h"
|
||||
#include "customized_cereal_multimap.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cereal;
|
||||
|
||||
TEST(MakeSeperatedStr, array)
|
||||
{
|
||||
array<int, 5> arr = { 1, 2, 3, 4, 5 };
|
||||
EXPECT_EQ(makeSeparatedStr(arr, " - "), "1 - 2 - 3 - 4 - 5");
|
||||
}
|
||||
|
||||
TEST(MakeSeperatedStr, vector)
|
||||
{
|
||||
vector<string> vec = { "aaa", "b", "c c", "dd" };
|
||||
EXPECT_EQ(makeSeparatedStr(vec, ", "), "aaa, b, c c, dd");
|
||||
}
|
||||
|
||||
TEST(Debug, dump_printable_char)
|
||||
{
|
||||
char ch = 'c';
|
||||
EXPECT_EQ(dumpHexChar(ch), string("'c'"));
|
||||
}
|
||||
|
||||
TEST(Debug, dump_non_printable_char)
|
||||
{
|
||||
char ch = 0x1B;
|
||||
EXPECT_EQ(dumpHexChar(ch), string("\\x1b"));
|
||||
}
|
||||
|
||||
TEST(Debug, dump_hex)
|
||||
{
|
||||
EXPECT_EQ(dumpHex(string("hello")), "hello");
|
||||
EXPECT_EQ(dumpHex(string("a\\b")), "a\\\\b");
|
||||
EXPECT_EQ(dumpHex(string("a\tb")), "a\\x09b");
|
||||
EXPECT_EQ(dumpHex(vector<char>({ 'w', 'o', 'r', 'l', 'd'})), "world");
|
||||
int tst_numeric[4] = {1, 10, 200, 201};
|
||||
EXPECT_EQ(dumpHex(tst_numeric), "\\x01\\x0a\\xc8\\xc9");
|
||||
}
|
||||
|
||||
TEST(Debug, dump_real_hex)
|
||||
{
|
||||
EXPECT_EQ(dumpRealHex(string("hello")), " 68 65 6c 6c 6f");
|
||||
EXPECT_EQ(dumpRealHex(string("a\\b")), " 61 5c 62");
|
||||
EXPECT_EQ(dumpRealHex(string("a\tb")), " 61 09 62");
|
||||
EXPECT_EQ(dumpRealHex(vector<char>({ 'w', 'o', 'r', 'l', 'd'})), " 77 6f 72 6c 64");
|
||||
int tst_numeric[4] = {1, 10, 200, 201};
|
||||
EXPECT_EQ(dumpRealHex(tst_numeric), " 01 0a c8 c9");
|
||||
}
|
||||
|
||||
class Aaaa {};
|
||||
|
||||
class B {};
|
||||
|
||||
ostream & operator<<(ostream &os, const B &) { return os; }
|
||||
|
||||
TEST(Printable, check_if_printable)
|
||||
{
|
||||
EXPECT_FALSE(IsPrintable<Aaaa>());
|
||||
EXPECT_TRUE(IsPrintable<B>());
|
||||
EXPECT_TRUE(IsPrintable<int>());
|
||||
EXPECT_TRUE(IsPrintable<string>());
|
||||
}
|
||||
|
||||
class TestCerealMap : public testing::Test
|
||||
{
|
||||
public:
|
||||
template<typename Type>
|
||||
string
|
||||
serializeMap(const map<string, Type> &test_map, const string &map_key)
|
||||
{
|
||||
std::stringstream out;
|
||||
{
|
||||
cereal::JSONOutputArchive out_ar(out);
|
||||
out_ar(cereal::make_nvp(map_key, test_map));
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
map<string, Type>
|
||||
deserializeMap(const string &map_text, const string &map_key)
|
||||
{
|
||||
map<string, Type> ret_value;
|
||||
std::stringstream in;
|
||||
in << map_text;
|
||||
{
|
||||
cereal::JSONInputArchive in_ar(in);
|
||||
in_ar(cereal::make_nvp(map_key, ret_value));
|
||||
}
|
||||
return ret_value;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestCerealMap, serialize)
|
||||
{
|
||||
map<string, string> strings_map = {{"fi", "fa"}, {"fo", "fam"}, {"bisli", "bamba"}};
|
||||
map<string, int> ints_map = {{"4", 2}, {"42", 420}};
|
||||
using strings = vector<string>;
|
||||
map<string, strings> strings_vectors_map = {{"1", strings({"2", "3"})}};
|
||||
EXPECT_EQ(
|
||||
serializeMap<string>(strings_map, "strings_map"),
|
||||
"{\n"
|
||||
" \"strings_map\": {\n"
|
||||
" \"bisli\": \"bamba\",\n"
|
||||
" \"fi\": \"fa\",\n"
|
||||
" \"fo\": \"fam\"\n"
|
||||
" }\n"
|
||||
"}"
|
||||
|
||||
);
|
||||
EXPECT_EQ(
|
||||
serializeMap<int>(ints_map, "ints_map"),
|
||||
"{\n"
|
||||
" \"ints_map\": {\n"
|
||||
" \"4\": 2,\n"
|
||||
" \"42\": 420\n"
|
||||
" }\n"
|
||||
"}"
|
||||
|
||||
);
|
||||
EXPECT_EQ(
|
||||
serializeMap<strings>(strings_vectors_map, "strings_vectors_map"),
|
||||
"{\n"
|
||||
" \"strings_vectors_map\": {\n"
|
||||
" \"1\": [\n"
|
||||
" \"2\",\n"
|
||||
" \"3\"\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(TestCerealMap, desirialize)
|
||||
{
|
||||
string map_str = "{\"bool_map\" :{\"true\": true, \"false\": false }}";
|
||||
map<string, bool> expected_bools_map({{"true", true}, {"false", false}});
|
||||
EXPECT_EQ(deserializeMap<bool>(map_str, "bool_map"), expected_bools_map);
|
||||
|
||||
map_str = "{\"string_map\" :{\"str\": \"str\", \"char *\": \"char *\" }}";
|
||||
map<string, string> expected_string_map({{"str", "str"}, {"char *", "char *"}});
|
||||
EXPECT_EQ(deserializeMap<string>(map_str, "string_map"), expected_string_map);
|
||||
|
||||
map_str = "{\"strings_vectors_map\" :{\"hello\": [\"world\", \"universe\"], \"hi\": [\"space\"] }}";
|
||||
using strings = vector<string>;
|
||||
|
||||
map<string, strings> expected_strings_vectors_map(
|
||||
{{"hello", strings({"world", "universe"})},
|
||||
{"hi", strings({"space"})}}
|
||||
);
|
||||
EXPECT_EQ(deserializeMap<strings>(map_str, "strings_vectors_map"), expected_strings_vectors_map);
|
||||
}
|
||||
|
||||
TEST(TestCerealMultimap, regularStringMap)
|
||||
{
|
||||
SerializableMultiMap<string> m;
|
||||
|
||||
string data_str =
|
||||
"{\n"
|
||||
" \"multimap\": {\n"
|
||||
" \"user\": \"omry\"\n"
|
||||
" }\n"
|
||||
"}";
|
||||
|
||||
stringstream is;
|
||||
is << data_str;
|
||||
JSONInputArchive ar(is);
|
||||
ar(make_nvp("multimap", m));
|
||||
|
||||
EXPECT_EQ(m.getMap<string>()["user"], "omry");
|
||||
}
|
||||
|
||||
TEST(TestCerealMultimap, mixedPrimitivesMap)
|
||||
{
|
||||
SerializableMultiMap<string, int, bool> m;
|
||||
|
||||
string data_str =
|
||||
"{\n"
|
||||
" \"multimap\": {\n"
|
||||
" \"user\": \"omry\",\n"
|
||||
" \"number\": 14,\n"
|
||||
" \"king of cpp\": true\n"
|
||||
" }\n"
|
||||
"}";
|
||||
|
||||
stringstream is;
|
||||
is << data_str;
|
||||
JSONInputArchive ar(is);
|
||||
ar(make_nvp("multimap", m));
|
||||
|
||||
EXPECT_EQ(m.getMap<string>()["user"], "omry");
|
||||
EXPECT_EQ(m.getMap<int>()["number"], 14);
|
||||
EXPECT_EQ(m.getMap<bool>()["king of cpp"], true);
|
||||
}
|
||||
|
||||
TEST(TestCerealMultimap, mixedPrimitivesAndObjectsMap)
|
||||
{
|
||||
SerializableMultiMap<string, int, bool, vector<string>> m;
|
||||
|
||||
string data_str =
|
||||
"{\n"
|
||||
" \"multimap\": {\n"
|
||||
" \"user\": \"omry\",\n"
|
||||
" \"number\": 14,\n"
|
||||
" \"king of cpp\": true,\n"
|
||||
" \"friends\": [\n"
|
||||
" \"Max\",\n"
|
||||
" \"David\",\n"
|
||||
" \"Daniel\",\n"
|
||||
" \"Oren\",\n"
|
||||
" \"Roi\",\n"
|
||||
" \"Moaad\"\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
"}";
|
||||
|
||||
stringstream is;
|
||||
is << data_str;
|
||||
JSONInputArchive ar(is);
|
||||
ar(make_nvp("multimap", m));
|
||||
|
||||
EXPECT_EQ(m.getMap<string>()["user"], "omry");
|
||||
EXPECT_EQ(m.getMap<int>()["number"], 14);
|
||||
EXPECT_EQ(m.getMap<bool>()["king of cpp"], true);
|
||||
EXPECT_EQ(m.getMap<vector<string>>()["friends"].front(), "Max");
|
||||
}
|
85
core/core_ut/enum_array_ut.cc
Normal file
85
core/core_ut/enum_array_ut.cc
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "enum_array.h"
|
||||
|
||||
#include "cptest.h"
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
enum class Test1 { val1, val2, val3, val4, COUNT };
|
||||
|
||||
TEST(enum_array, enum_with_count)
|
||||
{
|
||||
EnumArray<Test1, int> arr(0, 1, 2, 4);
|
||||
EXPECT_EQ(arr[Test1::val1], 0);
|
||||
EXPECT_EQ(arr[Test1::val2], 1);
|
||||
EXPECT_EQ(arr[Test1::val3], 2);
|
||||
EXPECT_EQ(arr[Test1::val4], 4);
|
||||
|
||||
arr[Test1::val4] = 3;
|
||||
EXPECT_EQ(arr[Test1::val4], 3);
|
||||
|
||||
vector<int> vals;
|
||||
for (auto num : arr) {
|
||||
vals.push_back(num);
|
||||
}
|
||||
vector<int> expected = { 0, 1, 2, 3 };
|
||||
EXPECT_EQ(vals, expected);
|
||||
}
|
||||
|
||||
TEST(enum_array, auto_fill)
|
||||
{
|
||||
EnumArray<Test1, int> arr(EnumArray<Test1, int>::Fill(), 18);
|
||||
|
||||
vector<int> vals;
|
||||
for (auto num : arr) {
|
||||
vals.push_back(num);
|
||||
}
|
||||
vector<int> expected = { 18, 18, 18, 18 };
|
||||
EXPECT_EQ(vals, expected);
|
||||
}
|
||||
|
||||
enum class Test2 { val1, val2, val3, val4 };
|
||||
template <>
|
||||
class EnumCount<Test2> : public EnumCountSpecialization<Test2, 4>
|
||||
{
|
||||
};
|
||||
|
||||
TEST(enum_array, enum_with_template_specialization)
|
||||
{
|
||||
EnumArray<Test2, int> arr(0, 1, 2, 4);
|
||||
EXPECT_EQ(arr[Test2::val1], 0);
|
||||
EXPECT_EQ(arr[Test2::val2], 1);
|
||||
EXPECT_EQ(arr[Test2::val3], 2);
|
||||
EXPECT_EQ(arr[Test2::val4], 4);
|
||||
|
||||
arr[Test2::val4] = 3;
|
||||
EXPECT_EQ(arr[Test2::val4], 3);
|
||||
|
||||
vector<int> vals;
|
||||
for (auto num : arr) {
|
||||
vals.push_back(num);
|
||||
}
|
||||
vector<int> expected = { 0, 1, 2, 3 };
|
||||
EXPECT_EQ(vals, expected);
|
||||
}
|
||||
|
||||
enum class Test3 { val1, val2, val3, val4 };
|
||||
|
||||
TEST(enum_array, array_with_explicit_length)
|
||||
{
|
||||
EnumArray<Test3, int, 4> arr(0, 1, 2, 4);
|
||||
EXPECT_EQ(arr[Test3::val1], 0);
|
||||
EXPECT_EQ(arr[Test3::val2], 1);
|
||||
EXPECT_EQ(arr[Test3::val3], 2);
|
||||
EXPECT_EQ(arr[Test3::val4], 4);
|
||||
|
||||
arr[Test3::val4] = 3;
|
||||
EXPECT_EQ(arr[Test3::val4], 3);
|
||||
|
||||
vector<int> vals;
|
||||
for (auto num : arr) {
|
||||
vals.push_back(num);
|
||||
}
|
||||
vector<int> expected = { 0, 1, 2, 3 };
|
||||
EXPECT_EQ(vals, expected);
|
||||
}
|
50
core/core_ut/enum_range_ut.cc
Normal file
50
core/core_ut/enum_range_ut.cc
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "enum_range.h"
|
||||
|
||||
#include "cptest.h"
|
||||
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
using testing::ElementsAre;
|
||||
|
||||
enum class Test1 { val1, val2, val3, val4, COUNT };
|
||||
|
||||
TEST(enum_range, whole_range)
|
||||
{
|
||||
EXPECT_THAT(NGEN::Range<Test1>(), ElementsAre(Test1::val1, Test1::val2, Test1::val3, Test1::val4));
|
||||
EXPECT_THAT(makeRange<Test1>(), ElementsAre(Test1::val1, Test1::val2, Test1::val3, Test1::val4));
|
||||
}
|
||||
|
||||
TEST(enum_range, up_to_point)
|
||||
{
|
||||
EXPECT_THAT(NGEN::Range<Test1>(Test1::val3), ElementsAre(Test1::val1, Test1::val2, Test1::val3));
|
||||
EXPECT_THAT(makeRange(Test1::val3), ElementsAre(Test1::val1, Test1::val2, Test1::val3));
|
||||
}
|
||||
|
||||
TEST(enum_range, slice_range)
|
||||
{
|
||||
EXPECT_THAT(NGEN::Range<Test1>(Test1::val2, Test1::val3), ElementsAre(Test1::val2, Test1::val3));
|
||||
EXPECT_THAT(makeRange(Test1::val2, Test1::val3), ElementsAre(Test1::val2, Test1::val3));
|
||||
}
|
||||
|
||||
|
||||
enum class Test2 { val1, val2, val3, val4 };
|
||||
template <>
|
||||
class EnumCount<Test2> : public EnumCountSpecialization<Test2, 4> {};
|
||||
|
||||
TEST(enum_range, whole_range_without_count_elem)
|
||||
{
|
||||
EXPECT_THAT(NGEN::Range<Test2>(), ElementsAre(Test2::val1, Test2::val2, Test2::val3, Test2::val4));
|
||||
EXPECT_THAT(makeRange<Test2>(), ElementsAre(Test2::val1, Test2::val2, Test2::val3, Test2::val4));
|
||||
}
|
||||
|
||||
TEST(enum_range, int_up_point)
|
||||
{
|
||||
EXPECT_THAT(NGEN::Range<int>(9), ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
|
||||
EXPECT_THAT(makeRange(9), ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
|
||||
}
|
||||
|
||||
TEST(enum_range, int_slice_range)
|
||||
{
|
||||
EXPECT_THAT(NGEN::Range<int>(5, 10), ElementsAre(5, 6, 7, 8, 9, 10));
|
||||
EXPECT_THAT(makeRange(5, 10), ElementsAre(5, 6, 7, 8, 9, 10));
|
||||
}
|
406
core/core_ut/maybe_res_ut.cc
Executable file
406
core/core_ut/maybe_res_ut.cc
Executable file
@@ -0,0 +1,406 @@
|
||||
#include "cptest.h"
|
||||
#include "maybe_res.h"
|
||||
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <set>
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
static Maybe<int>
|
||||
returnIfEven(int i)
|
||||
{
|
||||
if (i%2 == 1) return genError("Odd number");
|
||||
return i;
|
||||
}
|
||||
|
||||
TEST(Usage, typical_function)
|
||||
{
|
||||
auto even = returnIfEven(4);
|
||||
ASSERT_TRUE(even.ok());
|
||||
EXPECT_EQ(4, *even);
|
||||
EXPECT_THAT(even, IsValue(4));
|
||||
|
||||
auto odd = returnIfEven(5);
|
||||
ASSERT_FALSE(odd.ok());
|
||||
EXPECT_EQ("Odd number", odd.getErr());
|
||||
EXPECT_THAT(odd, IsError("Odd number"));
|
||||
}
|
||||
|
||||
TEST(genError, explicit_build)
|
||||
{
|
||||
Error<string> err = genError<string>("error");
|
||||
}
|
||||
|
||||
TEST(genError, implicit_build)
|
||||
{
|
||||
Error<string> err = genError(string("error"));
|
||||
}
|
||||
|
||||
TEST(genError, paramaters_build)
|
||||
{
|
||||
string str = "error";
|
||||
Error<vector<char>> err = genError<vector<char>>(str.begin(), str.end());
|
||||
}
|
||||
|
||||
TEST(genError, void_build)
|
||||
{
|
||||
Error<void> err1 = genError<void>();
|
||||
Error<void> err2 = genError<void>(5, 6, 7);
|
||||
EXPECT_TRUE(err1 == err2);
|
||||
}
|
||||
|
||||
TEST(Maybe, basic_error)
|
||||
{
|
||||
Maybe<int> res = genError<string>("error");
|
||||
ASSERT_FALSE(res.ok());
|
||||
EXPECT_EQ(string("error"), res.getErr());
|
||||
EXPECT_THAT(res, IsError("error"));
|
||||
}
|
||||
|
||||
TEST(Maybe, basic_value)
|
||||
{
|
||||
Maybe<int> res = 5;
|
||||
ASSERT_TRUE(res.ok());
|
||||
EXPECT_EQ(5, res.unpack());
|
||||
EXPECT_EQ(5, static_cast<int>(*res));
|
||||
EXPECT_EQ(5, *res);
|
||||
EXPECT_THAT(res, IsValue(5));
|
||||
}
|
||||
|
||||
TEST(Maybe, error_cast)
|
||||
{
|
||||
Maybe<int> res = genError<const char *>("error");
|
||||
EXPECT_THAT(res, IsError("error"));
|
||||
}
|
||||
|
||||
TEST(Maybe, error_cast_impilicit)
|
||||
{
|
||||
Maybe<int> res = genError("error");
|
||||
EXPECT_THAT(res, IsError("error"));
|
||||
}
|
||||
|
||||
TEST(Maybe, unpack_execption)
|
||||
{
|
||||
Maybe<int> res = 5;
|
||||
EXPECT_EQ(5, res.unpack<string>());
|
||||
|
||||
Maybe<int> err = genError("error");
|
||||
|
||||
EXPECT_THROW(err.unpack<string>(), string);
|
||||
try {
|
||||
err.unpack<string>();
|
||||
} catch (string str) {
|
||||
EXPECT_EQ("error", str);
|
||||
}
|
||||
|
||||
EXPECT_THROW(err.unpack<string>("really ", "bad "), string);
|
||||
try {
|
||||
err.unpack<string>("really ", "bad ");
|
||||
} catch (string str) {
|
||||
EXPECT_EQ("really bad error", str);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Maybe, verify)
|
||||
{
|
||||
Maybe<int> res = 5;
|
||||
res.verify<string>();
|
||||
res.verify<string>("really ", "bad ");
|
||||
|
||||
Maybe<int> err = genError("error");
|
||||
|
||||
EXPECT_THROW(err.verify<string>(), string);
|
||||
try {
|
||||
err.verify<string>();
|
||||
} catch (string str) {
|
||||
EXPECT_EQ("error", str);
|
||||
}
|
||||
|
||||
EXPECT_THROW(err.verify<string>("really ", "bad "), string);
|
||||
try {
|
||||
err.verify<string>("really ", "bad ");
|
||||
} catch (string str) {
|
||||
EXPECT_EQ("really bad error", str);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Maybe, equalValue)
|
||||
{
|
||||
Maybe<int> a=1, b=1, c=2;
|
||||
EXPECT_TRUE (a==b);
|
||||
EXPECT_FALSE(a==c);
|
||||
EXPECT_TRUE (a!=c);
|
||||
EXPECT_FALSE(a!=b);
|
||||
}
|
||||
|
||||
TEST(Maybe, equalError)
|
||||
{
|
||||
Maybe<char, int> a=genError(1), b=genError(1), c=genError(2);
|
||||
EXPECT_TRUE (a==b);
|
||||
EXPECT_FALSE(a==c);
|
||||
EXPECT_TRUE (a!=c);
|
||||
EXPECT_FALSE(a!=b);
|
||||
|
||||
Maybe<int> d=genError("error1");
|
||||
Maybe<int> e=genError("error2");
|
||||
|
||||
EXPECT_FALSE(d==e);
|
||||
}
|
||||
|
||||
|
||||
class MaybeAssignments : public Test
|
||||
{
|
||||
public:
|
||||
// A class to use as a value.
|
||||
// Maybe runs constructors and destructors manually, so we verify that they're
|
||||
// called properly.
|
||||
class MyValue
|
||||
{
|
||||
public:
|
||||
MyValue(int _x) : x(_x) { addObj(this); }
|
||||
MyValue(const MyValue &other) : x(other.x) { addObj(this); }
|
||||
~MyValue() { delObj(this); }
|
||||
bool operator==(const MyValue &other) const { return x==other.x; }
|
||||
bool operator!=(const MyValue &other) const { return x!=other.x; }
|
||||
|
||||
int x;
|
||||
|
||||
// Tracking all existing objects
|
||||
static set<const MyValue *> objects;
|
||||
|
||||
static void
|
||||
addObj(const MyValue *obj)
|
||||
{
|
||||
EXPECT_EQ(objects.end(), objects.find(obj));
|
||||
objects.insert(obj);
|
||||
}
|
||||
|
||||
static void
|
||||
delObj(const MyValue *obj)
|
||||
{
|
||||
EXPECT_NE(objects.end(), objects.find(obj));
|
||||
objects.erase(obj);
|
||||
}
|
||||
};
|
||||
|
||||
MaybeAssignments()
|
||||
{
|
||||
MyValue::objects.clear();
|
||||
}
|
||||
|
||||
~MaybeAssignments()
|
||||
{
|
||||
EXPECT_THAT(MyValue::objects, IsEmpty());
|
||||
}
|
||||
};
|
||||
|
||||
set<const MaybeAssignments::MyValue *> MaybeAssignments::MyValue::objects;
|
||||
|
||||
// Testing assignment of a new value. Combinations:
|
||||
// Old is value / error
|
||||
// New is value / error
|
||||
// New is L-value / R-value
|
||||
|
||||
TEST_F(MaybeAssignments, ValValRval)
|
||||
{
|
||||
Maybe<MyValue, MyValue> m(MyValue(1));
|
||||
|
||||
// Change the value
|
||||
EXPECT_EQ(1, m->x);
|
||||
m = 2;
|
||||
EXPECT_EQ(2, m->x);
|
||||
}
|
||||
|
||||
TEST_F(MaybeAssignments, ValValLval)
|
||||
{
|
||||
Maybe<MyValue, MyValue> m(MyValue(1));
|
||||
|
||||
// Change the value
|
||||
EXPECT_EQ(1, m->x);
|
||||
MyValue v = 2;
|
||||
m = v;
|
||||
EXPECT_EQ(2, m->x);
|
||||
}
|
||||
|
||||
TEST_F(MaybeAssignments, ErrValRval)
|
||||
{
|
||||
Maybe<MyValue, MyValue> m(genError(404));
|
||||
|
||||
// Convert an error to a value
|
||||
EXPECT_EQ(MyValue(404), m.getErr());
|
||||
m = 3;
|
||||
EXPECT_EQ(3, m->x);
|
||||
}
|
||||
|
||||
TEST_F(MaybeAssignments, ErrValLval)
|
||||
{
|
||||
Maybe<MyValue, MyValue> m(genError(404));
|
||||
|
||||
// Convert an error to a value
|
||||
EXPECT_EQ(MyValue(404), m.getErr());
|
||||
MyValue v = 3;
|
||||
m = v;
|
||||
EXPECT_EQ(3, m->x);
|
||||
}
|
||||
|
||||
TEST_F(MaybeAssignments, ValErrRval)
|
||||
{
|
||||
Maybe<MyValue, MyValue> m(MyValue(1));
|
||||
|
||||
// Convert a value to an error
|
||||
EXPECT_EQ(1, m->x);
|
||||
m = genError(500);
|
||||
EXPECT_EQ(MyValue(500), m.getErr());
|
||||
}
|
||||
|
||||
TEST_F(MaybeAssignments, ValErrLval)
|
||||
{
|
||||
Maybe<MyValue, MyValue> m(MyValue(1));
|
||||
|
||||
// Convert a value to an error
|
||||
EXPECT_EQ(1, m->x);
|
||||
Error<MyValue> e(500);
|
||||
m = e;
|
||||
EXPECT_EQ(MyValue(500), m.getErr());
|
||||
}
|
||||
|
||||
TEST_F(MaybeAssignments, ErrErrRval)
|
||||
{
|
||||
Maybe<uint> m(genError("404"));
|
||||
|
||||
// Change the error
|
||||
EXPECT_EQ("404", m.getErr());
|
||||
Error<string> e("500");
|
||||
m = move(e);
|
||||
EXPECT_EQ("500", m.getErr());
|
||||
}
|
||||
|
||||
TEST_F(MaybeAssignments, ErrErrLval)
|
||||
{
|
||||
Maybe<MyValue, MyValue> m(genError(404));
|
||||
|
||||
// Change the error
|
||||
EXPECT_EQ(MyValue(404), m.getErr());
|
||||
Error<MyValue> e(500);
|
||||
m = e;
|
||||
EXPECT_EQ(MyValue(500), m.getErr());
|
||||
}
|
||||
|
||||
|
||||
class ErrorTranslator
|
||||
{
|
||||
public:
|
||||
template <typename Err>
|
||||
ErrorTranslator(const map<Err, string> &m, Err err) : str(m.at(err)) {}
|
||||
|
||||
operator string() { return str; }
|
||||
|
||||
private:
|
||||
string str;
|
||||
};
|
||||
|
||||
TEST(Maybe, diff_aggr)
|
||||
{
|
||||
Maybe<int, int> err = genError(8);
|
||||
map<int, string> trans = { { 8, "my error" } };
|
||||
try {
|
||||
err.verify<string, ErrorTranslator>(trans);
|
||||
} catch (string str) {
|
||||
EXPECT_EQ("my error", str);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Maybe, illegal_access)
|
||||
{
|
||||
cptestPrepareToDie();
|
||||
|
||||
Maybe<int> err = genError("error");
|
||||
EXPECT_DEATH(*err, "Maybe value is not set");
|
||||
EXPECT_DEATH(err.unpack(), "Maybe value is not set");
|
||||
|
||||
Maybe<int> res = 5;
|
||||
EXPECT_DEATH(res.getErr(), "Maybe value is set");
|
||||
}
|
||||
|
||||
TEST(Maybe, passing_error)
|
||||
{
|
||||
Maybe<int> err1 = genError("error");
|
||||
Maybe<string> err2 = err1.passErr();
|
||||
|
||||
EXPECT_THAT(err2, IsError("error"));
|
||||
}
|
||||
|
||||
TEST(Maybe, maybe_void)
|
||||
{
|
||||
cptestPrepareToDie();
|
||||
|
||||
Maybe<void> res;
|
||||
EXPECT_TRUE(res.ok());
|
||||
|
||||
EXPECT_DEATH(res.getErr(), "Maybe value is set");
|
||||
}
|
||||
|
||||
|
||||
TEST(Maybe, maybe_void_error)
|
||||
{
|
||||
Maybe<void> err = genError("error");
|
||||
|
||||
EXPECT_THAT(err, IsError("error"));
|
||||
}
|
||||
|
||||
TEST(Maybe, maybe_void_error_passing)
|
||||
{
|
||||
Maybe<int> err1 = genError("error");
|
||||
Maybe<void> err2 = err1.passErr();
|
||||
|
||||
EXPECT_FALSE(err2.ok());
|
||||
EXPECT_EQ("error", err2.getErr());
|
||||
}
|
||||
|
||||
TEST(Maybe, printing)
|
||||
{
|
||||
ostringstream os;
|
||||
Maybe<int> val1 = 5;
|
||||
os << val1;
|
||||
EXPECT_EQ("Value(5)", os.str());
|
||||
|
||||
os.str("");
|
||||
Maybe<void> val2;
|
||||
os << val2;
|
||||
EXPECT_EQ("Value()", os.str());
|
||||
|
||||
os.str("");
|
||||
Maybe<int> err1 = genError("error");
|
||||
os << err1;
|
||||
EXPECT_EQ("Error(error)", os.str());
|
||||
|
||||
os.str("");
|
||||
Maybe<void> err2 = genError("error");;
|
||||
os << err2;
|
||||
EXPECT_EQ("Error(error)", os.str());
|
||||
|
||||
}
|
||||
|
||||
|
||||
TEST(Maybe, cast_value)
|
||||
{
|
||||
Maybe<int> val1 = 5;
|
||||
Maybe<double> val2(val1);
|
||||
EXPECT_THAT(val2, IsValue(5.0));
|
||||
}
|
||||
|
||||
TEST(Maybe, cast_err)
|
||||
{
|
||||
Maybe<string, int> err1 = genError(3);
|
||||
Maybe<string, double> err2 = move(err1);
|
||||
EXPECT_THAT(err2, IsError(3.0));
|
||||
}
|
||||
|
||||
TEST(Maybe, cast_err_void)
|
||||
{
|
||||
Maybe<int, int> err1 = genError(3);
|
||||
Maybe<double, void> err2 = err1;
|
||||
EXPECT_FALSE(err2.ok());
|
||||
}
|
42
core/core_ut/tostring_ut.cc
Normal file
42
core/core_ut/tostring_ut.cc
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "tostring.h"
|
||||
|
||||
#include "cptest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing;
|
||||
|
||||
TEST(ToStringTest, basic)
|
||||
{
|
||||
ToString str;
|
||||
EXPECT_EQ("", static_cast<string>(str));
|
||||
|
||||
string tmp = str;
|
||||
EXPECT_EQ("", tmp);
|
||||
}
|
||||
|
||||
TEST(ToStringTest, one_parameter)
|
||||
{
|
||||
ToString str("aaa");
|
||||
EXPECT_EQ(string("aaa"), static_cast<string>(str));
|
||||
}
|
||||
|
||||
TEST(ToStringTest, three_parameters)
|
||||
{
|
||||
ToString str("R", 8, 0);
|
||||
EXPECT_EQ(string("R80"), static_cast<string>(str));
|
||||
}
|
||||
|
||||
TEST(ToStringTest, operator)
|
||||
{
|
||||
ToString str;
|
||||
str << 'R' << 80;
|
||||
EXPECT_EQ(string("R80"), static_cast<string>(str));
|
||||
}
|
||||
|
||||
TEST(ToStringTest, reset)
|
||||
{
|
||||
ToString str("aaa");
|
||||
EXPECT_EQ(string("aaa"), static_cast<string>(str));
|
||||
str.reset();
|
||||
EXPECT_EQ(string(), static_cast<string>(str));
|
||||
}
|
116
core/core_ut/virtual_container_ut.cc
Normal file
116
core/core_ut/virtual_container_ut.cc
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "virtual_modifiers.h"
|
||||
|
||||
#include "cptest.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
TEST(SingleModifer, CharRemover)
|
||||
{
|
||||
string orig = " 123 45 67 ggg\t h ";
|
||||
|
||||
auto without_space = makeVirtualContainer<CharRemover<' '>>(orig);
|
||||
auto without_tab = makeVirtualContainer<CharRemover<'\t'>>(orig);
|
||||
auto without_g = makeVirtualContainer<CharRemover<'g'>>(orig);
|
||||
auto withall = makeVirtualContainer<CharRemover<'p'>>(orig);
|
||||
|
||||
EXPECT_EQ(orig, " 123 45 67 ggg\t h ");
|
||||
EXPECT_EQ(string(without_space.begin(), without_space.end()), "1234567ggg\th");
|
||||
EXPECT_EQ(string(without_tab.begin(), without_tab.end()), " 123 45 67 ggg h ");
|
||||
EXPECT_EQ(string(without_g.begin(), without_g.end()), " 123 45 67 \t h ");
|
||||
EXPECT_EQ(string(withall.begin(), withall.end()), orig);
|
||||
}
|
||||
|
||||
TEST(SingleModifer, HexDecoder)
|
||||
{
|
||||
string orig = "%45 %46 x47 %4";
|
||||
|
||||
auto decode_cent = makeVirtualContainer<HexDecoder<'%'>>(orig);
|
||||
auto decode_x = makeVirtualContainer<HexDecoder<'x'>>(orig);
|
||||
|
||||
EXPECT_EQ(orig, "%45 %46 x47 %4");
|
||||
EXPECT_EQ(string(decode_cent.begin(), decode_cent.end()), "E F x47 %4");
|
||||
EXPECT_EQ(string(decode_x.begin(), decode_x.end()), "%45 %46 G %4");
|
||||
|
||||
orig = "452e462E47";
|
||||
auto decode_all = makeVirtualContainer<HexDecoder<-1>>(orig);
|
||||
EXPECT_EQ(string(decode_all.begin(), decode_all.end()), "E.F.G");
|
||||
}
|
||||
|
||||
TEST(SingleModifer, ReplaceChar)
|
||||
{
|
||||
string orig = "12+34-56-78+90-12-34+56";
|
||||
|
||||
auto plus_to_space = makeVirtualContainer<ReplaceChar<'+', ' '>>(orig);
|
||||
auto minus_to_plus = makeVirtualContainer<ReplaceChar<'-', '+'>>(orig);
|
||||
auto plus_to_minus = makeVirtualContainer<ReplaceChar<'+', '-'>>(orig);
|
||||
auto minus_to_space = makeVirtualContainer<ReplaceChar<'-', ' '>>(orig);
|
||||
auto m_to_n = makeVirtualContainer<ReplaceChar<'m', 'n'>>(orig);
|
||||
|
||||
EXPECT_EQ(orig, "12+34-56-78+90-12-34+56");
|
||||
EXPECT_EQ(string(plus_to_space.begin(), plus_to_space.end()), "12 34-56-78 90-12-34 56");
|
||||
EXPECT_EQ(string(minus_to_plus.begin(), minus_to_plus.end()), "12+34+56+78+90+12+34+56");
|
||||
EXPECT_EQ(string(plus_to_minus.begin(), plus_to_minus.end()), "12-34-56-78-90-12-34-56");
|
||||
EXPECT_EQ(string(minus_to_space.begin(), minus_to_space.end()), "12+34 56 78+90 12 34+56");
|
||||
EXPECT_EQ(string(m_to_n.begin(), m_to_n.end()), orig);
|
||||
}
|
||||
|
||||
class ReplaceOne : public ReplaceSubContiners<string>
|
||||
{
|
||||
public:
|
||||
ReplaceOne() { init(&src, &dst); }
|
||||
|
||||
private:
|
||||
string src = "111";
|
||||
string dst = "222";
|
||||
};
|
||||
|
||||
class ReplaceTwo : public ReplaceSubContiners<string>
|
||||
{
|
||||
public:
|
||||
ReplaceTwo() { init(&src, &dst); }
|
||||
|
||||
private:
|
||||
string src = "333";
|
||||
string dst = "4444";
|
||||
};
|
||||
|
||||
class ReplaceThree : public ReplaceSubContiners<string>
|
||||
{
|
||||
public:
|
||||
ReplaceThree() { init(&src, &dst); }
|
||||
|
||||
private:
|
||||
string src = "555";
|
||||
string dst = "44";
|
||||
};
|
||||
|
||||
TEST(SingleModifer, ReplaceSubContiners)
|
||||
{
|
||||
string orig = "111 333 11 555 1111";
|
||||
|
||||
auto replace_one = makeVirtualContainer<ReplaceOne>(orig);
|
||||
auto replace_two = makeVirtualContainer<ReplaceTwo>(orig);
|
||||
auto replace_three = makeVirtualContainer<ReplaceThree>(orig);
|
||||
|
||||
EXPECT_EQ(orig, "111 333 11 555 1111");
|
||||
EXPECT_EQ(string(replace_one.begin(), replace_one.end()), "222 333 11 555 2221");
|
||||
EXPECT_EQ(string(replace_two.begin(), replace_two.end()), "111 4444 11 555 1111");
|
||||
EXPECT_EQ(string(replace_three.begin(), replace_three.end()), "111 333 11 44 1111");
|
||||
}
|
||||
|
||||
TEST(MultipleModifier, TwoModifiers)
|
||||
{
|
||||
string orig = " 4 5 2 e 4 6 2 E 4 7 ";
|
||||
auto decode_one = makeVirtualContainer<CharRemover<' '>>(orig);
|
||||
auto decode_two = makeVirtualContainer<HexDecoder<-1>>(decode_one);
|
||||
EXPECT_EQ(string(decode_two.begin(), decode_two.end()), "E.F.G");
|
||||
}
|
||||
|
||||
using CombinedModifier = ModifiersAggregator<HexDecoder<-1>, CharRemover<' '>>;
|
||||
|
||||
TEST(MultipleModifier, CombinedModifier)
|
||||
{
|
||||
string orig = " 4 5 2 e 4 6 2 E 4 7 ";
|
||||
auto decode = makeVirtualContainer<CombinedModifier>(orig);
|
||||
EXPECT_EQ(string(decode.begin(), decode.end()), "E.F.G");
|
||||
}
|
Reference in New Issue
Block a user