summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/ctor.cc91
-rw-r--r--test/paths.h15
-rw-r--r--test/source_type_test.cc76
-rw-r--r--test/suite/ctor_files/ctor.cc.bar62
-rw-r--r--test/suite/ctor_files/ctor.cc.base62
-rw-r--r--test/suite/ctor_files/ctor.cc.multi64
-rw-r--r--test/suite/foobar.h3
-rw-r--r--test/suite/hello.cc6
-rwxr-xr-xtest/suite/test.sh104
-rw-r--r--test/tasks_test.cc106
-rw-r--r--test/testmain.cc36
-rw-r--r--test/tools_test.cc212
m---------test/uunit0
13 files changed, 775 insertions, 62 deletions
diff --git a/test/ctor.cc b/test/ctor.cc
index 8080d61..9b690a2 100644
--- a/test/ctor.cc
+++ b/test/ctor.cc
@@ -5,7 +5,7 @@
namespace
{
-BuildConfigurations ctorTestConfigs()
+BuildConfigurations ctorTestConfigs(const Settings& settings)
{
return
{
@@ -14,13 +14,16 @@ BuildConfigurations ctorTestConfigs()
.target = "execute_test",
.sources = {
"execute_test.cc",
- "uunit/uunit.cc",
+ "testmain.cc",
"../src/execute.cc",
},
- .cxxflags = {
- "-std=c++17", "-O3", "-s", "-Wall", "-Werror",
- "-I../src", "-Iuunit",
- "-DOUTPUT=\"execute\"",
+ .flags = {
+ .cxxflags = {
+ "-std=c++20", "-O3", "-s", "-Wall", "-Werror",
+ "-I../src", "-Iuunit",
+ "-DOUTPUT=\"execute\"",
+ },
+ .ldflags = { "-pthread" },
},
},
{
@@ -28,13 +31,77 @@ BuildConfigurations ctorTestConfigs()
.target = "tasks_test",
.sources = {
"tasks_test.cc",
- "uunit/uunit.cc",
+ "testmain.cc",
},
- .depends = {"libctor.a"},
- .cxxflags = {
- "-std=c++17", "-O3", "-s", "-Wall", "-Werror",
- "-I../src", "-Iuunit",
- "-DOUTPUT=\"tasks\"",
+ .depends = { "libctor_nomain.a" },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20", "-O3", "-s", "-Wall", "-Werror",
+ "-I../src", "-Iuunit",
+ "-DOUTPUT=\"tasks\"",
+ },
+ .ldflags = { "-pthread" },
+ },
+ },
+ {
+ .type = TargetType::UnitTest,
+ .target = "source_type_test",
+ .sources = {
+ "source_type_test.cc",
+ "testmain.cc",
+ },
+ .depends = { "libctor_nomain.a" },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20", "-O3", "-s", "-Wall", "-Werror",
+ "-I../src", "-Iuunit",
+ "-DOUTPUT=\"source_type\"",
+ },
+ .ldflags = { "-pthread" },
+ },
+ },
+ {
+ .type = TargetType::UnitTest,
+ .target = "tools_test",
+ .sources = {
+ "tools_test.cc",
+ "testmain.cc",
+ "../src/tools.cc",
+ },
+ //.depends = { "libctor_nomain.a" },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20", "-O3", "-Wall", "-Werror",
+ "-I../src", "-Iuunit",
+ "-DOUTPUT=\"tools\"",
+ },
+ },
+ },
+ {
+ .type = TargetType::UnitTestLib,
+ .target = "libctor_nomain.a",
+ .sources = {
+ "../src/build.cc",
+ "../src/configure.cc",
+ "../src/execute.cc",
+ "../src/rebuild.cc",
+ "../src/tasks.cc",
+ "../src/task.cc",
+ "../src/task_ar.cc",
+ "../src/task_cc.cc",
+ "../src/task_fn.cc",
+ "../src/task_ld.cc",
+ "../src/task_so.cc",
+ "../src/tools.cc",
+ "../src/util.cc",
+ "../src/externals_manual.cc",
+ },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20", "-O3", "-s", "-Wall", "-Werror",
+ "-I../src",
+ },
+ .ldflags = { "-pthread" },
},
},
};
diff --git a/test/paths.h b/test/paths.h
new file mode 100644
index 0000000..f149972
--- /dev/null
+++ b/test/paths.h
@@ -0,0 +1,15 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#pragma once
+
+#include <string>
+#include <filesystem>
+
+namespace paths
+{
+extern std::string argv_0;
+extern std::filesystem::path top_srcdir;
+extern std::filesystem::path top_builddir;
+extern std::filesystem::path testdir;
+}
diff --git a/test/source_type_test.cc b/test/source_type_test.cc
new file mode 100644
index 0000000..ed7e783
--- /dev/null
+++ b/test/source_type_test.cc
@@ -0,0 +1,76 @@
+#include <uunit.h>
+
+#include <libctor.h>
+#include <task_cc.h>
+
+std::ostream& operator<<(std::ostream& stream, const Language& lang)
+{
+ switch(lang)
+ {
+ case Language::Auto:
+ stream << "Language::Auto";
+ break;
+ case Language::C:
+ stream << "Language::C";
+ break;
+ case Language::Cpp:
+ stream << "Language::Cpp";
+ break;
+ case Language::Asm:
+ stream << "Language::Asm";
+ break;
+ }
+
+ return stream;
+}
+class TestableTaskCC
+ : public TaskCC
+{
+public:
+ TestableTaskCC(const Source& source)
+ : TaskCC({}, {}, "build", source)
+ {}
+
+ Language language() const
+ {
+ return source_language;
+ }
+};
+
+class SourceTypeTest
+ : public uUnit
+{
+public:
+ SourceTypeTest()
+ {
+ uTEST(SourceTypeTest::test);
+ }
+
+ void test()
+ {
+ { // c++
+ TestableTaskCC task("hello.cc");
+ uASSERT_EQUAL(Language::Cpp, task.language());
+ }
+
+ { // c
+ TestableTaskCC task("hello.c");
+ uASSERT_EQUAL(Language::C, task.language());
+ }
+
+ { // asm
+ TestableTaskCC task("hello.s");
+ uASSERT_EQUAL(Language::Asm, task.language());
+ }
+
+ { // custom/explicit language
+ TestableTaskCC task( {"hello.foo", Language::Asm} );
+ uASSERT_EQUAL(Language::Asm, task.language());
+ }
+
+ // Note: Failure state will result in exit(1) so cannot be tested
+ }
+};
+
+// Registers the fixture into the 'registry'
+static SourceTypeTest test;
diff --git a/test/suite/ctor_files/ctor.cc.bar b/test/suite/ctor_files/ctor.cc.bar
new file mode 100644
index 0000000..92456cb
--- /dev/null
+++ b/test/suite/ctor_files/ctor.cc.bar
@@ -0,0 +1,62 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#include <libctor.h>
+//#include "config.h"
+
+namespace
+{
+BuildConfigurations ctorConfigs()
+{
+ return
+ {
+ {
+ .name = "hello",
+ .target = "hello",
+ .sources = {
+ "hello.cc",
+ },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20",
+ "-O3",
+ "-g",
+ "-Wall",
+ "-Werror",
+ },
+ },
+ .externals = {"bar"},
+ }
+ };
+}
+
+ExternalConfigurations ctorExtConfigs()
+{
+ return
+ {
+ {
+ .name = "bar",
+ .flags = {
+ .cxxflags = { "-D_A_", "-DBAR"},
+ .cflags = { "-D_B_" },
+ .ldflags = { "-D_C_" },
+ .asmflags = { "-D_D_" },
+ },
+ // Creates --with-foo-prefix arg to configure which will be used for
+ // -L and -I flags.
+ // If not specified configure will try to find them in the system paths.
+ },
+// {
+// .name = "bar",
+// .type = TargetType::ExternalPkgConfig,
+// .min_version = "0.1",
+// .max_version = "0.9",
+// // cflags, cxxflags and ldflags deduced by pkg-config tool (or parsed
+// // directly from .pc if faster)
+// },
+ };
+}
+}
+
+REG(ctorConfigs);
+REG(ctorExtConfigs);
diff --git a/test/suite/ctor_files/ctor.cc.base b/test/suite/ctor_files/ctor.cc.base
new file mode 100644
index 0000000..6c60513
--- /dev/null
+++ b/test/suite/ctor_files/ctor.cc.base
@@ -0,0 +1,62 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#include <libctor.h>
+//#include "config.h"
+
+namespace
+{
+BuildConfigurations ctorConfigs()
+{
+ return
+ {
+ {
+ .name = "hello",
+ .target = "hello",
+ .sources = {
+ "hello.cc",
+ },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20",
+ "-O3",
+ "-g",
+ "-Wall",
+ "-Werror",
+ },
+ },
+ .externals = {"bar"},
+ }
+ };
+}
+
+ExternalConfigurations ctorExtConfigs()
+{
+ return
+ {
+ {
+ .name = "bar",
+ .flags = {
+ .cxxflags = { "-D_A_", "-DFOO"},
+ .cflags = { "-D_B_" },
+ .ldflags = { "-D_C_" },
+ .asmflags = { "-D_D_" },
+ },
+ // Creates --with-foo-prefix arg to configure which will be used for
+ // -L and -I flags.
+ // If not specified configure will try to find them in the system paths.
+ },
+// {
+// .name = "bar",
+// .type = TargetType::ExternalPkgConfig,
+// .min_version = "0.1",
+// .max_version = "0.9",
+// // cflags, cxxflags and ldflags deduced by pkg-config tool (or parsed
+// // directly from .pc if faster)
+// },
+ };
+}
+}
+
+REG(ctorConfigs);
+REG(ctorExtConfigs);
diff --git a/test/suite/ctor_files/ctor.cc.multi b/test/suite/ctor_files/ctor.cc.multi
new file mode 100644
index 0000000..9db2517
--- /dev/null
+++ b/test/suite/ctor_files/ctor.cc.multi
@@ -0,0 +1,64 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#include <libctor.h>
+//#include "config.h"
+
+#include "foobar.h"
+
+namespace
+{
+BuildConfigurations ctorConfigs()
+{
+ return
+ {
+ {
+ .name = "hello",
+ .target = "hello",
+ .sources = {
+ "hello.cc",
+ },
+ .flags = {
+ .cxxflags = {
+ "-std=c++20",
+ "-O3",
+ "-g",
+ "-Wall",
+ "-Werror",
+ },
+ },
+ .externals = {"bar"},
+ }
+ };
+}
+
+ExternalConfigurations ctorExtConfigs()
+{
+ return
+ {
+ {
+ .name = "bar",
+ .flags = {
+ .cxxflags = { "-D_A_", "-DFOO"},
+ .cflags = { "-D_B_" },
+ .ldflags = { "-D_C_" },
+ .asmflags = { "-D_D_" },
+ },
+ // Creates --with-foo-prefix arg to configure which will be used for
+ // -L and -I flags.
+ // If not specified configure will try to find them in the system paths.
+ },
+// {
+// .name = "bar",
+// .type = TargetType::ExternalPkgConfig,
+// .min_version = "0.1",
+// .max_version = "0.9",
+// // cflags, cxxflags and ldflags deduced by pkg-config tool (or parsed
+// // directly from .pc if faster)
+// },
+ };
+}
+}
+
+REG(ctorConfigs);
+REG(ctorExtConfigs);
diff --git a/test/suite/foobar.h b/test/suite/foobar.h
new file mode 100644
index 0000000..e6e274e
--- /dev/null
+++ b/test/suite/foobar.h
@@ -0,0 +1,3 @@
+#pragma once
+
+// Nothing to see here
diff --git a/test/suite/hello.cc b/test/suite/hello.cc
new file mode 100644
index 0000000..06e3deb
--- /dev/null
+++ b/test/suite/hello.cc
@@ -0,0 +1,6 @@
+#include <iostream>
+
+int main()
+{
+ std::cout << "Hello\n";
+}
diff --git a/test/suite/test.sh b/test/suite/test.sh
new file mode 100755
index 0000000..c980154
--- /dev/null
+++ b/test/suite/test.sh
@@ -0,0 +1,104 @@
+#!/bin/bash
+
+function fail
+{
+ echo "*** Failure at line $1"
+ exit 1
+}
+
+function ctor
+{
+ echo "*** Running: ./ctor $*"
+ ./ctor $*
+}
+
+# Wipe the board
+rm -Rf build
+rm -f configuration.cc
+rm -f ctor
+
+cp ctor_files/ctor.cc.base ctor.cc
+
+# Compile bootstrap binary
+g++ -pthread -std=c++20 -L../../build -lctor -I../../src ctor.cc -o ctor || fail ${LINENO}
+
+# No build files should have been created yet
+[ -d build ] && fail ${LINENO}
+
+# capture md5 sum of ctor binary before configure is called
+MD5=`md5sum ctor`
+ctor configure --ctor-includedir ../../src --ctor-libdir ../../build
+
+# ctor should be rebuilt at this point, so md5 sum should have changed
+(echo $MD5 | md5sum --status -c) && fail ${LINENO}
+
+# configuration.cc should have been generated now
+[ ! -f configuration.cc ] && fail ${LINENO}
+
+# Shouldn't compile anything yet - only configure
+[ -f build/hello-hello_cc.o ] && fail ${LINENO}
+
+MD5=`md5sum ctor`
+
+# Run normally to build project
+ctor -v
+
+# Compiled object should now exist
+[ ! -f build/hello-hello_cc.o ] && fail ${LINENO}
+
+# ctor should not have been rebuilt, so md5 sum should be the same
+(echo $MD5 | md5sum --status -c) || fail ${LINENO}
+
+MOD1=`stat -c %Y build/hello-hello_cc.o`
+touch hello.cc
+sleep 1.1
+
+# Run normally to rebuild hello.cc
+ctor -v
+
+# Object file should have been recompiled
+MOD2=`stat -c %Y build/hello-hello_cc.o`
+[[ $MOD1 == $MOD2 ]] && fail ${LINENO}
+
+# Replacve -DFOO with -DBAR in foo external.cxxflags
+cp ctor_files/ctor.cc.bar ctor.cc
+
+MD5C=`md5sum configuration.cc`
+MD5=`md5sum ctor`
+MOD1=`stat -c %Y build/hello-hello_cc.o`
+sleep 1.1
+
+# Run normally to reconfigure, rebuild ctor and rebuild hello.cc
+ctor -v
+
+MOD2=`stat -c %Y build/hello-hello_cc.o`
+[[ $MOD1 == $MOD2 ]] && fail ${LINENO}
+(echo $MD5C | md5sum --status -c) && fail ${LINENO}
+(echo $MD5 | md5sum --status -c) && fail ${LINENO}
+
+cp ctor_files/ctor.cc.multi ctor.cc
+
+MD5C=`md5sum configuration.cc`
+MD5=`md5sum ctor`
+MOD1=`stat -c %Y build/hello-hello_cc.o`
+sleep 1.1
+
+# Run normally to reconfigure, rebuild ctor and rebuild hello.cc
+ctor -v
+
+MOD2=`stat -c %Y build/hello-hello_cc.o`
+[[ $MOD1 == $MOD2 ]] && fail ${LINENO}
+(echo $MD5C | md5sum --status -c) && fail ${LINENO}
+(echo $MD5 | md5sum --status -c) && fail ${LINENO}
+
+# now touching foobar.h, should retrigger re-configuration
+touch foobar.h
+
+MOD1=`stat -c %Y ctor`
+sleep 1.1
+
+# Run normally to reconfigure, rebuild ctor and rebuild hello.cc
+ctor -v
+
+MOD2=`stat -c %Y ctor`
+[[ $MOD1 == $MOD2 ]] && fail ${LINENO}
diff --git a/test/tasks_test.cc b/test/tasks_test.cc
index d6515b8..2e0ffc7 100644
--- a/test/tasks_test.cc
+++ b/test/tasks_test.cc
@@ -2,11 +2,10 @@
#include <libctor.h>
#include <tasks.h>
-#include <settings.h>
namespace
{
-BuildConfigurations ctorTestConfigs1()
+BuildConfigurations ctorTestConfigs1(const Settings&)
{
return
{
@@ -20,7 +19,7 @@ BuildConfigurations ctorTestConfigs1()
};
}
-BuildConfigurations ctorTestConfigs2()
+BuildConfigurations ctorTestConfigs2(const Settings&)
{
return
{
@@ -37,6 +36,19 @@ BuildConfigurations ctorTestConfigs2()
REG(ctorTestConfigs1);
REG(ctorTestConfigs2);
+std::size_t count(const std::set<std::shared_ptr<Task>>& tasks,
+ const std::string& name)
+{
+ auto cnt{0u};
+ for(const auto& task : tasks)
+ {
+ if(task->target() == name)
+ {
+ cnt++;
+ }
+ }
+ return cnt;
+}
class TestTask
: public Task
@@ -44,7 +56,7 @@ class TestTask
public:
TestTask(const std::string& name, bool dirty,
const std::vector<std::string>& deps = {})
- : Task({})
+ : Task({}, {}, {})
, task_name(name)
, task_dirty(dirty)
, task_deps(deps)
@@ -55,6 +67,8 @@ public:
int clean() override { return 0; }
std::vector<std::string> depends() const override { return task_deps; }
std::string target() const override { return task_name; }
+ std::filesystem::path targetFile() const override { return {}; }
+ bool derived() const override { return false; }
bool dirtyInner() override { return task_dirty; }
private:
@@ -95,34 +109,26 @@ public:
void getTasks_test()
{
using namespace std::string_literals;
- Settings settings{};
+ Settings settings{ .builddir = "foo" };
{
auto tasks = getTasks(settings);
uASSERT_EQUAL(6u, tasks.size());
- auto task = tasks.begin();
- uASSERT_EQUAL("target1-foo_cc.o"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target1-bar_c.o"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target1"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target2"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target3"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target4"s, (*task)->target());
+ // Note: count() is used here because the order of
+ // std::set<std::shared_ptr<T>> is not deterministic.
+ uASSERT_EQUAL(1u, count(tasks, "target1"s));
+ uASSERT_EQUAL(1u, count(tasks, "target2"s));
+ uASSERT_EQUAL(1u, count(tasks, "target3"s));
+ uASSERT_EQUAL(1u, count(tasks, "target4"s));
+ uASSERT_EQUAL(1u, count(tasks, "test/target1-foo_cc.o"s));
+ uASSERT_EQUAL(1u, count(tasks, "test/target1-bar_c.o"s));
}
{
auto tasks = getTasks(settings, {"target1", "target3"});
uASSERT_EQUAL(4u, tasks.size());
- auto task = tasks.begin();
- uASSERT_EQUAL("target1-foo_cc.o"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target1-bar_c.o"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target1"s, (*task)->target());
- task++;
- uASSERT_EQUAL("target3"s, (*task)->target());
+ uASSERT_EQUAL(1u, count(tasks, "target1"s));
+ uASSERT_EQUAL(1u, count(tasks, "target3"s));
+ uASSERT_EQUAL(1u, count(tasks, "test/target1-foo_cc.o"s));
+ uASSERT_EQUAL(1u, count(tasks, "test/target1-bar_c.o"s));
}
{
auto tasks = getTasks(settings, {"no-such-target"});
@@ -136,8 +142,8 @@ public:
Settings settings{};
{ // Zero (Empty)
- std::list<std::shared_ptr<Task>> allTasks;
- std::list<std::shared_ptr<Task>> dirtyTasks;
+ std::set<std::shared_ptr<Task>> allTasks;
+ std::set<std::shared_ptr<Task>> dirtyTasks;
for(auto& task : dirtyTasks)
{
@@ -150,10 +156,10 @@ public:
{ // Zero (One task, no dirty)
auto task1 = std::make_shared<TestTask>("task1", false);
- std::list<std::shared_ptr<Task>> allTasks;
- allTasks.push_back(task1);
+ std::set<std::shared_ptr<Task>> allTasks;
+ allTasks.insert(task1);
- std::list<std::shared_ptr<Task>> dirtyTasks;
+ std::set<std::shared_ptr<Task>> dirtyTasks;
for(auto& task : dirtyTasks)
{
@@ -166,11 +172,11 @@ public:
{ // One (One task, one dirty)
auto task1 = std::make_shared<TestTask>("task1", true);
- std::list<std::shared_ptr<Task>> allTasks;
- allTasks.push_back(task1);
+ std::set<std::shared_ptr<Task>> allTasks;
+ allTasks.insert(task1);
- std::list<std::shared_ptr<Task>> dirtyTasks;
- dirtyTasks.push_back(task1);
+ std::set<std::shared_ptr<Task>> dirtyTasks;
+ dirtyTasks.insert(task1);
for(auto& task : dirtyTasks)
{
@@ -185,12 +191,12 @@ public:
auto task1 = std::make_shared<TestTask>("task1", false);
auto task2 = std::make_shared<TestTask>("task2", true);
- std::list<std::shared_ptr<Task>> allTasks;
- allTasks.push_back(task1);
- allTasks.push_back(task2);
+ std::set<std::shared_ptr<Task>> allTasks;
+ allTasks.insert(task1);
+ allTasks.insert(task2);
- std::list<std::shared_ptr<Task>> dirtyTasks;
- dirtyTasks.push_back(task2);
+ std::set<std::shared_ptr<Task>> dirtyTasks;
+ dirtyTasks.insert(task2);
for(auto& task : dirtyTasks)
{
@@ -207,12 +213,12 @@ public:
std::vector<std::string> deps = {"task1"};
auto task2 = std::make_shared<TestTask>("task2", true, deps);
- std::list<std::shared_ptr<Task>> allTasks;
- allTasks.push_back(task1);
- allTasks.push_back(task2);
+ std::set<std::shared_ptr<Task>> allTasks;
+ allTasks.insert(task1);
+ allTasks.insert(task2);
- std::list<std::shared_ptr<Task>> dirtyTasks;
- dirtyTasks.push_back(task2);
+ std::set<std::shared_ptr<Task>> dirtyTasks;
+ dirtyTasks.insert(task2);
for(auto& task : dirtyTasks)
{
@@ -229,13 +235,13 @@ public:
std::vector<std::string> deps = {"task1"};
auto task2 = std::make_shared<TestTask>("task2", true, deps);
- std::list<std::shared_ptr<Task>> allTasks;
- allTasks.push_back(task2);
- allTasks.push_back(task1);
+ std::set<std::shared_ptr<Task>> allTasks;
+ allTasks.insert(task2);
+ allTasks.insert(task1);
- std::list<std::shared_ptr<Task>> dirtyTasks;
- dirtyTasks.push_back(task2);
- dirtyTasks.push_back(task1);
+ std::set<std::shared_ptr<Task>> dirtyTasks;
+ dirtyTasks.insert(task2);
+ dirtyTasks.insert(task1);
for(auto& task : dirtyTasks)
{
diff --git a/test/testmain.cc b/test/testmain.cc
new file mode 100644
index 0000000..db8e22c
--- /dev/null
+++ b/test/testmain.cc
@@ -0,0 +1,36 @@
+// -*- c++ -*-
+// Distributed under the BSD 2-Clause License.
+// See accompanying file LICENSE for details.
+#define uUNIT_MAIN
+#include "uunit.h"
+
+#include <fstream>
+#include <string>
+#include <filesystem>
+
+namespace paths
+{
+std::string argv_0;
+std::filesystem::path top_srcdir;
+std::filesystem::path top_builddir;
+std::filesystem::path testdir;
+}
+
+int main(int argc, char* argv[])
+{
+ (void)argc;
+
+ paths::argv_0 = argv[0];
+
+ auto cur = std::filesystem::current_path();
+ paths::testdir = std::filesystem::path(paths::argv_0).parent_path();
+ // assuming <builddir>/test
+ paths::top_builddir = paths::testdir.parent_path();
+ paths::top_srcdir = std::filesystem::relative(cur, paths::testdir);
+
+ std::filesystem::current_path(paths::testdir);
+
+ std::ofstream xmlfile;
+ xmlfile.open("result_" OUTPUT ".xml");
+ return uUnit::runTests(xmlfile);
+}
diff --git a/test/tools_test.cc b/test/tools_test.cc
new file mode 100644
index 0000000..3e9de1b
--- /dev/null
+++ b/test/tools_test.cc
@@ -0,0 +1,212 @@
+#include <uunit.h>
+
+#include <initializer_list>
+#include <cassert>
+
+#include <tools.h>
+
+using namespace std::string_literals;
+
+namespace
+{
+std::ostream& operator<<(std::ostream& stream, const ToolChain& tool_chain)
+{
+ switch(tool_chain)
+ {
+ case ToolChain::gcc:
+ stream << "ToolChain::gcc";
+ break;
+ case ToolChain::clang:
+ stream << "ToolChain::clang";
+ break;
+ }
+ return stream;
+}
+
+std::ostream& operator<<(std::ostream& stream, const std::vector<std::string>& vs)
+{
+ bool first{true};
+ stream << "{ ";
+ for(const auto& v : vs)
+ {
+ if(!first)
+ {
+ stream << ", ";
+ }
+ stream << "'" << v << "'";
+ first = false;
+ }
+ stream << " }";
+
+ return stream;
+}
+
+std::ostream& operator<<(std::ostream& stream, opt o)
+{
+ // Adding to this enum should also imply adding to the unit-tests below
+ switch(o)
+ {
+ case opt::output: stream << "opt::output"; break;
+ case opt::debug: stream << "opt::debug"; break;
+ case opt::strip: stream << "opt::strip"; break;
+ case opt::warn_all: stream << "opt::warn_all"; break;
+ case opt::warnings_as_errors: stream << "opt::warnings_as_errors"; break;
+ case opt::generate_dep_tree: stream << "opt::generate_dep_tree"; break;
+ case opt::no_link: stream << "opt::no_link"; break;
+ case opt::include_path: stream << "opt::include_path"; break;
+ case opt::library_path: stream << "opt::library_path"; break;
+ case opt::link: stream << "opt::link"; break;
+ case opt::cpp_std: stream << "opt::cpp_std"; break;
+ case opt::build_shared: stream << "opt::build_shared"; break;
+ case opt::threads: stream << "opt::threads"; break;
+ case opt::optimization: stream << "opt::optimization"; break;
+ case opt::position_independent_code: stream << "opt::position_independent_code"; break;
+ case opt::position_independent_executable: stream << "opt::position_independent_executable"; break;
+ case opt::custom: stream << "opt::custom"; break;
+ }
+
+ return stream;
+}
+
+std::ostream& operator<<(std::ostream& stream, const std::pair<opt, std::string>& vs)
+{
+ stream << "{ " << vs.first << ", " << vs.second << " }";
+
+ return stream;
+}
+}
+
+// Controllable getConfiguration stub:
+namespace
+{
+std::string conf_host_cxx{};
+std::string conf_build_cxx{};
+}
+const std::string& getConfiguration(const std::string& key,
+ const std::string& defval)
+{
+ if(key == cfg::host_cxx)
+ {
+ return conf_host_cxx;
+ }
+
+ if(key == cfg::build_cxx)
+ {
+ return conf_build_cxx;
+ }
+
+ assert(false); // bad key
+
+ static std::string res{};
+ return res;
+}
+
+class ToolsTest
+ : public uUnit
+{
+public:
+ ToolsTest()
+ {
+ uTEST(ToolsTest::getToolChain_test);
+ uTEST(ToolsTest::getOption_toolchain_test);
+ uTEST(ToolsTest::getOption_str_test);
+ }
+
+ void getToolChain_test()
+ {
+ // host
+ conf_host_cxx = "/usr/bin/g++";
+ uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Host));
+
+ conf_host_cxx = "/usr/bin/g++-10";
+ uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Host));
+
+ conf_host_cxx = "/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0";
+ uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Host));
+
+ conf_host_cxx = "/usr/bin/clang++";
+ uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Host));
+
+ conf_host_cxx = "/usr/bin/clang++-10";
+ uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Host));
+
+ conf_host_cxx = "/usr/lib/llvm/12/bin/i686-pc-linux-gnu-clang++-12";
+ uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Host));
+
+ // build
+ conf_build_cxx = "/usr/bin/g++";
+ uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Build));
+
+ conf_build_cxx = "/usr/bin/g++-10";
+ uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Build));
+
+ conf_build_cxx = "/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0";
+ uASSERT_EQUAL(ToolChain::gcc, getToolChain(OutputSystem::Build));
+
+ conf_build_cxx = "/usr/bin/clang++";
+ uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Build));
+
+ conf_build_cxx = "/usr/bin/clang++-10";
+ uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Build));
+
+ conf_build_cxx = "/usr/lib/llvm/12/bin/i686-pc-linux-gnu-clang++-12";
+ uASSERT_EQUAL(ToolChain::clang, getToolChain(OutputSystem::Build));
+ }
+
+ void getOption_toolchain_test()
+ {
+ using sv = std::vector<std::string>;
+
+ uUnit::assert_equal(sv{ "-o", "foo" }, getOption(ToolChain::clang, opt::output, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-g" }, getOption(ToolChain::clang, opt::debug), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-s" }, getOption(ToolChain::clang, opt::strip), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Wall" }, getOption(ToolChain::clang, opt::warn_all), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Werror" }, getOption(ToolChain::clang, opt::warnings_as_errors), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-MMD" }, getOption(ToolChain::clang, opt::generate_dep_tree), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-c" }, getOption(ToolChain::clang, opt::no_link), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Ifoo" }, getOption(ToolChain::clang, opt::include_path, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Lfoo" }, getOption(ToolChain::clang, opt::library_path, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-lfoo" }, getOption(ToolChain::clang, opt::link, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-std=foo" }, getOption(ToolChain::clang, opt::cpp_std, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-shared" }, getOption(ToolChain::clang, opt::build_shared), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-pthread" }, getOption(ToolChain::clang, opt::threads), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Ofoo" }, getOption(ToolChain::clang, opt::optimization, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-fPIC" }, getOption(ToolChain::clang, opt::position_independent_code), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-fPIE" }, getOption(ToolChain::clang, opt::position_independent_executable), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-foo" }, getOption(ToolChain::clang, opt::custom, "-foo"), __FILE__, __LINE__);
+
+ uUnit::assert_equal(sv{ "-o", "foo" }, getOption(ToolChain::gcc, opt::output, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-g" }, getOption(ToolChain::gcc, opt::debug), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-s" }, getOption(ToolChain::gcc, opt::strip), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Wall" }, getOption(ToolChain::gcc, opt::warn_all), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Werror" }, getOption(ToolChain::gcc, opt::warnings_as_errors), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-MMD" }, getOption(ToolChain::gcc, opt::generate_dep_tree), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-c" }, getOption(ToolChain::gcc, opt::no_link), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Ifoo" }, getOption(ToolChain::gcc, opt::include_path, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Lfoo" }, getOption(ToolChain::gcc, opt::library_path, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-lfoo" }, getOption(ToolChain::gcc, opt::link, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-std=foo" }, getOption(ToolChain::gcc, opt::cpp_std, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-shared" }, getOption(ToolChain::gcc, opt::build_shared), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-pthread" }, getOption(ToolChain::gcc, opt::threads), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-Ofoo" }, getOption(ToolChain::gcc, opt::optimization, "foo"), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-fPIC" }, getOption(ToolChain::gcc, opt::position_independent_code), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-fPIE" }, getOption(ToolChain::gcc, opt::position_independent_executable), __FILE__, __LINE__);
+ uUnit::assert_equal(sv{ "-foo" }, getOption(ToolChain::gcc, opt::custom, "-foo"), __FILE__, __LINE__);
+ }
+
+ void getOption_str_test()
+ {
+ using p = std::pair<opt, std::string>;
+ uUnit::assert_equal(p{ opt::include_path, "foo" }, getOption("-Ifoo", ToolChain::gcc), __FILE__, __LINE__);
+ uUnit::assert_equal(p{ opt::library_path, "foo" }, getOption("-Lfoo", ToolChain::gcc), __FILE__, __LINE__);
+
+ uUnit::assert_equal(p{ opt::include_path, "foo" }, getOption("-Ifoo", ToolChain::clang), __FILE__, __LINE__);
+ uUnit::assert_equal(p{ opt::library_path, "foo" }, getOption("-Lfoo", ToolChain::clang), __FILE__, __LINE__);
+ }
+
+
+
+};
+
+// Registers the fixture into the 'registry'
+static ToolsTest test;
diff --git a/test/uunit b/test/uunit
-Subproject fd83de802d05a227cc00489f66ea70fccb4dda0
+Subproject bc078da645412c6b36ef59e635d6c35d11088c9