From bfdb4e9d2cfc7890c5f194e670039fa76c391330 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Fri, 10 May 2024 15:09:50 +0200 Subject: Added tests --- test-ymake.cpp | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 342 insertions(+), 13 deletions(-) (limited to 'test-ymake.cpp') diff --git a/test-ymake.cpp b/test-ymake.cpp index 1df3ce0..3aea372 100644 --- a/test-ymake.cpp +++ b/test-ymake.cpp @@ -1,5 +1,6 @@ #include #include +#include #include @@ -8,6 +9,8 @@ #include #include +#include "file.h" + namespace fs = std::filesystem; namespace bp = boost::process; @@ -54,26 +57,36 @@ void create_file(const fs::path& path, const std::string& contents) Reichwein::File::setFile(path, contents); } -int run_command(const std::string& command) +boost::process::environment env_from_map(const std::unordered_map& map) +{ + boost::process::environment result{boost::this_process::environment()}; + + for (const auto& pair: map) { + result[pair.first] = pair.second; + } + return result; +} + +int run_command(const std::string& command, const std::unordered_map& envmap = {}) { - return bp::system(command, bp::std_out > bp::null, bp::std_err > bp::null); + return bp::system(command, bp::std_out > bp::null, bp::std_err > bp::null, env_from_map(envmap)); } -int run_command(const std::string& command, std::string& output) +int run_command(const std::string& command, std::string& output, const std::unordered_map& envmap = {}) { bp::ipstream is; bp::ipstream es; - int result = bp::system(command, bp::std_out > is, bp::std_err > es); + int result = bp::system(command, bp::std_out > is, bp::std_err > es, env_from_map(envmap)); output = std::string(std::istreambuf_iterator(is), {}); output += std::string(std::istreambuf_iterator(es), {}); return result; } -int run_command(const std::string& command, std::vector& output) +int run_command(const std::string& command, std::vector& output, const std::unordered_map& envmap = {}) { std::string output_string; - int result = run_command(command, output_string); + int result = run_command(command, output_string, envmap); output = Reichwein::Stringhelper::split(output_string, "\r\n"); return result; @@ -212,10 +225,272 @@ TEST_F(ymakeTest, build_three_cpp) EXPECT_TRUE(!fs::exists("hello")); } -// TODO: test file extensions .c .cc .cpp -// TODO: multiple builds -// TODO: test tests -// TODO: test g++/clang++ +TEST_F(ymakeTest, build_cpp_c_cc) +{ + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("second.c", R"()"); + create_file("third.cc", R"()"); + + create_file("YMakefile", R"( + + + hello + hello.cpp + second.c + third.cc + + +)"); + + std::vector output; + int result = run_command("../ymake", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 4); // 3 compile, 1 link +} + +TEST_F(ymakeTest, multiple_builds) +{ + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("second.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + create_file("third.cpp", R"()"); + + create_file("YMakefile", R"( + + + hello + hello.cpp + + + second + second.cpp + third.cpp + + +)"); + + std::vector output; + int result = run_command("../ymake", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 5); // 3 compile, 2 link +} + +TEST_F(ymakeTest, build_and_test) +{ + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("second.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + create_file("third.cpp", R"()"); + + create_file("YMakefile", R"( + + + hello + hello.cpp + + + second + second.cpp + third.cpp + + +)"); + + std::vector output; + int result = run_command("../ymake", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 2); // 1 compile, 1 link + + result = run_command("../ymake test", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 4); // 2 compile, 1 link, 1 test + + result = run_command("../ymake clean", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 8); // hello second hello.o second.o thord.o hello.d second.d third.d + + result = run_command("../ymake clean", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 0); +} + +TEST_F(ymakeTest, build_and_no_test_defined) +{ + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("YMakefile", R"( + + + hello + hello.cpp + + +)"); + + std::vector output; + int result = run_command("../ymake", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 2); // 1 compile, 1 link + + result = run_command("../ymake test", output); + EXPECT_EQ(result, 0); + + ASSERT_EQ(output.size(), 1); + EXPECT_EQ(output[0], "Everything up to date."); +} + +TEST_F(ymakeTest, test_fail) +{ + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("test-hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 1; +})"); + + create_file("YMakefile", R"( + + + hello + hello.cpp + + + test-hello + test-hello.cpp + + +)"); + + std::vector output; + int result = run_command("../ymake", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output.size(), 2); // 1 compile, 1 link + + result = run_command("../ymake test", output); + EXPECT_EQ(result, 1); + + ASSERT_EQ(output.size(), 4); // 1 compile, 1 link, test: run, exit code +} + +TEST_F(ymakeTest, test_only) +{ + create_file("test-hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("YMakefile", R"( + + + test-hello + test-hello.cpp + + +)"); + + std::vector output; + int result = run_command("../ymake", output); + EXPECT_EQ(result, 0); + + ASSERT_EQ(output.size(), 1); + EXPECT_EQ(output[0], "Everything up to date."); + + result = run_command("../ymake test", output); + EXPECT_EQ(result, 0); + + ASSERT_EQ(output.size(), 3); // 1 compile, 1 link, test: run +} + +TEST_F(ymakeTest, build_with_gcc) +{ + if (!is_executable("g++")) { + GTEST_SKIP() << "g++ not available"; + } + + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("YMakefile", R"( + + + hello + hello.cpp + + +)"); + + std::vector output; + int result = run_command("../ymake", output, {{"CXX", "g++"}}); + EXPECT_EQ(result, 0); + + ASSERT_EQ(output.size(), 2); // compile, link + for (const auto&i: output) { + EXPECT_EQ(i.substr(0, 4), "g++ "); + } +} + +TEST_F(ymakeTest, build_with_clang) +{ + if (!is_executable("clang++")) { + GTEST_SKIP() << "clang++ not available"; + } + + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("YMakefile", R"( + + + hello + hello.cpp + + +)"); + + std::vector output; + int result = run_command("../ymake", output, {{"CXX", "clang++"}}); + EXPECT_EQ(result, 0); + + ASSERT_EQ(output.size(), 2); // compile, link + for (const auto&i: output) { + EXPECT_EQ(i.substr(0, 8), "clang++ "); + } +} + // TODO: multiple dirs / YMakefiles TEST_F(yscanTest, no_cpp_file) @@ -252,7 +527,7 @@ TEST_F(yscanTest, one_cpp_file) )"); } -TEST_F(yscanTest, one_three_files) +TEST_F(yscanTest, four_files) { create_file("hello.cpp", R"(int main(int argc, char* argv[]) { @@ -278,6 +553,60 @@ TEST_F(yscanTest, one_three_files) )"); } -// TODO: test multiple builds -// TODO: test tests +TEST_F(yscanTest, tests) +{ + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + create_file("test-second.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + create_file("test-third.cpp", R"()"); + + std::string output; + int result = run_command("../yscan", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output, R"( + + testdir1 + hello.cpp + + + test-testdir1 + test-second.cpp + test-third.cpp + + +)"); +} + +TEST_F(yscanTest, unrelated_files) +{ + create_file("hello.cpp", R"(int main(int argc, char* argv[]) +{ + return 0; +})"); + + create_file("Makefile", ""); + create_file("other.h", ""); + create_file("second.rb", ""); + create_file("third.d", ""); + + std::string output; + int result = run_command("../yscan", output); + EXPECT_EQ(result, 0); + + EXPECT_EQ(output, R"( + + testdir1 + hello.cpp + + +)"); +} + +// TODO: test multiple directories -- cgit v1.2.3