add some basic unit test infra to allow testing together with impl
parent
cc8452e265
commit
d359e46818
|
@ -37,6 +37,8 @@
|
||||||
#ifndef OSTD_RANGE_HH
|
#ifndef OSTD_RANGE_HH
|
||||||
#define OSTD_RANGE_HH
|
#define OSTD_RANGE_HH
|
||||||
|
|
||||||
|
#include "ostd/unit_test.hh"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
@ -1328,6 +1330,17 @@ inline auto range(T v) {
|
||||||
return detail::number_range<T>(v);
|
return detail::number_range<T>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OSTD_UNIT_TEST(range, {
|
||||||
|
auto r = range(5, 10, 2);
|
||||||
|
fail_if(r.empty() || (r.front() != 5));
|
||||||
|
r.pop_front();
|
||||||
|
fail_if(r.empty() || (r.front() != 7));
|
||||||
|
r.pop_front();
|
||||||
|
fail_if(r.empty() || (r.front() != 9));
|
||||||
|
r.pop_front();
|
||||||
|
fail_if(!r.empty());
|
||||||
|
});
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct reverse_range: input_range<reverse_range<T>> {
|
struct reverse_range: input_range<reverse_range<T>> {
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/** @defgroup Testing
|
||||||
|
*
|
||||||
|
* @brief Reusable unit test infrastructure.
|
||||||
|
*
|
||||||
|
* This module defines header-only infra for unit tests that can be used to
|
||||||
|
* integrate tests directly where the implementation is. All you really need
|
||||||
|
* to do then is enable a macro, include the file you're testing and compile
|
||||||
|
* into an executable.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file unit_test.hh
|
||||||
|
*
|
||||||
|
* @brief The unit test infrastructure implementation.
|
||||||
|
*
|
||||||
|
* Include this at the very beginning in the files you want to define unit
|
||||||
|
* tests in. It has no dependencies within libostd.
|
||||||
|
*
|
||||||
|
* @copyright See COPYING.md in the project tree for further information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OSTD_UNIT_TEST_HH
|
||||||
|
#define OSTD_UNIT_TEST_HH
|
||||||
|
|
||||||
|
#ifdef OSTD_BUILD_TESTS
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
#include <stdexcept>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ostd {
|
||||||
|
namespace test {
|
||||||
|
|
||||||
|
/** @addtogroup Testing
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef OSTD_BUILD_TESTS
|
||||||
|
|
||||||
|
#define OSTD_TEST_MODULE_STRINGIFY(x) #x
|
||||||
|
#define OSTD_TEST_MODULE_STR(x) OSTD_TEST_MODULE_STRINGIFY(x)
|
||||||
|
#define OSTD_TEST_MODULE OSTD_TEST_MODULE_STR(OSTD_BUILD_TESTS)
|
||||||
|
|
||||||
|
static std::vector<void (*)()> test_cases;
|
||||||
|
|
||||||
|
static bool add_test(std::string testn, void (*func)()) {
|
||||||
|
if (testn == OSTD_TEST_MODULE) {
|
||||||
|
test_cases.push_back(func);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OSTD_UNIT_TEST(module, body) \
|
||||||
|
static bool test_case_##module##_##__LINE__ = \
|
||||||
|
ostd::test::add_test(#module, []() { using namespace ostd::test; body });
|
||||||
|
|
||||||
|
struct test_error {};
|
||||||
|
|
||||||
|
void fail_if(bool b) {
|
||||||
|
if (b) {
|
||||||
|
throw test_error{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fail_if_not(bool b) {
|
||||||
|
if (!b) {
|
||||||
|
throw test_error{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
int succ = 0, fail = 0;
|
||||||
|
for (auto &f: test_cases) {
|
||||||
|
try {
|
||||||
|
f();
|
||||||
|
} catch (test_error) {
|
||||||
|
++fail;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++succ;
|
||||||
|
}
|
||||||
|
#if defined(_WIN32) || defined(WIN32)
|
||||||
|
printf(
|
||||||
|
"%s...\t%d out of %d (%d failures)\n",
|
||||||
|
OSTD_TEST_MODULE, succ, succ + fail, fail
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
printf(
|
||||||
|
"%s...\t%s\033[1m%d out of %d\033[0m (%d failures)\n",
|
||||||
|
OSTD_TEST_MODULE, fail ? "\033[91m" : "\033[92m",
|
||||||
|
succ, succ + fail, fail
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* OSTD_BUILD_TESTS */
|
||||||
|
|
||||||
|
#define OSTD_UNIT_TEST(module, body)
|
||||||
|
|
||||||
|
#endif /* OSTD_BUILD_TESTS */
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
} /* namespace test */
|
||||||
|
} /* namespace ostd */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -36,17 +36,12 @@ int main() {
|
||||||
/* do not change past this point */
|
/* do not change past this point */
|
||||||
|
|
||||||
int nsuccess = 0, nfailed = 0;
|
int nsuccess = 0, nfailed = 0;
|
||||||
std::string modname = nullptr;
|
std::string modname;
|
||||||
|
|
||||||
auto print_result = [&](string_range fmsg = nullptr) {
|
auto print_error = [&](string_range fmsg) {
|
||||||
write(modname, "...\t");
|
write(modname, "...\t");
|
||||||
if (!fmsg.empty()) {
|
writeln(COLOR_RED, COLOR_BOLD, '(', fmsg, ')', COLOR_END);
|
||||||
writeln(COLOR_RED, COLOR_BOLD, '(', fmsg, ')', COLOR_END);
|
++nfailed;
|
||||||
++nfailed;
|
|
||||||
} else {
|
|
||||||
writeln(COLOR_GREEN, COLOR_BOLD, "(success)", COLOR_END);
|
|
||||||
++nsuccess;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
filesystem::directory_iterator ds{testdir};
|
filesystem::directory_iterator ds{testdir};
|
||||||
|
@ -70,7 +65,7 @@ int main() {
|
||||||
|
|
||||||
auto cxxcmd = appender<std::string>();
|
auto cxxcmd = appender<std::string>();
|
||||||
format(
|
format(
|
||||||
cxxcmd, "%s %s%s%s -o %s %s", compiler, testdir,
|
cxxcmd, "%s %s%s%s -o %s %s ", compiler, testdir,
|
||||||
char(filesystem::path::preferred_separator),
|
char(filesystem::path::preferred_separator),
|
||||||
p.filename(), exepath, cxxflags
|
p.filename(), exepath, cxxflags
|
||||||
);
|
);
|
||||||
|
@ -78,20 +73,24 @@ int main() {
|
||||||
cxxcmd.get() += ' ';
|
cxxcmd.get() += ' ';
|
||||||
cxxcmd.get() += userflags;
|
cxxcmd.get() += userflags;
|
||||||
}
|
}
|
||||||
|
cxxcmd.get() += ' ';
|
||||||
|
cxxcmd.get() += "-DOSTD_BUILD_TESTS=";
|
||||||
|
cxxcmd.get() += modname;
|
||||||
|
|
||||||
int ret = system(cxxcmd.get().data());
|
int ret = system(cxxcmd.get().data());
|
||||||
if (ret) {
|
if (ret) {
|
||||||
print_result("compile errror");
|
print_error("compile errror");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = system(exepath.data());
|
ret = system(exepath.data());
|
||||||
if (ret) {
|
if (ret) {
|
||||||
print_result("runtime error");
|
print_error("runtime error");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(exepath.data());
|
remove(exepath.data());
|
||||||
print_result();
|
++nsuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln("\n", COLOR_BLUE, COLOR_BOLD, "testing done:", COLOR_END);
|
writeln("\n", COLOR_BLUE, COLOR_BOLD, "testing done:", COLOR_END);
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#define OSTD_BUILD_TESTS range
|
||||||
|
|
||||||
|
#include <ostd/unit_test.hh>
|
||||||
|
#include <ostd/range.hh>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
ostd::test::run();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue