@@ -162,19 +162,13 @@ void dds::build(const build_params& params, const package_manifest& man) { | |||
plan.archive_all(env, params.parallel_jobs); | |||
plan.link_all(env, params.parallel_jobs); | |||
// int n_test_fails = 0; | |||
// for (path_ref test_exe : all_tests) { | |||
// spdlog::info("Running test: {}", fs::relative(test_exe, params.out_root).string()); | |||
// const auto test_res = run_proc({test_exe.string()}); | |||
// if (!test_res.okay()) { | |||
// spdlog::error("TEST FAILED\n{}", test_res.output); | |||
// n_test_fails++; | |||
// } | |||
// } | |||
// if (n_test_fails) { | |||
// throw compile_failure("Test failures during build"); | |||
// } | |||
auto test_failures = plan.run_all_tests(env, params.parallel_jobs); | |||
for (auto& failures : test_failures) { | |||
spdlog::error("Test {} failed! Output:\n{}[dds - test output end]", failures.executable_path.string(), failures.output); | |||
} | |||
if (!test_failures.empty()) { | |||
throw compile_failure("Test failures during the build!"); | |||
} | |||
if (params.do_export) { | |||
export_project(pkg, env); |
@@ -5,6 +5,7 @@ | |||
#include <spdlog/spdlog.h> | |||
#include <chrono> | |||
#include <algorithm> | |||
#include <cassert> | |||
@@ -41,3 +42,32 @@ void link_executable_plan::link(build_env_ref env, const library_plan& lib) cons | |||
proc_res.output)); | |||
} | |||
} | |||
bool link_executable_plan::is_app() const noexcept { | |||
return _main_compile.source().kind == source_kind::app; | |||
} | |||
bool link_executable_plan::is_test() const noexcept { | |||
return _main_compile.source().kind == source_kind::test; | |||
} | |||
std::optional<test_failure> link_executable_plan::run_test(build_env_ref env) const { | |||
auto exe_path = calc_executable_path(env); | |||
auto msg = fmt::format("Run test: {:30}", fs::relative(exe_path, env.output_root).string()); | |||
spdlog::info(msg); | |||
auto start = std::chrono::high_resolution_clock::now(); | |||
auto res = run_proc({exe_path}); | |||
auto end = std::chrono::high_resolution_clock::now(); | |||
auto dur = std::chrono::duration_cast<std::chrono::microseconds>(end - start); | |||
if (res.okay()) { | |||
spdlog::info("{} - PASSED in {:>6n}μs", msg, dur.count()); | |||
return std::nullopt; | |||
} else { | |||
spdlog::error("{} - FAILED in {:>6n}μs [exitted {}]", msg, dur.count(), res.retc); | |||
test_failure f; | |||
f.executable_path = exe_path; | |||
f.output = res.output; | |||
f.retc = res.retc; | |||
return f; | |||
} | |||
} |
@@ -11,6 +11,12 @@ namespace dds { | |||
class library_plan; | |||
struct test_failure { | |||
fs::path executable_path; | |||
std::string output; | |||
int retc; | |||
}; | |||
class link_executable_plan { | |||
std::vector<fs::path> _input_libs; | |||
compile_file_plan _main_compile; | |||
@@ -32,6 +38,10 @@ public: | |||
fs::path calc_executable_path(const build_env& env) const noexcept; | |||
void link(const build_env&, const library_plan&) const; | |||
std::optional<test_failure> run_test(build_env_ref) const; | |||
bool is_test() const noexcept; | |||
bool is_app() const noexcept; | |||
}; | |||
} // namespace dds |
@@ -114,4 +114,24 @@ void build_plan::link_all(const build_env& env, int njobs) const { | |||
} | |||
} | |||
std::vector<test_failure> build_plan::run_all_tests(build_env_ref env, int njobs) const { | |||
using namespace ranges::views; | |||
auto test_executables = // | |||
iter_libraries(*this) // | |||
| transform(&library_plan::executables) // | |||
| join // | |||
| filter(&link_executable_plan::is_test) // | |||
; | |||
std::mutex mut; | |||
std::vector<test_failure> fails; | |||
parallel_run(test_executables, njobs, [&](const auto& exe) { | |||
auto fail_info = exe.run_test(env); | |||
if (fail_info) { | |||
std::scoped_lock lk{mut}; | |||
fails.emplace_back(std::move(*fail_info)); | |||
} | |||
}); | |||
return fails; | |||
} |
@@ -21,6 +21,8 @@ public: | |||
void compile_all(const build_env& env, int njobs) const; | |||
void archive_all(const build_env& env, int njobs) const; | |||
void link_all(const build_env& env, int njobs) const; | |||
std::vector<test_failure> run_all_tests(build_env_ref env, int njobs) const; | |||
}; | |||
} // namespace dds |