#include #include #include #include #include #include namespace fs = std::filesystem; namespace bp = boost::process; namespace { const fs::path testpath{"testdir1"}; } class ymakeTest: public ::testing::Test { private: fs::path original_path; protected: ymakeTest() { } ~ymakeTest() override { } void SetUp() override { original_path = fs::current_path(); fs::remove_all(testpath); fs::create_directory(testpath); fs::current_path(testpath); } void TearDown() override { fs::current_path(original_path); fs::remove_all(testpath); } }; class yscanTest: public ymakeTest { }; void create_file(const fs::path& path, const std::string& contents) { Reichwein::File::setFile(path, contents); } int run_command(const std::string& command) { return bp::system(command, bp::std_out > bp::null, bp::std_err > bp::null); } int run_command(const std::string& command, std::string& output) { bp::ipstream is; bp::ipstream es; int result = bp::system(command, bp::std_out > is, bp::std_err > es); 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) { std::string output_string; int result = run_command(command, output_string); output = Reichwein::Stringhelper::split(output_string, "\r\n"); return result; } TEST_F(ymakeTest, build_one_cpp) { 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); // compile, link } TEST_F(ymakeTest, build_one_cpp_compile_error) { create_file("hello.cpp", R"(int main(int argc, char* argv[]) { retrn 0; })"); create_file("YMakefile", R"( hello hello.cpp )"); int result = run_command("../ymake"); EXPECT_NE(result, 0); } TEST_F(ymakeTest, clean_one_cpp) { 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 clean", output); EXPECT_EQ(output.size(), 0); ASSERT_EQ(result, 0); result = run_command("../ymake", output); EXPECT_EQ(output.size(), 2); // compile, link ASSERT_EQ(result, 0); result = run_command("../ymake clean", output); EXPECT_EQ(output.size(), 3); // rm .o, .d, executable ASSERT_EQ(result, 0); } TEST_F(ymakeTest, YMakefile_missing) { int result = run_command("../ymake"); EXPECT_NE(result, 0); result = run_command("../ymake clean"); EXPECT_NE(result, 0); } TEST_F(ymakeTest, build_three_cpp) { create_file("hello.cpp", R"(int main(int argc, char* argv[]) { return 0; })"); create_file("second.cpp", R"( #include "second.h" )"); create_file("second.h", R"( #pragma once )"); create_file("third.cpp", R"( )"); create_file("YMakefile", R"( hello hello.cpp second.cpp third.cpp )"); std::vector output; int result = run_command("../ymake", output); EXPECT_EQ(result, 0); EXPECT_EQ(output.size(), 4); // compile 3, link 1 } // TODO: test .c .cc .cpp // TODO: multiple builds // TODO: test tests TEST_F(yscanTest, no_cpp_file) { std::string output; int result = run_command("../yscan", output); EXPECT_EQ(result, 0); EXPECT_EQ(output, R"( testdir1 )"); } TEST_F(yscanTest, one_cpp_file) { create_file("hello.cpp", R"(int main(int argc, char* argv[]) { return 0; })"); std::string output; int result = run_command("../yscan", output); EXPECT_EQ(result, 0); EXPECT_EQ(output, R"( testdir1 hello.cpp )"); } // TODO: test multiple files // TODO: test multiple builds // TODO: test tests