diff options
Diffstat (limited to 'test-ymake.cpp')
-rw-r--r-- | test-ymake.cpp | 355 |
1 files changed, 342 insertions, 13 deletions
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 <filesystem> #include <string> +#include <unordered_map> #include <boost/process.hpp> @@ -8,6 +9,8 @@ #include <libreichwein/file.h> #include <libreichwein/stringhelper.h> +#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<std::string, std::string>& 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<std::string, std::string>& 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<std::string, std::string>& 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<char>(is), {}); output += std::string(std::istreambuf_iterator<char>(es), {}); return result; } -int run_command(const std::string& command, std::vector<std::string>& output) +int run_command(const std::string& command, std::vector<std::string>& output, const std::unordered_map<std::string, std::string>& 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"( +<ymake> + <build> + <name>hello</name> + <source>hello.cpp</source> + <source>second.c</source> + <source>third.cc</source> + </build> +</ymake> +)"); + + std::vector<std::string> 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"( +<ymake> + <build> + <name>hello</name> + <source>hello.cpp</source> + </build> + <build> + <name>second</name> + <source>second.cpp</source> + <source>third.cpp</source> + </build> +</ymake> +)"); + + std::vector<std::string> 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"( +<ymake> + <build> + <name>hello</name> + <source>hello.cpp</source> + </build> + <test> + <name>second</name> + <source>second.cpp</source> + <source>third.cpp</source> + </test> +</ymake> +)"); + + std::vector<std::string> 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"( +<ymake> + <build> + <name>hello</name> + <source>hello.cpp</source> + </build> +</ymake> +)"); + + std::vector<std::string> 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"( +<ymake> + <build> + <name>hello</name> + <source>hello.cpp</source> + </build> + <test> + <name>test-hello</name> + <source>test-hello.cpp</source> + </test> +</ymake> +)"); + + std::vector<std::string> 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"( +<ymake> + <test> + <name>test-hello</name> + <source>test-hello.cpp</source> + </test> +</ymake> +)"); + + std::vector<std::string> 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"( +<ymake> + <build> + <name>hello</name> + <source>hello.cpp</source> + </build> +</ymake> +)"); + + std::vector<std::string> 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"( +<ymake> + <build> + <name>hello</name> + <source>hello.cpp</source> + </build> +</ymake> +)"); + + std::vector<std::string> 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"(<ymake> + <build> + <name>testdir1</name> + <source>hello.cpp</source> + </build> + <test> + <name>test-testdir1</name> + <source>test-second.cpp</source> + <source>test-third.cpp</source> + </test> +</ymake> +)"); +} + +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"(<ymake> + <build> + <name>testdir1</name> + <source>hello.cpp</source> + </build> +</ymake> +)"); +} + +// TODO: test multiple directories |