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