summaryrefslogtreecommitdiffhomepage
path: root/test-ymake.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2024-05-10 15:09:50 +0200
committerRoland Reichwein <mail@reichwein.it>2024-05-10 15:09:50 +0200
commitbfdb4e9d2cfc7890c5f194e670039fa76c391330 (patch)
tree2584a736ed6f2827c39420882555a154d7b5d570 /test-ymake.cpp
parent6086ec079a31276c81decdd7b5b5daaafdeb58ca (diff)
Added tests
Diffstat (limited to 'test-ymake.cpp')
-rw-r--r--test-ymake.cpp355
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