summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Builder.cpp2
-rw-r--r--Makefile25
-rw-r--r--file.cpp2
-rw-r--r--test-ymake.cpp151
4 files changed, 176 insertions, 4 deletions
diff --git a/Builder.cpp b/Builder.cpp
index cbe6466..c59aec8 100644
--- a/Builder.cpp
+++ b/Builder.cpp
@@ -231,7 +231,7 @@ void Builder::build_file(const fs::path& p) {
for (auto &i: objects) {
command += fmt::format(" {}", i.string());
}
- command += " -lfmt -lreichwein";
+ command += " -lreichwein -lfmt";
command += fmt::format(" -o {}", p.string());
}
diff --git a/Makefile b/Makefile
index 4a8438a..914831d 100644
--- a/Makefile
+++ b/Makefile
@@ -7,10 +7,19 @@ YSCAN=yscan
YSCAN_SRC=yscan-main.cpp yscan.cpp file.cpp
YSCAN_OBJ=$(YSCAN_SRC:.cpp=.o)
+TEST=test-ymake
+TEST_SRC=test-ymake.cpp
+TEST_OBJ=$(TEST_SRC:.cpp=.o)
+
all: $(PROJECTNAME) $(YSCAN)
-LDLIBS += -lfmt -lreichwein
-CXXFLAGS += -std=c++17
+LDLIBS += -lreichwein -lfmt
+CXXFLAGS += \
+ -std=c++17 \
+ -I/usr/src/googletest/googletest/include \
+ -I/usr/src/googletest/googlemock/include \
+ -I/usr/src/googletest/googletest \
+ -I/usr/src/googletest/googlemock
$(PROJECTNAME): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@
@@ -18,9 +27,21 @@ $(PROJECTNAME): $(OBJ)
$(YSCAN): $(YSCAN_OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@
+$(TEST): libgmock.a $(TEST_OBJ)
+ $(CXX) $(LDFLAGS) $^ $(LDLIBS) $(LIBS) -o $@
+
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
+libgmock.a:
+ $(CXX) $(CXXFLAGS) -c /usr/src/googletest/googletest/src/gtest-all.cc
+ $(CXX) $(CXXFLAGS) -c /usr/src/googletest/googlemock/src/gmock-all.cc
+ $(CXX) $(CXXFLAGS) -c /usr/src/googletest/googlemock/src/gmock_main.cc
+ ar -rv libgmock.a gmock-all.o gtest-all.o gmock_main.o
+
+test: $(TEST)
+ ./$(TEST)
+
install:
mkdir -p $(DESTDIR)/usr/bin
cp $(PROJECTNAME) $(DESTDIR)/usr/bin/
diff --git a/file.cpp b/file.cpp
index 823d723..9912d29 100644
--- a/file.cpp
+++ b/file.cpp
@@ -13,7 +13,7 @@ bool is_buildable_by_extension(const fs::path& p) {
}
namespace {
- std::unordered_set<fs::path> compile_unit_source_types{".cpp", ".c"};
+ std::unordered_set<fs::path> compile_unit_source_types{".cpp", ".c", ".cc", ".S", ".rs"};
}
// type of file is source of compile unit (no included types like headers)
diff --git a/test-ymake.cpp b/test-ymake.cpp
new file mode 100644
index 0000000..a4d9aa4
--- /dev/null
+++ b/test-ymake.cpp
@@ -0,0 +1,151 @@
+#include <filesystem>
+#include <string>
+
+#include <boost/process.hpp>
+
+#include <gtest/gtest.h>
+
+#include <libreichwein/file.h>
+#include <libreichwein/stringhelper.h>
+
+namespace fs = std::filesystem;
+namespace bp = boost::process;
+
+namespace {
+ const fs::path testpath{"testdir1"};
+}
+
+class BuildTest: public ::testing::Test
+{
+private:
+ fs::path original_path;
+
+protected:
+ BuildTest() {
+ }
+
+ ~BuildTest() 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);
+ }
+
+};
+
+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::vector<std::string>& output)
+{
+ bp::ipstream is;
+ bp::ipstream es;
+ int result = bp::system(command, bp::std_out > is, bp::std_err > es);
+ std::string output_string(std::istreambuf_iterator<char>(is), {});
+ output_string += std::string(std::istreambuf_iterator<char>(es), {});
+ output = Reichwein::Stringhelper::split(output_string, "\r\n");
+
+ return result;
+}
+
+TEST_F(BuildTest, build_one_cpp)
+{
+ 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); // compile, link
+}
+
+TEST_F(BuildTest, build_one_cpp_compile_error)
+{
+ create_file("hello.cpp", R"(int main(int argc, char* argv[])
+{
+ retrn 0;
+})");
+
+ create_file("YMakefile", R"(
+<ymake>
+ <build>
+ <name>hello</name>
+ <source>hello.cpp</source>
+ </build>
+</ymake>
+)");
+
+ int result = run_command("../ymake");
+ EXPECT_NE(result, 0);
+}
+
+TEST_F(BuildTest, clean_one_cpp)
+{
+ 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 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(BuildTest, YMakefile_missing)
+{
+ int result = run_command("../ymake");
+ EXPECT_NE(result, 0);
+
+ result = run_command("../ymake clean");
+ EXPECT_NE(result, 0);
+}
+