diff --git a/build.sh b/build.sh index c34da5c..d2175bb 100755 --- a/build.sh +++ b/build.sh @@ -15,6 +15,10 @@ ASM_SOURCES="jump_all_gas make_all_gas ontop_all_gas" CXX_SOURCE_DIR="src" CXX_SOURCES="context_stack io concurrency" +# tests +TEST_DIR="tests" +TEST_CASES="algorithm range" + # output lib OSTD_LIB="libostd" @@ -184,6 +188,7 @@ clean() { evalv "rm -f \"$OSTD_STATIC_LIB\"" evalv "rm -f \"$OSTD_SHARED_LIB\"" evalv "rm -f test_runner.o test_runner" + evalv "rm -rf \"${TEST_DIR}\"" } # call_cxx input output [shared] @@ -234,9 +239,28 @@ build_example() { rm -f "examples/${1}.o" } +# build _test name +build_test() { + cat << EOF > "${TEST_DIR}/${1}.cc" +#define OSTD_BUILD_TESTS libostd_${1} + +#include +#include +#include + +int main() { + auto [ succ, fail ] = ostd::test::run(); + ostd::writeln(succ, " ", fail); + return 0; +} +EOF + call_cxx "${TEST_DIR}/${1}.cc" "${TEST_DIR}/${1}.o" + call_ld "${TEST_DIR}/${1}" "${TEST_DIR}/${1}.o" "$OSTD_DEFAULT_LIB" + rm -f "${TEST_DIR}/${1}.o" +} + # build test runner build_test_runner() { - OSTD_CXXFLAGS="${OSTD_CXXFLAGS} -DOSTD_DEFAULT_LIB='\"${OSTD_DEFAULT_LIB}\"'" call_cxx test_runner.cc test_runner.o call_ld test_runner test_runner.o "$OSTD_DEFAULT_LIB" rm -f test_runner.o @@ -283,12 +307,6 @@ if [ "$BUILD_SHARED" = "yes" ]; then fi evalv "rm -f $ASM_OBJ" -# build test runner -if [ "$BUILD_TESTSUITE" = "yes" ]; then - echo "Building test runner..." - build_test_runner & -fi - # build examples if [ "$BUILD_EXAMPLES" = "yes" ]; then echo "Building examples..." @@ -297,8 +315,25 @@ if [ "$BUILD_EXAMPLES" = "yes" ]; then done fi +# build test runner and tests +if [ "$BUILD_TESTSUITE" = "yes" ]; then + echo "Building tests..." + build_test_runner & + if [ ! -d "$TEST_DIR" ]; then + mkdir -p "$TEST_DIR" + fi + for test in $TEST_CASES; do + build_test "$test" & + done +fi + # wait for remaining tasks wait +# run tests if meant to +if [ "$BUILD_TESTSUITE" = "yes" ]; then + ./test_runner "$TEST_DIR" +fi + # done exit 0 diff --git a/test_runner.cc b/test_runner.cc index ba13638..e3003e9 100644 --- a/test_runner.cc +++ b/test_runner.cc @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -7,8 +7,6 @@ #include #include #include -#include -#include using namespace ostd; @@ -27,27 +25,6 @@ constexpr auto COLOR_END = ""; #define popen _popen #endif -#ifndef OSTD_DEFAULT_LIB -#define OSTD_DEFAULT_LIB "libostd.a" -#endif - -static void write_test_src(file_stream &s, string_range modname) { - s.writefln( - "#define OSTD_BUILD_TESTS libostd_%s\n" - "\n" - "#include \n" - "#include \n" - "#include \n" - "\n" - "int main() {\n" - " auto [ succ, fail ] = ostd::test::run();\n" - " ostd::writeln(succ, \" \", fail);\n" - " return 0;\n" - "}", - modname, modname - ); -} - static void write_padded(string_range s, std::size_t n) { write(s, "..."); if ((s.size() + 3) >= n) { @@ -58,107 +35,72 @@ static void write_padded(string_range s, std::size_t n) { } } -int main() { +int main(int argc, char **argv) { /* configurable section */ - - auto compiler = env_get("CXX").value_or("c++"); - auto cxxflags = "-std=c++1z -I. -Wall -Wextra -Wshadow -Wold-style-cast " - "-Wno-missing-braces"; /* clang false positive */ - - auto userflags = env_get("CXXFLAGS").value_or(""); + char const *testdir = "tests"; + if (argc > 1) { + testdir = argv[1]; + } /* do not change past this point */ - std::atomic_int nsuccess = 0, nfailed = 0; + std::size_t nsuccess = 0, nfailed = 0; - auto print_error = [&](string_range modname, string_range fmsg) { + auto print_error = [&](string_range modname) { write_padded(modname, 20); - writeln(COLOR_RED, COLOR_BOLD, '(', fmsg, ')', COLOR_END); + writeln(COLOR_RED, COLOR_BOLD, "(runtime error)", COLOR_END); ++nfailed; }; - ostd::thread_pool tpool; - tpool.start(std::thread::hardware_concurrency()); - - filesystem::directory_iterator ds{"ostd"}; + filesystem::directory_iterator ds{testdir}; for (auto &v: ds) { auto p = filesystem::path{v}; - if ( - (!filesystem::is_regular_file(p)) || - (p.extension().string() != ".hh") - ) { + if (!filesystem::is_regular_file(p)) { continue; } - tpool.push([&, modname = p.stem().string()]() { #ifdef OSTD_PLATFORM_WIN32 - std::string exepath = ".\\test_"; - exepath += modname; - exepath += ".exe"; + if (p.extension().string() != ".exe") #else - std::string exepath = "./test_"; - exepath += modname; + if (p.extension().string() != "") #endif + { + continue; + } + auto modname = p.stem().string(); + auto exepath = p.string(); - auto cxxcmd = appender(); - format(cxxcmd, "%s -o %s %s", compiler, exepath, cxxflags); - if (!userflags.empty()) { - cxxcmd.get() += ' '; - cxxcmd.get() += userflags; - } - cxxcmd.get() += " -xc++ - -xnone "; - cxxcmd.get() += OSTD_DEFAULT_LIB; + auto rf = popen(exepath.data(), "r"); + if (!rf) { + print_error(modname); + continue; + } - /* compile */ - auto cf = popen(cxxcmd.get().data(), "w"); - if (!cf) { - print_error(modname, "compile errror"); - return; - } + int succ = 0, fail = 0; + if (fscanf(rf, "%d %d", &succ, &fail) != 2) { + pclose(rf); + print_error(modname); + continue; + } - file_stream cfs{cf}; - write_test_src(cfs, modname); + if (pclose(rf)) { + print_error(modname); + continue; + } - if (pclose(cf)) { - print_error(modname, "compile errror"); - return; - } + write_padded(modname, 20); + writefln( + "%s%s%d out of %d%s (%d failures)", + fail ? COLOR_RED : COLOR_GREEN, COLOR_BOLD, + succ, succ + fail, COLOR_END, fail + ); - /* run */ - auto rf = popen(exepath.data(), "r"); - if (!rf) { - print_error(modname, "runtime error"); - return; - } - - int succ = 0, fail = 0; - if (fscanf(rf, "%d %d", &succ, &fail) != 2) { - print_error(modname, "runtime error"); - } - - if (pclose(rf)) { - print_error(modname, "runtime error"); - return; - } - - write_padded(modname, 20); - writefln( - "%s%s%d out of %d%s (%d failures)", - fail ? COLOR_RED : COLOR_GREEN, COLOR_BOLD, - succ, succ + fail, COLOR_END, fail - ); - - remove(exepath.data()); - if (fail) { - ++nfailed; - } else { - ++nsuccess; - } - }); + if (fail) { + ++nfailed; + } else { + ++nsuccess; + } } - /* wait for tasks */ - tpool.destroy(); - writeln("\n", COLOR_BLUE, COLOR_BOLD, "testing done:", COLOR_END); writeln(COLOR_GREEN, "SUCCESS: ", int(nsuccess), COLOR_END); writeln(COLOR_RED, "FAILURE: ", int(nfailed), COLOR_END);