401 lines
11 KiB
C++
401 lines
11 KiB
C++
#include <string>
|
|
#include "../src/ro.h"
|
|
#include <functional>
|
|
#include <iostream>
|
|
#include <cstring>
|
|
|
|
|
|
using namespace std;
|
|
using namespace ro;
|
|
|
|
struct Stat{
|
|
int passed;
|
|
int total;
|
|
};
|
|
|
|
static Stat g_stat = {0,0};
|
|
|
|
#define assert(v,fmt,...) if(!(v)) { \
|
|
throw Error(ro::sfmt("ASSERT ERROR %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)); \
|
|
}
|
|
|
|
|
|
void test(const char* desc, const std::function<void()>& lambda)
|
|
{
|
|
std::cout << "Run test: " << desc << "..........";
|
|
try {
|
|
lambda();
|
|
std::cout << "OK" << std::endl;
|
|
g_stat.passed++;
|
|
}
|
|
catch(ro::Error e)
|
|
{
|
|
std::cout << "FAILED" << std::endl;
|
|
std::cout << e.what() << std::endl;
|
|
}
|
|
g_stat.total++;
|
|
}
|
|
|
|
int main(int argc, char const *argv[])
|
|
{
|
|
test("Test Option", [](){
|
|
Option<string> opt;
|
|
assert(opt.is_none(), "Option is not empty");
|
|
assert(! opt.is_some(), "Option has some value");
|
|
string text = "This is some data";
|
|
opt = text;
|
|
assert(opt.is_some(), "Option shall has some value");
|
|
assert(opt.unwrap() == text,"Value mistmatch");
|
|
});
|
|
|
|
test("Option -> Result convert", [](){
|
|
Option<string> opt;
|
|
Result<string, Error> ret = opt.ok_or(ERR("Option is null"));
|
|
assert(ret.is_err(), "Object should containe error object");
|
|
string err = ret.err().unwrap().what();
|
|
assert( err.find("Option is null") != string::npos, "Error message mistmatch");
|
|
|
|
opt = "abc";
|
|
ret = opt.ok_or(ERR("Option is null"));
|
|
assert(ret.is_ok(), "Object should contain data");
|
|
assert(ret.unwrap() == "abc", "Data mistmatch");
|
|
});
|
|
|
|
test("OPtion get_or_insert", [](){
|
|
auto x = None(int);
|
|
int y = x.get_or_insert(5);
|
|
assert(y == 5, "Unexpected value");
|
|
|
|
assert(x == 5, "Unexpected value");
|
|
});
|
|
|
|
test("Option map", [](){
|
|
auto fn = [](int x){
|
|
return "Hello";
|
|
};
|
|
|
|
Option<int> opt;
|
|
Option<string> opt1 = opt.map<string>(fn);
|
|
assert(opt.is_none() == opt1.is_none(), "Nothing shall be changed");
|
|
|
|
opt = 2;
|
|
opt1 = opt.map<string>(fn);
|
|
assert(opt1.unwrap() == "Hello", "Value mismatch");
|
|
});
|
|
|
|
|
|
test("Option map_or", [](){
|
|
auto fn = [](int x){
|
|
return ++x;
|
|
};
|
|
|
|
Option<int> opt;
|
|
int v = opt.map_or<int>(0, fn);
|
|
assert(v == 0, "Value mismatch");
|
|
|
|
opt = 2;
|
|
v = opt.map_or<int>(0, fn);
|
|
assert(v == 3, "Value mismatch %d",v);
|
|
});
|
|
|
|
test("Option filter", [](){
|
|
auto fn = [](int n) {
|
|
return n % 2 == 0;
|
|
};
|
|
//Option<int> opt = None(int).filter(fn);
|
|
assert(None(int).filter(fn).is_none(), "Filter value shall be None");
|
|
assert(Some(3).filter(fn).is_none(), "Filter value shall be None");
|
|
assert(Some(4).filter(fn).is_some(), "Filter value shall not be None");
|
|
});
|
|
|
|
test("Option OR", [](){
|
|
auto x = Some(2);
|
|
auto y = None(int);
|
|
assert((x | y) == Some(2), "Unexpected value");
|
|
|
|
x = None(int);
|
|
y = Some(100);
|
|
assert((x | y) == Some(100), "Unexpected value");
|
|
|
|
x = Some(2);
|
|
y = Some(100);
|
|
assert((x|y) == Some(2), "Unexpected value");
|
|
|
|
x = None(int);
|
|
y = None(int);
|
|
assert((x | y) == None(int), "Unexpected value");
|
|
});
|
|
|
|
test("Option AND", [](){
|
|
auto x = Some(2);
|
|
auto y = None(int);
|
|
assert((x & y) == None(int), "Unexpected value");
|
|
|
|
x = None(int);
|
|
y = Some(100);
|
|
assert((x & y) == None(int), "Unexpected value");
|
|
|
|
x = Some(2);
|
|
y = Some(100);
|
|
assert((x&y) == Some(100), "Unexpected value");
|
|
|
|
x = None(int);
|
|
y = None(int);
|
|
assert((x & y) == None(int), "Unexpected value");
|
|
});
|
|
|
|
test("Option XOR", [](){
|
|
auto x = Some(2);
|
|
auto y = None(int);
|
|
assert((x ^ y) == Some(2), "Unexpected value");
|
|
|
|
x = None(int);
|
|
y = Some(100);
|
|
assert((x ^ y) == Some(100), "Unexpected value");
|
|
|
|
x = Some(2);
|
|
y = Some(100);
|
|
assert((x^y) == None(int), "Unexpected value");
|
|
|
|
x = None(int);
|
|
y = None(int);
|
|
assert((x ^ y) == None(int), "Unexpected value");
|
|
});
|
|
|
|
test("Option or_else", [](){
|
|
auto nobody = [](){return None(int);};
|
|
auto vikings = [](){return Some(100);};
|
|
|
|
assert(None(int).or_else(vikings) == Some(100), "Unexpected value");
|
|
assert(None(int).or_else(nobody) == None(int), "Unexpected value");
|
|
|
|
assert(Some(2).or_else(vikings) == Some(2), "Unexpected value");
|
|
});
|
|
|
|
test("Option and_then", [](){
|
|
auto fn = [](int x){return string("Hello");};
|
|
|
|
assert(Some(1).and_then<string>(fn) == Some(string("Hello")), "Unexpected value");
|
|
assert(None(int).and_then<string>(fn) == None(string), "Unexpected value");
|
|
});
|
|
|
|
test("Option take", [](){
|
|
auto x = Some(2);
|
|
auto y = x.take();
|
|
|
|
assert(x == None(int), "Unexpected value");
|
|
assert(y == Some(2), "Unexpected value");
|
|
|
|
auto z = None(int);
|
|
y = z.take();
|
|
assert(x == None(int), "Unexpected value");
|
|
assert(y == None(int), "Unexpected value");
|
|
});
|
|
|
|
test("Option take_if", [](){
|
|
auto fn = [](int n) {
|
|
return n % 2 == 0;
|
|
};
|
|
auto x = Some(2);
|
|
auto y = x.take_if(fn);
|
|
|
|
assert(x == None(int), "Unexpected value");
|
|
assert(y == Some(2), "Unexpected value");
|
|
|
|
auto z = Some(3);
|
|
y = z.take_if(fn);
|
|
assert(z == Some(3), "Unexpected value");
|
|
assert(y == None(int), "Unexpected value");
|
|
});
|
|
|
|
test("Option unwrap_or", [](){
|
|
assert(Some(2).unwrap_or(4) == 2, "Unexpected value");
|
|
assert(None(int).unwrap_or(4) == 4, "Unexpected value");
|
|
|
|
assert(None(Error).unwrap_or(Error("Hello")) == Error("Hello"), "Unexpected value");
|
|
|
|
});
|
|
test("Option unwrap_or_else", [](){
|
|
assert(Some(2).unwrap_or_else([](){ return 4; }) == 2, "Unexpected value");
|
|
assert(None(int).unwrap_or_else([](){ return 4; }) == 4, "Unexpected value");
|
|
|
|
});
|
|
|
|
test("Option zip", [](){
|
|
auto x = Some(2);
|
|
auto y = Some(string("Hello"));
|
|
auto z = None(int);
|
|
|
|
assert(x.zip(y).unwrap() == std::tuple(2, string("Hello")), "Unexpected value");
|
|
|
|
assert(x.zip(z).is_none(), "Unexpected value");
|
|
|
|
});
|
|
|
|
test("Test Result", []{
|
|
Result<string, Error> ret = ERR("Error");
|
|
assert(ret.is_err(), "Object should containe error object");
|
|
ret = string("Hello");
|
|
assert(ret.is_ok(), "Object should contain data");
|
|
assert(ret.unwrap() == "Hello", "Data mistmatch");
|
|
});
|
|
|
|
test("Result->option convert",[](){
|
|
Result<string, Error> ret = ERR("Error");
|
|
Option<string> opt_v = ret.ok();
|
|
assert(opt_v.is_none(), "Value shall not be present");
|
|
Option<Error> opt_err = ret.err();
|
|
assert(opt_err.is_some(), "Erreur shall not be none");
|
|
|
|
ret = string("Hello");
|
|
opt_v = ret.ok();
|
|
assert(opt_v.is_some(), "Value shall be present");
|
|
opt_err = ret.err();
|
|
assert(opt_err.is_none(), "Erreur shall be none");
|
|
});
|
|
|
|
test("Result expect", [](){
|
|
try{
|
|
Result<string, Error> ret = ERR("Error");
|
|
auto s = ret.expect(ERR("Expect message"));
|
|
assert(false, "Should not happend");
|
|
}
|
|
catch(Error e)
|
|
{
|
|
assert(true, "%s", e.what());
|
|
}
|
|
});
|
|
|
|
test("Result map", [](){
|
|
auto err = ERR("Error");
|
|
auto fn = [](string data){
|
|
return 1;
|
|
};
|
|
Result<string, Error> ret = err;
|
|
Result<int, Error> ret1 = ret.map<int>(fn);
|
|
assert(ret1.is_err(), "mapped result shall be an error");
|
|
assert(ret1.err() == ret.err(), "Error object mistmatch");
|
|
|
|
ret = string("Hello");
|
|
ret1 = ret.map<int>(fn);
|
|
assert(ret1.is_ok(), "mapped result shall not be an error");
|
|
assert(ret1.unwrap() == 1, "Value mistmatch");
|
|
});
|
|
|
|
|
|
test("Result map_err", [](){
|
|
auto fn = [](int x){
|
|
return "Hello";
|
|
};
|
|
Result<bool, int> ret = true;
|
|
Result<bool, string> ret1 = ret.map_err<string>(fn);
|
|
assert(ret1.unwrap() == true, "Value mistmatch");
|
|
|
|
ret = 10;
|
|
ret1 = ret.map_err<string>(fn);
|
|
assert(ret1.err().unwrap() == "Hello", "Value mistmatch");
|
|
});
|
|
|
|
test("Result map_or", [](){
|
|
auto fn = [](int x){
|
|
return ++x;
|
|
};
|
|
|
|
Result<int, Error> ret = ERR("Error");
|
|
int v = ret.map_or<int>(0, fn);
|
|
assert(v == 0, "Value mismatch");
|
|
|
|
ret = 2;
|
|
v = ret.map_or<int>(0, fn);
|
|
assert(v == 3, "Value mismatch %d",v);
|
|
});
|
|
|
|
test("Result AND", [](){
|
|
Result<int, Error> x = 2;
|
|
Result<int, Error> y = Error("Hello");
|
|
assert((x&y) == Error("Hello"), "Value mismatch");
|
|
|
|
x = Error("Error1");
|
|
y = 10;
|
|
assert((x&y) == Error("Error1"), "Value mismatch");
|
|
|
|
x = Error("Error1");
|
|
y = Error("Error2");
|
|
assert((x&y) == Error("Error1"), "Value mismatch");
|
|
|
|
x = 1;
|
|
y = 10;
|
|
assert((x&y) == 10, "Value mismatch");
|
|
});
|
|
|
|
test("Result OR", [](){
|
|
Result<int, Error> x = 2;
|
|
Result<int, Error> y = Error("Hello");
|
|
assert((x|y) == 2, "Value mismatch");
|
|
|
|
x = Error("Error1");
|
|
y = 10;
|
|
assert((x|y) == 10, "Value mismatch");
|
|
|
|
x = Error("Error1");
|
|
y = Error("Error2");
|
|
assert((x|y) == Error("Error2"), "Value mismatch");
|
|
|
|
x = 1;
|
|
y = 10;
|
|
assert((x|y) == 1, "Value mismatch");
|
|
});
|
|
|
|
test("Result and_then", [](){
|
|
auto fn = [](int x){return string("Hello");};
|
|
|
|
Result<int, Error> x = 2;
|
|
auto test = Result<string,Error>(string("Hello"));
|
|
assert(x.and_then<string>(fn) == string("Hello"), "Unexpected value");
|
|
x = Error("Error");
|
|
assert(x.and_then<string>(fn) == Error("Error"), "Unexpected value");
|
|
});
|
|
|
|
test("Result or_else", [](){
|
|
auto sq = [](int x){return x*x;};
|
|
auto err = [](int x){return x;};
|
|
Result<double, int> x(2.0);
|
|
auto ret = x.or_else<int>(sq).or_else<int>(sq);
|
|
assert(ret == 2.0, "Unexpected value");
|
|
ret = x.or_else<int>(err).or_else<int>(sq);
|
|
assert(ret == 2.0, "Unexpected value");
|
|
|
|
x = 3;
|
|
ret = x.or_else<int>(sq).or_else<int>(err);
|
|
assert(ret == 9, "Unexpected value");
|
|
|
|
ret = x.or_else<int>(err).or_else<int>(err);
|
|
assert(ret == 3, "Unexpected value");
|
|
});
|
|
|
|
test("Result unwrap_err", [](){
|
|
Result<int, Error> x = Error("Hello");
|
|
assert(x.unwrap_err() == Error("Hello"), "Unexpected value");
|
|
});
|
|
|
|
test("Result unwrap_or", [](){
|
|
Result<int, Error> x = 2;
|
|
assert(x.unwrap_or(10) == 2, "Unexpected value");
|
|
|
|
x = ERR("Error");
|
|
assert(x.unwrap_or(10) == 10, "Unexpected value");
|
|
});
|
|
|
|
test("Result unwrap_or_else", [](){
|
|
auto fn = [](const Error& x){return strlen(x.what());};
|
|
Result<int, Error> x = 2;
|
|
assert(x.unwrap_or_else(fn) == 2, "Unexpected value");
|
|
|
|
x = Error("HELLO");
|
|
assert(x.unwrap_or_else(fn) == 5, "Unexpected value");
|
|
});
|
|
|
|
|
|
cout << "REPORT: " << g_stat.passed << " tests passed / " << g_stat.total << " tests." << endl;
|
|
}
|