#include #include #include #include #include #include #include #include #include #include #include //#include "../examples/libc99/libc99.h" #include "../src/prototype.hh" void test_getters(int* c_int_p, pEp::POD& pint, int expected) { pEpLog("to_string(): " + pint.to_string()); // compare addresses pEpLog("addresses == c_int_p"); assert(pint.c_data() == c_int_p); assert(pint.data() == c_int_p); // compare values if (c_int_p != nullptr) { pEpLog("operator int(): " + std::to_string(pint)); assert(pint == *c_int_p); assert(pint == expected); // will segfault with nullptr, and this is correct pEpLog("data(): " + std::to_string(*pint.data())); assert(*pint.data() == *c_int_p); assert(*pint.data() == expected); pEpLog("c_data(): " + std::to_string(*pint.c_data())); assert(*pint.c_data() == *c_int_p); assert(*pint.c_data() == expected); } } void test_assign(int* c_int_p, pEp::POD& pint) { { pEpLogH2("assign operator"); int new_val = 23; pint = new_val; test_getters(c_int_p, pint, new_val); } { pEpLogH2("raw c_str assign"); int new_val = 23; *c_int_p = new_val; test_getters(c_int_p, pint, new_val); } } void test_getters(char** c_str_p, pEp::String& pstr, const std::string& expected) { pEpLog("to_string(): " + pstr.to_string()); // compare addresses pEpLog("addresses == c_str_p"); assert(pstr.c_data() == *c_str_p); assert(pstr.data() == c_str_p); // compare values if (*c_str_p != nullptr) { pEpLog("operator std::string(): " + std::string(pstr)); assert(std::string(pstr) == std::string(*c_str_p)); assert(std::string(pstr) == expected); // will segfault with nullptr, and this is correct pEpLog("data(): " + std::string(*pstr.data())); assert(std::string(*pstr.data()) == std::string(*c_str_p)); assert(std::string(*pstr.data()) == expected); pEpLog("c_data(): " + std::string(pstr.c_data())); assert(std::string(pstr.c_data()) == std::string(*c_str_p)); assert(std::string(pstr.c_data()) == expected); } else { std::string tmp{ pstr }; pEpLog("operator std::string(): " + tmp); assert(tmp.empty()); } } void test_assign(char** c_str_p, pEp::String& pstr) { { pEpLogH2("assign operator"); std::string new_val{ "assign operator" }; pstr = new_val; test_getters(c_str_p, pstr, new_val); } { pEpLogH2("raw c_str assign"); std::string new_val{ "raw c_str assign" }; free(*c_str_p); *c_str_p = strdup(new_val.c_str()); test_getters(c_str_p, pstr, new_val); } } int main() { // c-types are always POD // we need to handle pointer types and value types differently // pointer types need to be memory-managed (heap) // value types are being copied around (stack) static_assert(std::is_pod::value && !std::is_pointer::value, "not an integral"); static_assert( std::is_pod<::Test_enum>::value && !std::is_pointer<::Test_enum>::value, "not an integral"); static_assert( std::is_pod<::Test_struct1>::value && !std::is_pointer<::Test_struct1>::value, "not an integral"); // pEp::Utils::readKey(); pEp::Adapter::pEpLog::set_enabled(true); // POD if (1) { // VALID USAGE int init_val = 0; // new pEp::POD on int { pEpLogH1("new pEp::POD on int"); int c_int = init_val; pEp::POD pint(&c_int); test_getters(&c_int, pint, init_val); test_assign(&c_int, pint); } // equality operator { pEpLogH1("equality operator"); int c_int1 = init_val; int c_int2 = init_val; pEp::POD pint1(&c_int1); pEp::POD pint2(&c_int2); assert(pint1 == pint2); c_int2 = 23; assert(pint1 != pint2); } } // String // pEp::String::log_enabled = false; if (1) { //TODO: Test non-owning mode // INVALID USAGE // char* c_str_u; // uninitialized == INVALID // undefined behaviour, most likely "pointer being freed was not allocated" // { // char* c_str; // pEp::String pstr(c_str); // } // char* c_str_s = "fdsfs"; // statically initialized == INVALID // { // char ca[4] = { 'p', 'E', 'p'}; // char* c_str = ca; // pEp::String pstr(c_str); // } // VALID USAGE // new pEp::String on char* pointing to NULL { pEpLogH1("new pEp::String on char* pointing to NULL"); char* c_str = NULL; // nullptr pEp::String pstr(true, &c_str); test_getters(&c_str, pstr, ""); test_assign(&c_str, pstr); } std::string init_val{ "initialized c string" }; // new pEp::String on already initalized char* { pEpLogH1("new pEp::String on already initalized char*"); char* c_str = strdup(init_val.c_str()); pEp::String pstr(true, &c_str); test_getters(&c_str, pstr, init_val); test_assign(&c_str, pstr); } // bind() { pEpLogH1("bind()"); pEp::String pstr{}; char* c_str = strdup(init_val.c_str()); //TODO: PITYASSERT_THROWS pstr.bind(true, &c_str); test_getters(&c_str, pstr, init_val); test_assign(&c_str, pstr); } // equality operator { pEpLogH1("equality operator"); pEp::String pstr1{}; char* c_str1 = strdup(init_val.c_str()); char* c_str2 = strdup(init_val.c_str()); pstr1.bind(true, &c_str1); pEp::String pstr2{ true, &c_str2 }; assert(pstr1 == pstr2); pstr2 = "huhu"; assert(pstr1 != pstr2); } } // Struct if (1) { // create an instance if (1) { pEp::TestStruct1 pstruct1{ true }; // pEp::TestStruct1 pstruct1(true, 23, TWO, "pEp"); pEpLog(pstruct1.c_int); pEpLog(pstruct1.c_enum); pEpLog(pstruct1.c_str); ::Test_struct1* c_struct1 = pstruct1; pEpLog(c_struct1->c_int); pEpLog(c_struct1->c_enum); pEpLog(c_struct1->c_str); pEpLog("DONE"); } // wrap already existing instance { ::Test_struct1* c_struct1 = ::new_test_struct(0, ONE, "pEp"); pEpLog(c_struct1->c_int); pEpLog(c_struct1->c_enum); pEpLog(c_struct1->c_str); pEpLog("DONE"); pEp::TestStruct1 pstruct1(true, &c_struct1); pEpLog(pstruct1.c_int); pEpLog(pstruct1.c_enum); pEpLog(pstruct1.c_str); pEpLog("DONE"); } } }