First release of open-appsec source code

This commit is contained in:
roybarda
2022-10-26 19:33:19 +03:00
parent 3883109caf
commit a883352f79
1353 changed files with 276290 additions and 1 deletions

View 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
View 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
View 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");
}

View 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);
}

View 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
View 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());
}

View 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));
}

View 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");
}