-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
382 additions
and
160 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,3 +29,7 @@ | |
|
||
example1-basic | ||
example2-mocks | ||
|
||
.qtc_clangd/ | ||
test_main | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
SRC = $(wildcard *.cpp *.h) | ||
|
||
all: example1-basic example2-mocks | ||
all: test_main | ||
|
||
example1-basic: $(SRC) | ||
g++ example1-basic.cpp -o example1-basic --std=c++14 -g | ||
example1-basic.o: $(SRC) | ||
g++ example1-basic.cpp -c -o example1-basic.o --std=c++17 -g | ||
|
||
example2-mocks.o: $(SRC) | ||
g++ example2-mocks.cpp -c -o example2-mocks.o --std=c++17 -g | ||
|
||
example2-mocks: $(SRC) | ||
g++ example2-mocks.cpp -o example2-mocks --std=c++14 -g | ||
test_main: example1-basic.o example2-mocks.o test_main.cpp | ||
g++ example1-basic.o example2-mocks.o test_main.cpp -o test_main --std=c++17 -g | ||
|
||
clean: | ||
rm -f example1-basic example2-mocks | ||
rm -f example1-basic.o example2-mocks.o test_main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
#pragma once | ||
|
||
#define PRINT_INFO std::cout << __FILE__ << ":" << __LINE__ << ": "; | ||
#define ASSERT(test_var_x, error) \ | ||
if (!(test_var_x)) { \ | ||
PRINT_INFO; \ | ||
unittest::testResult++; \ | ||
std::cout << #test_var_x << ": " << error << std::endl; \ | ||
return; \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT(test_var_x) ASSERT(test_var_x, "expression is not true") | ||
|
||
// Support old syntax | ||
#define ASSERT_EQ EXPECT_EQ | ||
#define ASSERT_NE EXPECT_NE | ||
#define ASSERT_GT EXPECT_GT | ||
#define ASSERT_LT EXPECT_LT | ||
#define ASSERT_NEAR EXPECT_LT | ||
|
||
#define EXPECT_EQ(test_var_x, test_var_y) \ | ||
if (!((test_var_x) == (test_var_y))) { \ | ||
PRINT_INFO; \ | ||
unittest::testResult++; \ | ||
std::cout << #test_var_x << " = '" << test_var_x \ | ||
<< "' is not equal to " << #test_var_y << " = '" \ | ||
<< test_var_y << "'" << std::endl; \ | ||
unittest::testResult++; \ | ||
return; \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT_NE(test_var_x, test_var_y) \ | ||
if ((test_var_x) == (test_var_y)) { \ | ||
PRINT_INFO; \ | ||
std::cout << #test_var_x << " = " << test_var_x << " is equal to " \ | ||
<< #test_var_y << " = " << test_var_y << std::endl; \ | ||
unittest::testResult++; \ | ||
return; \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT_GT(test_var_x, test_var_y) \ | ||
if (!((test_var_x) > (test_var_y))) { \ | ||
PRINT_INFO; \ | ||
std::cout << #test_var_x << " = " << test_var_x \ | ||
<< " is not greater than " << #test_var_y << " = " \ | ||
<< test_var_y << std::endl; \ | ||
unittest::testResult++; \ | ||
return; \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT_LT(test_var_x, test_var_y) \ | ||
if (!((test_var_x) < (test_var_y))) { \ | ||
PRINT_INFO; \ | ||
std::cout << #test_var_x << " = " << test_var_x \ | ||
<< " is not less than " << #test_var_y << " = " \ | ||
<< test_var_y << std::endl; \ | ||
unittest::testResult++; \ | ||
return; \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT_NEAR(test_var_x, test_var_y, test_var_e) \ | ||
{ \ | ||
auto a = (test_var_x); \ | ||
auto b = (test_var_y); \ | ||
if (a + test_var_e < b || a > b + test_var_e) { \ | ||
PRINT_INFO; \ | ||
std::cout << #test_var_x << " == " << test_var_x \ | ||
<< " is not near " << #test_var_y << std::endl; \ | ||
++testResult; \ | ||
return; \ | ||
} \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT_TRUE(expression) \ | ||
{ \ | ||
auto test_var_x = static_cast<bool>(expression); \ | ||
if (!test_var_x) { \ | ||
PRINT_INFO; \ | ||
std::cout << #expression << " == " << test_var_x \ | ||
<< " is not true as expected " << std::endl; \ | ||
++unittest::testResult; \ | ||
return; \ | ||
} \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT_FALSE(expression) \ | ||
{ \ | ||
auto test_var_x = static_cast<bool>(expression); \ | ||
if (test_var_x) { \ | ||
PRINT_INFO; \ | ||
std::cout << #expression << " == " << test_var_x \ | ||
<< " is not false as expected " << std::endl; \ | ||
++unittest::testResult; \ | ||
return; \ | ||
} \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define EXPECT_THROW(expression, error) \ | ||
{ \ | ||
bool threw = false; \ | ||
try { \ | ||
expression; \ | ||
} \ | ||
catch (error & e) { \ | ||
threw = true; \ | ||
} \ | ||
if (!threw) { \ | ||
std::cout << "Expected exeption " << #error << ": got none" \ | ||
<< std::endl; \ | ||
unittest::testResult++; \ | ||
return; \ | ||
} \ | ||
} \ | ||
unittest::semicolon() | ||
|
||
#define ERROR(error) \ | ||
PRINT_INFO; \ | ||
std::cout << error << std::endl; \ | ||
unittest::testResult++; \ | ||
return; \ | ||
unittest::semicolon() | ||
|
||
// The not implemented error is used to flag for wanted features not implemented | ||
#define ERROR_NOT_IMPLEMENTED() \ | ||
PRINT_INFO; \ | ||
std::cout << "not implemented" << std::endl; \ | ||
testResult = -1; \ | ||
return; \ | ||
unittest::semicolon() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
#pragma once | ||
|
||
#include <functional> | ||
#include <iostream> | ||
#include <list> | ||
#include <string> | ||
#include <string_view> | ||
|
||
namespace unittest { | ||
|
||
struct StaticTestSuit; | ||
|
||
struct Tests { | ||
|
||
Tests() = default; | ||
Tests(const Tests &) = delete; | ||
Tests(Tests &&) = delete; | ||
Tests &operator=(const Tests &) = delete; | ||
Tests &operator=(Tests &&) = delete; | ||
~Tests(); | ||
|
||
static Tests &instance() { | ||
static Tests reg{}; | ||
return reg; | ||
} | ||
|
||
void run(); | ||
|
||
std::vector<StaticTestSuit *> tests; | ||
}; | ||
|
||
struct StaticTestSuit { | ||
StaticTestSuit() { | ||
Tests::instance().tests.push_back(this); | ||
} | ||
|
||
struct TestEntry { | ||
std::string suit; | ||
std::string name; | ||
std::function<void()> f = {}; | ||
std::string result = {}; | ||
}; | ||
|
||
/// List instead of vector to keep position in memory | ||
std::list<TestEntry> entries; | ||
|
||
std::string testSuitName; | ||
int testResult = 0; | ||
|
||
std::function<void()> &newTest(std::string testName) { | ||
return add(testSuitName, testName); | ||
} | ||
|
||
std::function<void()> &add(std::string_view suitName, | ||
std::string_view testName) { | ||
entries.push_back({ | ||
.suit = std::string{suitName}, | ||
.name = std::string{testName}, | ||
}); | ||
return entries.back().f; | ||
} | ||
|
||
int run() { | ||
using std::cout; | ||
using std::endl; | ||
int numFailed = 0; | ||
int numSucceded = 0; | ||
int numInactive = 0; | ||
|
||
// if (!parseArguments(argc, argv)) { | ||
// return 0; | ||
// } | ||
|
||
// if (setup) { | ||
// setup(); | ||
// } | ||
|
||
cout << "==== Starts test suit " << testSuitName << " ====" << endl | ||
<< endl; | ||
|
||
for (auto &it : entries) { | ||
if (it.name.rfind("disabled ", 0) == 0) { | ||
it.result = "disabled"; | ||
// it.result = "disabled"; | ||
++numInactive; | ||
continue; | ||
} | ||
|
||
cout << "=== running test: " << it.name << " ===" << endl; | ||
testResult = 0; | ||
|
||
#ifdef DO_NOT_CATCH_ERRORS | ||
it.f(); | ||
#else | ||
try { | ||
it.f(); | ||
} | ||
catch (std::exception &e) { | ||
std::cerr << "error: " << e.what() << endl; | ||
testResult = -2; | ||
} | ||
catch (const char *c) { | ||
std::cerr << "error: " << c << endl; | ||
testResult = -2; | ||
} | ||
catch (const std::string &what) { | ||
std::cerr << "error: " << what << endl; | ||
testResult = -2; | ||
} | ||
catch (...) { | ||
std::cerr << "error" << endl; | ||
testResult = -2; | ||
} | ||
#endif | ||
if (testResult == -1) { | ||
cout << " --> not impl" << endl << endl; | ||
it.result = "not implemented"; | ||
} | ||
if (testResult == -2) { | ||
cout << " --> crashed" << endl << endl; | ||
++numFailed; | ||
it.result = "crashed!"; | ||
} | ||
else if (testResult) { | ||
cout << " --> failed" << endl << endl << endl << endl; | ||
numFailed++; | ||
it.result = "fail"; | ||
} | ||
else { | ||
cout << " --> success " << endl << endl << endl << endl; | ||
it.result = "pass"; | ||
numSucceded++; | ||
} | ||
} | ||
|
||
cout << endl; | ||
cout << "==== results: ===============================" << endl; | ||
for (auto &it : entries) { | ||
cout << it.result; | ||
for (auto i = it.result.size(); i < 15; ++i) { | ||
cout << " "; | ||
} | ||
if (it.name.rfind("disabled ", 0) == 0) { | ||
cout << " " << it.name.substr(9) << "\n"; | ||
} | ||
else { | ||
cout << " " << it.name << "\n"; | ||
} | ||
} | ||
cout << endl; | ||
if (numFailed) { | ||
cout << "TEST FAILED..."; | ||
} | ||
else { | ||
cout << "SUCCESS..."; | ||
} | ||
cout << "\n"; | ||
if (numInactive) { | ||
cout << "(Disabled: " << numInactive << ") "; | ||
} | ||
cout << "Failed: " << numFailed << " Passed: " << numSucceded << endl; | ||
|
||
return numFailed > 0; | ||
} | ||
}; | ||
|
||
// struct RegisterTestStatic { | ||
// Tests::TestEntry &entry; | ||
|
||
// RegisterTestStatic(const RegisterTestStatic &) = default; | ||
// RegisterTestStatic(RegisterTestStatic &&) = default; | ||
// RegisterTestStatic &operator=(const RegisterTestStatic &) = delete; | ||
// RegisterTestStatic &operator=(RegisterTestStatic &&) = delete; | ||
// ~RegisterTestStatic(); | ||
|
||
// RegisterTestStatic(std::string_view suitName, std::string_view testName) | ||
// : entry{Tests::instance().add(suitName, testName)} {} | ||
|
||
// RegisterTestStatic &operator=(std::function<void()> f) { | ||
// entry.f = f; | ||
// return *this; | ||
// } | ||
//}; | ||
|
||
inline Tests::~Tests() = default; | ||
|
||
inline void Tests::run() { | ||
for (auto &test : tests) { | ||
test->run(); | ||
} | ||
} | ||
|
||
} // namespace unittest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#include "unittest.h" | ||
|
||
int main(int argc, char **argv) { | ||
using namespace unittest; | ||
|
||
Tests::instance().run(); | ||
} |
Oops, something went wrong.