diff options
Diffstat (limited to 'tests')
57 files changed, 1351 insertions, 0 deletions
diff --git a/tests/ROOT b/tests/ROOT new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/ROOT diff --git a/tests/TARGETS b/tests/TARGETS new file mode 100644 index 0000000..c64245e --- /dev/null +++ b/tests/TARGETS @@ -0,0 +1,6 @@ +{ "ALL": + { "type": "install" + , "deps": [["test_cases/deps", "ALL"], ["test_cases/cflags", "ALL"]] + , "tainted": ["test"] + } +} diff --git a/tests/test_cases/cflags/TARGETS b/tests/test_cases/cflags/TARGETS new file mode 100644 index 0000000..44c99f1 --- /dev/null +++ b/tests/test_cases/cflags/TARGETS @@ -0,0 +1,19 @@ +{ "public": + { "type": ["test_rules", "test_case"] + , "name": ["cflags_public"] + , "targets": + [ "+main_use_half3" + , "+test_use_half3" + , "+main_use_half3f" + , "+test_use_half3f" + ] + , "asserts": + [ "./main_use_half3/main_use_half3 | grep 1.5" + , "[ \"$(cat ./test_use_half3/result)\" = \"PASS\" ]" + , "./main_use_half3f/main_use_half3f | grep 1.5" + , "[ \"$(cat ./test_use_half3f/result)\" = \"PASS\" ]" + ] + , "data": [["TREE", null, "public"]] + } +, "ALL": {"type": "install", "deps": ["public"], "tainted": ["test"]} +} diff --git a/tests/test_cases/cflags/public/TARGETS b/tests/test_cases/cflags/public/TARGETS new file mode 100644 index 0000000..79aadb3 --- /dev/null +++ b/tests/test_cases/cflags/public/TARGETS @@ -0,0 +1,49 @@ +{ "half": + { "type": ["@", "rules", "CC", "library"] + , "name": ["half"] + , "hdrs": ["half.hpp"] + , "srcs": ["half.cpp"] + , "cflags": ["-DHALF_PRECISION_DOUBLE"] + , "stage": ["half"] + } +, "half3": + { "type": ["@", "rules", "CC", "library"] + , "name": ["half3"] + , "hdrs": ["half3.hpp"] + , "srcs": ["half3.cpp"] + , "deps": ["half"] + , "stage": ["half3"] + } +, "half3f": + { "type": ["@", "rules", "CC", "library"] + , "name": ["half3f"] + , "hdrs": ["half3f.hpp"] + , "srcs": ["half3f.cpp"] + , "private-deps": ["half3"] + , "stage": ["half3f"] + } +, "main_use_half3": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main_use_half3"] + , "srcs": ["main_use_half3.cpp"] + , "private-deps": ["half3"] + } +, "test_use_half3": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_use_half3"] + , "srcs": ["test_use_half3.cpp"] + , "private-deps": ["half3"] + } +, "main_use_half3f": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main_use_half3f"] + , "srcs": ["main_use_half3f.cpp"] + , "private-deps": ["half3f"] + } +, "test_use_half3f": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_use_half3f"] + , "srcs": ["test_use_half3f.cpp"] + , "private-deps": ["half3f"] + } +} diff --git a/tests/test_cases/cflags/public/half.cpp b/tests/test_cases/cflags/public/half.cpp new file mode 100644 index 0000000..e26ff6e --- /dev/null +++ b/tests/test_cases/cflags/public/half.cpp @@ -0,0 +1,5 @@ +#include "half.hpp" + +HALF_RESULT_TYPE half(int val) { + return static_cast<HALF_RESULT_TYPE>(val / 2.0); +} diff --git a/tests/test_cases/cflags/public/half.hpp b/tests/test_cases/cflags/public/half.hpp new file mode 100644 index 0000000..0baebcb --- /dev/null +++ b/tests/test_cases/cflags/public/half.hpp @@ -0,0 +1,12 @@ +#ifndef HALF_HPP +#define HALF_HPP + +#ifdef HALF_PRECISION_DOUBLE +#define HALF_RESULT_TYPE double +#else +#define HALF_RESULT_TYPE int +#endif + +HALF_RESULT_TYPE half(int val); + +#endif diff --git a/tests/test_cases/cflags/public/half3.cpp b/tests/test_cases/cflags/public/half3.cpp new file mode 100644 index 0000000..484f7f8 --- /dev/null +++ b/tests/test_cases/cflags/public/half3.cpp @@ -0,0 +1,3 @@ +#include "half3.hpp" + +HALF_RESULT_TYPE half3() { return half(3); } diff --git a/tests/test_cases/cflags/public/half3.hpp b/tests/test_cases/cflags/public/half3.hpp new file mode 100644 index 0000000..271ed68 --- /dev/null +++ b/tests/test_cases/cflags/public/half3.hpp @@ -0,0 +1,8 @@ +#ifndef HALF3_HPP +#define HALF3_HPP + +#include "half/half.hpp" + +HALF_RESULT_TYPE half3(); + +#endif diff --git a/tests/test_cases/cflags/public/half3f.cpp b/tests/test_cases/cflags/public/half3f.cpp new file mode 100644 index 0000000..88b6d55 --- /dev/null +++ b/tests/test_cases/cflags/public/half3f.cpp @@ -0,0 +1,7 @@ +#include "half3/half3.hpp" + +#ifndef HALF_PRECISION_DOUBLE +#error should be defined +#endif + +float half3f() { return static_cast<float>(half3()); } diff --git a/tests/test_cases/cflags/public/half3f.hpp b/tests/test_cases/cflags/public/half3f.hpp new file mode 100644 index 0000000..1207f63 --- /dev/null +++ b/tests/test_cases/cflags/public/half3f.hpp @@ -0,0 +1,6 @@ +#ifndef BAZ_HPP +#define BAZ_HPP + +float half3f(); + +#endif diff --git a/tests/test_cases/cflags/public/main_use_half3.cpp b/tests/test_cases/cflags/public/main_use_half3.cpp new file mode 100644 index 0000000..1c9d6ba --- /dev/null +++ b/tests/test_cases/cflags/public/main_use_half3.cpp @@ -0,0 +1,7 @@ +#include "half3/half3.hpp" +#include <iostream> + +int main() { + std::cout << half3() << std::endl; + return 0; +} diff --git a/tests/test_cases/cflags/public/main_use_half3f.cpp b/tests/test_cases/cflags/public/main_use_half3f.cpp new file mode 100644 index 0000000..3e855cd --- /dev/null +++ b/tests/test_cases/cflags/public/main_use_half3f.cpp @@ -0,0 +1,11 @@ +#include "half3f/half3f.hpp" +#include <iostream> + +#ifdef HALF_PRECISION_DOUBLE +#error should not be defined +#endif + +int main() { + std::cout << half3f() << std::endl; + return 0; +} diff --git a/tests/test_cases/cflags/public/test_use_half3.cpp b/tests/test_cases/cflags/public/test_use_half3.cpp new file mode 100644 index 0000000..1cf50ad --- /dev/null +++ b/tests/test_cases/cflags/public/test_use_half3.cpp @@ -0,0 +1,6 @@ +#include "half3/half3.hpp" + +int main() { + auto result = half3(); + return result > 1 and result < 2 ? 0 : 1; +} diff --git a/tests/test_cases/cflags/public/test_use_half3f.cpp b/tests/test_cases/cflags/public/test_use_half3f.cpp new file mode 100644 index 0000000..078e69c --- /dev/null +++ b/tests/test_cases/cflags/public/test_use_half3f.cpp @@ -0,0 +1,10 @@ +#include "half3f/half3f.hpp" + +#ifdef HALF_PRECISION_DOUBLE +#error should not be defined +#endif + +int main() { + auto result = half3f(); + return result > 1 and result < 2 ? 0 : 1; +} diff --git a/tests/test_cases/deps/TARGETS b/tests/test_cases/deps/TARGETS new file mode 100644 index 0000000..10a6749 --- /dev/null +++ b/tests/test_cases/deps/TARGETS @@ -0,0 +1,197 @@ +{ "private": + { "type": ["test_rules", "test_case"] + , "name": ["deps_private"] + , "targets": + [ "+foo" + , "-main_includes_foo" + , "+main_links_foo" + , "+main_links_bar_foo" + , "+install_bar" + ] + , "asserts": + [ "test -f foo/foo/libfoo.a" + , "test -f foo/foo/foo.hpp" + , "! test -f foo/bar/bar.hpp" + , "./main_links_foo/main | grep foo" + , "./main_links_bar_foo/main | grep bar" + , "./main_links_bar_foo/main | grep foo" + , "test -f install_bar/lib/bar/libbar.a" + , "test -f install_bar/include/bar/bar.hpp" + , "test -f install_bar/lib/foo/libfoo.a" + , "! test -f install_bar/include/foo/foo.hpp" + ] + , "data": [["TREE", null, "private"]] + } +, "public": + { "type": ["test_rules", "test_case"] + , "name": ["deps_public"] + , "targets": + [ "+foo" + , "+main_includes_foo" + , "+main_links_foo" + , "+main_links_bar_foo" + , "+install_bar" + ] + , "asserts": + [ "test -f foo/foo/libfoo.a" + , "test -f foo/foo/foo.hpp" + , "! test -f foo/bar/bar.hpp" + , "./main_includes_foo/main | grep main" + , "./main_links_foo/main | grep foo" + , "./main_links_bar_foo/main | grep bar" + , "./main_links_bar_foo/main | grep foo" + , "test -f install_bar/lib/bar/libbar.a" + , "test -f install_bar/include/bar/bar.hpp" + , "test -f install_bar/lib/foo/libfoo.a" + , "test -f install_bar/include/foo/foo.hpp" + ] + , "data": [["TREE", null, "public"]] + } +, "shared": + { "type": ["test_rules", "test_case"] + , "name": ["deps_shared"] + , "targets": + [ "+foo" + , "+bar" + , "+main_uses_foo" + , "+test_uses_foo" + , "+main_uses_bar" + , "+test_uses_bar" + , "+test_uses_bar_s" + , "+test_uses_baz" + , "+test_uses_main" + , "+test_diamond" + , "+install_foo" + , "+install_bar_s" + , "+install_baz" + , "+install_main" + ] + , "asserts": + [ "test -f foo/libfoo.so.1.2.3" + , "test -f foo/foo/foo.hpp" + , "test -f bar/libbar.so" + , "test -f bar/bar/bar.hpp" + , "! test -f bar/foo/foo.hpp" + , "test -f install_foo/lib/libfoo.so.1.2.3" + , "test -f install_foo/include/foo/foo.hpp" + , "grep 'Name: foo' install_foo/lib/pkgconfig/foo.pc" + , "grep 'Version: 1.2.3' install_foo/lib/pkgconfig/foo.pc" + , "grep -- '-L${libdir}' install_foo/lib/pkgconfig/foo.pc" + , "grep -- '-l:libfoo.so.1.2.3' install_foo/lib/pkgconfig/foo.pc" + , "test -f install_bar_s/lib/bar/libbar.a" + , "test -f install_bar_s/include/bar/bar.hpp" + , "test -f install_bar_s/lib/libfoo.so.1.2.3" + , "! test -f install_bar_s/include/foo/foo.hpp" + , "grep 'Name: bar' install_bar_s/lib/pkgconfig/bar.pc" + , "grep '${libdir}/bar/libbar.a' install_bar_s/lib/pkgconfig/bar.pc" + , "grep '${libdir}/libfoo.so.1.2.3' install_bar_s/lib/pkgconfig/bar.pc" + , "test -f install_baz/lib/libbaz.so" + , "test -f install_baz/include/baz/baz.hpp" + , "! test -f install_baz/lib/foo/libfoo.a" + , "! test -f install_baz/include/foo/foo.hpp" + , "./install_main/bin/main_uses_bar | grep main" + , "./install_main/bin/main_uses_bar | grep bar" + , "./install_main/bin/main_uses_bar | grep foo" + , "! test -d install_main/include" + ] + , "data": [["TREE", null, "shared"]] + } +, "prebuilt_tests": + { "type": "tree" + , "deps": + [ ["test_cases/deps/prebuilt", "foo.hpp"] + , ["test_cases/deps/prebuilt", "bar.hpp"] + , ["test_cases/deps/prebuilt", "TARGETS"] + , ["TREE", null, "shared"] + ] + } +, "prebuilt": + { "type": ["test_rules", "test_case"] + , "name": ["deps_prebuilt"] + , "targets": + [ "+foo" + , "+bar" + , "+main_uses_foo" + , "+test_uses_foo" + , "+main_uses_bar" + , "+test_uses_bar" + , "+test_uses_bar_s" + , "+test_uses_main" + , "+install_foo" + , "+install_bar" + , "+install_main" + , "+test_uses_foobar" + , "+test_uses_foobar_s" + , "+install_foobar" + ] + , "asserts": + [ "test -f foo/libfoo.so.1.2.3" + , "test -f foo/foo/foo.hpp" + , "test -f bar/libbar.so" + , "test -f bar/bar/bar.hpp" + , "test -f install_foo/lib/pkgconfig/foo/foo.cflags" + , "test -f install_foo/lib/pkgconfig/foo/foo.ldflags" + , "test -f install_bar/lib/pkgconfig/foo/foo.cflags" + , "test -f install_bar/lib/pkgconfig/foo/foo.ldflags" + , "test -f install_bar/lib/pkgconfig/bar/bar.cflags" + , "test -f install_bar/lib/pkgconfig/bar/bar.ldflags" + , "./install_main/bin/main_uses_bar | grep main" + , "./install_main/bin/main_uses_bar | grep bar" + , "./install_main/bin/main_uses_bar | grep foo" + , "test -f install_foobar/lib/libfoo.so.1.2.3" + , "test -f install_foobar/lib/libbar.so" + , "test -f install_foobar/lib/pkgconfig/foobar.pc" + , "grep 'Cflags:.*@${prefix}/lib/pkgconfig/bar/foobar.cflags' install_foobar/lib/pkgconfig/foobar.pc" + , "grep -- '-DUSE_BAR=1 -DUSE_FOO=1' install_foobar/lib/pkgconfig/bar/foobar.cflags" + , "grep 'Libs:.*@${prefix}/lib/pkgconfig/bar/foobar.ldflags' install_foobar/lib/pkgconfig/foobar.pc" + , "grep -- '-lm -lpthread' install_foobar/lib/pkgconfig/bar/foobar.ldflags" + ] + , "data": ["prebuilt_tests"] + } +, "cmake": + { "type": ["test_rules", "test_case"] + , "name": ["deps_cmake"] + , "libs": ["googletest", "libz", "libcurl"] + , "targets": + [ "+gtest" + , "+test" + , "+gtest_main" + , "+testbin" + , "+shell_test" + , "+install_gtest" + , "+install_gtest_main" + , "+install_testbin" + , "+install_libcurl" + ] + , "asserts": + [ "test -f gtest/libgtest.a" + , "test -f gtest/gtest/gtest.h" + , "grep 'PASSED.*1 test' test/stdout" + , "test -f gtest_main/libgtest.so.1.13.0" + , "test -f gtest_main/libgtest_main.so.1.13.0" + , "test -f gtest_main/gtest/gtest.h" + , "test -f ./testbin/test" + , "grep 'PASSED.*1 test' shell_test/stdout" + , "test -f install_gtest/lib/libgtest.a" + , "test -f install_gtest/include/gtest/gtest.h" + , "grep 'Cflags.*lib/pkgconfig/gtest.cflags' install_gtest/lib/pkgconfig/gtest.pc" + , "grep 'Libs.*libgtest.a' install_gtest/lib/pkgconfig/gtest.pc" + , "grep 'Libs.*lib/pkgconfig/gtest.ldflags' install_gtest/lib/pkgconfig/gtest.pc" + , "test -f install_gtest_main/lib/libgtest.so.1.13.0" + , "test -f install_gtest_main/lib/libgtest_main.so.1.13.0" + , "test -f install_gtest_main/include/gtest/gtest.h" + , "grep 'Cflags.*lib/pkgconfig/gtest_main.cflags' install_gtest_main/lib/pkgconfig/gtest_main.pc" + , "grep 'Libs.*libgtest.so.1.13.0' install_gtest_main/lib/pkgconfig/gtest_main.pc" + , "grep 'Libs.*libgtest_main.so.1.13.0' install_gtest_main/lib/pkgconfig/gtest_main.pc" + , "grep 'Libs.*lib/pkgconfig/gtest_main.ldflags' install_gtest_main/lib/pkgconfig/gtest_main.pc" + , "./install_testbin/bin/test | grep 'PASSED.*1 test'" + , "path=$(ldd install_libcurl/lib/libcurl.so.4.8.0 | awk '/libz/{print $3}') && test -z \"${path##$(pwd)*}\"" + ] + , "data": [["TREE", null, "cmake"]] + } +, "ALL": + { "type": "install" + , "deps": ["private", "public", "shared", "prebuilt", "cmake"] + , "tainted": ["test"] + } +} diff --git a/tests/test_cases/deps/cmake/TARGETS b/tests/test_cases/deps/cmake/TARGETS new file mode 100644 index 0000000..7b3bf6f --- /dev/null +++ b/tests/test_cases/deps/cmake/TARGETS @@ -0,0 +1,80 @@ +{ "gtest": + { "type": ["@", "rules", "CC/foreign/cmake", "library"] + , "name": ["gtest"] + , "version": ["1", "13", "0"] + , "project": [["@", "googletest", "", "tree"]] + , "out_hdr_dirs": ["gtest"] + , "out_libs": ["libgtest.a"] + , "pkg-config": ["gtest.pc"] + } +, "testlib": + { "type": ["@", "rules", "CC", "library"] + , "name": ["testlib"] + , "shared": ["yes"] + , "srcs": ["main.cpp"] + , "private-deps": ["gtest"] + } +, "test": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test"] + , "private-deps": ["testlib", "gtest"] + } +, "gtest_main": + { "type": ["@", "rules", "CC/foreign/cmake", "library"] + , "name": ["gtest_main"] + , "version": ["1", "13", "0"] + , "project": [["@", "googletest", "", "tree"]] + , "defines": ["BUILD_SHARED_LIBS=ON"] + , "out_hdr_dirs": ["gtest"] + , "out_libs": ["libgtest_main.so.1.13.0", "libgtest.so.1.13.0"] + , "pkg-config": ["gtest_main.pc", "gtest.pc"] + } +, "testbin": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["test"] + , "srcs": ["test.cpp"] + , "private-deps": ["gtest_main"] + } +, "shell_test": + { "type": ["@", "rules", "shell/test", "script"] + , "name": ["shell_test"] + , "test": ["test.sh"] + , "deps": ["testbin"] + } +, "install_gtest": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["gtest"]} +, "install_gtest_main": + { "type": ["@", "rules", "CC", "install-with-deps"] + , "targets": ["gtest_main"] + } +, "install_testbin": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["testbin"]} +, "libz": + { "type": ["@", "rules", "CC/foreign/cmake", "library"] + , "name": ["libz"] + , "version": ["1", "2", "13"] + , "project": [["@", "libz", "", "tree"]] + , "defines": ["BUILD_SHARED_LIBS=ON"] + , "post_cmds": + [ "cp lib/libz.so.1.2.13 lib/libz.so" + , "cp lib/libz.so.1.2.13 lib/libz.so.1" + ] + , "out_hdrs": ["zconf.h", "zlib.h"] + , "out_libs": ["libz.so", "libz.so.1", "libz.so.1.2.13"] + , "pc_prefix": ["share/pkgconfig"] + , "pkg-config": ["zlib.pc"] + } +, "libcurl": + { "type": ["@", "rules", "CC/foreign/cmake", "library"] + , "name": ["libcurl"] + , "version": ["8", "0", "1"] + , "project": [["@", "libcurl", "", "tree"]] + , "defines": ["BUILD_SHARED_LIBS=ON", "CURL_ENABLE_SSL=OFF", "USE_ZLIB=ON"] + , "out_hdr_dirs": ["curl"] + , "out_libs": ["libcurl.so.4.8.0"] + , "pkg-config": ["libcurl.pc"] + , "deps": ["libz"] + } +, "install_libcurl": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["libcurl"]} +} diff --git a/tests/test_cases/deps/cmake/main.cpp b/tests/test_cases/deps/cmake/main.cpp new file mode 100644 index 0000000..575a358 --- /dev/null +++ b/tests/test_cases/deps/cmake/main.cpp @@ -0,0 +1,8 @@ +#include <gtest/gtest.h> + +TEST(CastTest, float) { EXPECT_EQ(42.0f, float(42)); } + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/test_cases/deps/cmake/test.cpp b/tests/test_cases/deps/cmake/test.cpp new file mode 100644 index 0000000..b1811d8 --- /dev/null +++ b/tests/test_cases/deps/cmake/test.cpp @@ -0,0 +1,3 @@ +#include <gtest/gtest.h> + +TEST(CastTest, double) { EXPECT_EQ(42.0, double(42)); } diff --git a/tests/test_cases/deps/cmake/test.sh b/tests/test_cases/deps/cmake/test.sh new file mode 100644 index 0000000..80b7965 --- /dev/null +++ b/tests/test_cases/deps/cmake/test.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +./test | grep PASSED diff --git a/tests/test_cases/deps/prebuilt/TARGETS b/tests/test_cases/deps/prebuilt/TARGETS new file mode 100644 index 0000000..c923995 --- /dev/null +++ b/tests/test_cases/deps/prebuilt/TARGETS @@ -0,0 +1,158 @@ +{ "foo.pc": + { "type": "file_gen" + , "name": "foo.pc" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "Name: foo" + , "Version: 1.2.3" + , "Description: test prebuilt foo" + , "URL: unknown" + , "Cflags: -I/usr/include -DUSE_FOO=1" + , "Libs: -L/usr/lib -lfoo -lpthread" + ] + } + } +, "foo": + { "type": ["@", "rules", "CC/prebuilt", "library"] + , "name": ["foo"] + , "version": ["1", "2", "3"] + , "hdrs": ["foo.hpp"] + , "lib": [["shared", "foo"]] + , "pkg-config": ["foo.pc"] + , "stage": ["foo"] + } +, "foo_s": + { "type": ["@", "rules", "CC/prebuilt", "library"] + , "name": ["foo"] + , "version": ["1", "2", "3"] + , "hdrs": ["foo.hpp"] + , "lib": [["shared", "foo_s"]] + , "pkg-config": ["foo.pc"] + , "stage": ["foo"] + } +, "bar.pc": + { "type": "file_gen" + , "name": "bar.pc" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "Name: bar" + , "Version: unknown" + , "Description: test prebuilt bar" + , "URL: unknown" + , "Cflags: -I/usr/include -DUSE_BAR=1" + , "Libs: -L/usr/lib -lbar -lpthread -lm" + ] + } + } +, "bar": + { "type": ["@", "rules", "CC/prebuilt", "library"] + , "name": ["bar"] + , "hdrs": ["bar.hpp"] + , "lib": [["shared", "bar"]] + , "pkg-config": ["bar.pc"] + , "stage": ["bar"] + , "deps": ["foo"] + } +, "bar_s": + { "type": ["@", "rules", "CC/prebuilt", "library"] + , "name": ["bar"] + , "hdrs": ["bar.hpp"] + , "lib": [["shared", "bar_s"]] + , "pkg-config": ["bar.pc"] + , "stage": ["bar"] + , "deps": ["foo"] + } +, "main_uses_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main_uses_foo"] + , "srcs": [["shared", "main_uses_foo.cpp"]] + , "private-deps": ["foo"] + } +, "test_uses_foo": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_foo"] + , "srcs": [["shared", "test_uses_foo.cpp"]] + , "private-deps": ["foo"] + } +, "main_uses_bar": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main_uses_bar"] + , "srcs": [["shared", "main_uses_bar.cpp"]] + , "private-deps": ["bar"] + } +, "test_uses_bar": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_bar"] + , "srcs": [["shared", "test_uses_bar.cpp"]] + , "private-deps": ["bar"] + } +, "test_uses_bar_s": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_bar"] + , "srcs": [["shared", "test_uses_bar.cpp"]] + , "private-deps": ["bar_s"] + } +, "test_uses_main": + { "type": ["@", "rules", "shell/test", "script"] + , "name": ["test_uses_main"] + , "test": [["shared", "test_uses_main.sh"]] + , "deps": ["main_uses_bar"] + } +, "install_foo": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["foo"]} +, "install_bar": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["bar"]} +, "install_main": + { "type": ["@", "rules", "CC", "install-with-deps"] + , "targets": ["main_uses_bar"] + } +, "foobar.pc": + { "type": "file_gen" + , "name": "foobar.pc" + , "data": + { "type": "join" + , "separator": "\n" + , "$1": + [ "Name: foobar" + , "Version: unknown" + , "Description: test compound prebuilt foobar" + , "URL: unknown" + , "Requires: bar, foo >= 1.2.3" + ] + } + } +, "foobar": + { "type": ["@", "rules", "CC/prebuilt", "library"] + , "name": ["foobar"] + , "hdrs": ["bar.hpp"] + , "lib": [["shared", "bar"], ["shared", "foo"]] + , "pkg-config": ["foobar.pc", "foo.pc", "bar.pc"] + , "stage": ["bar"] + } +, "foobar_s": + { "type": ["@", "rules", "CC/prebuilt", "library"] + , "name": ["foobar"] + , "hdrs": ["bar.hpp"] + , "lib": [["shared", "bar_s"], ["shared", "foo_s"]] + , "pkg-config": ["foobar.pc", "foo.pc", "bar.pc"] + , "stage": ["bar"] + } +, "test_uses_foobar": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_bar"] + , "srcs": [["shared", "test_uses_bar.cpp"]] + , "private-deps": ["foobar"] + } +, "test_uses_foobar_s": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_bar"] + , "srcs": [["shared", "test_uses_bar.cpp"]] + , "private-deps": ["foobar_s"] + } +, "install_foobar": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["foobar"]} +} diff --git a/tests/test_cases/deps/prebuilt/bar.hpp b/tests/test_cases/deps/prebuilt/bar.hpp new file mode 100644 index 0000000..243dba6 --- /dev/null +++ b/tests/test_cases/deps/prebuilt/bar.hpp @@ -0,0 +1,8 @@ +#ifndef BAR_HPP +#define BAR_HPP + +#ifdef USE_BAR +int bar(); +#endif + +#endif diff --git a/tests/test_cases/deps/prebuilt/foo.hpp b/tests/test_cases/deps/prebuilt/foo.hpp new file mode 100644 index 0000000..4f040d4 --- /dev/null +++ b/tests/test_cases/deps/prebuilt/foo.hpp @@ -0,0 +1,8 @@ +#ifndef FOO_HPP +#define FOO_HPP + +#ifdef USE_FOO +int foo(); +#endif + +#endif diff --git a/tests/test_cases/deps/private/TARGETS b/tests/test_cases/deps/private/TARGETS new file mode 100644 index 0000000..dd72948 --- /dev/null +++ b/tests/test_cases/deps/private/TARGETS @@ -0,0 +1,36 @@ +{ "foo": + { "type": ["@", "rules", "CC", "library"] + , "name": ["foo"] + , "hdrs": ["foo.hpp"] + , "srcs": ["foo.cpp"] + , "stage": ["foo"] + } +, "bar": + { "type": ["@", "rules", "CC", "library"] + , "name": ["bar"] + , "hdrs": ["bar.hpp"] + , "srcs": ["bar.cpp"] + , "private-deps": ["foo"] + , "stage": ["bar"] + } +, "main_includes_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main"] + , "srcs": ["main_includes_foo.cpp"] + , "private-deps": ["bar"] + } +, "main_links_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main"] + , "srcs": ["main_links_foo.cpp"] + , "private-deps": ["bar"] + } +, "main_links_bar_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main"] + , "srcs": ["main_links_bar_foo.cpp"] + , "private-deps": ["bar"] + } +, "install_bar": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["bar"]} +} diff --git a/tests/test_cases/deps/private/bar.cpp b/tests/test_cases/deps/private/bar.cpp new file mode 100644 index 0000000..dfce0e8 --- /dev/null +++ b/tests/test_cases/deps/private/bar.cpp @@ -0,0 +1,8 @@ +#include "foo/foo.hpp" +#include "bar.hpp" +#include <iostream> + +int bar() { + std::cout << "bar\n"; + return foo(); +} diff --git a/tests/test_cases/deps/private/bar.hpp b/tests/test_cases/deps/private/bar.hpp new file mode 100644 index 0000000..94d4f16 --- /dev/null +++ b/tests/test_cases/deps/private/bar.hpp @@ -0,0 +1,6 @@ +#ifndef BAR_HPP +#define BAR_HPP + +int bar(); + +#endif diff --git a/tests/test_cases/deps/private/foo.cpp b/tests/test_cases/deps/private/foo.cpp new file mode 100644 index 0000000..f985022 --- /dev/null +++ b/tests/test_cases/deps/private/foo.cpp @@ -0,0 +1,7 @@ +#include "foo.hpp" +#include <iostream> + +int foo() { + std::cout << "foo\n"; + return 0; +} diff --git a/tests/test_cases/deps/private/foo.hpp b/tests/test_cases/deps/private/foo.hpp new file mode 100644 index 0000000..1a28686 --- /dev/null +++ b/tests/test_cases/deps/private/foo.hpp @@ -0,0 +1,6 @@ +#ifndef FOO_HPP +#define FOO_HPP + +int foo(); + +#endif diff --git a/tests/test_cases/deps/private/main_includes_foo.cpp b/tests/test_cases/deps/private/main_includes_foo.cpp new file mode 100644 index 0000000..16701c7 --- /dev/null +++ b/tests/test_cases/deps/private/main_includes_foo.cpp @@ -0,0 +1,9 @@ +// test that foo.hpp not available + +#include "foo/foo.hpp" +#include <iostream> + +int main() { + std::cout << "main\n"; + return 0; +} diff --git a/tests/test_cases/deps/private/main_links_bar_foo.cpp b/tests/test_cases/deps/private/main_links_bar_foo.cpp new file mode 100644 index 0000000..e936074 --- /dev/null +++ b/tests/test_cases/deps/private/main_links_bar_foo.cpp @@ -0,0 +1,9 @@ +// test that foo is linked after bar + +#include "bar/bar.hpp" +#include <iostream> + +int main() { + std::cout << "main\n"; + return bar(); +} diff --git a/tests/test_cases/deps/private/main_links_foo.cpp b/tests/test_cases/deps/private/main_links_foo.cpp new file mode 100644 index 0000000..1e1e07a --- /dev/null +++ b/tests/test_cases/deps/private/main_links_foo.cpp @@ -0,0 +1,10 @@ +// test that foo is linked + +#include <iostream> + +int foo(); // forward declare + +int main() { + std::cout << "main\n"; + return foo(); +} diff --git a/tests/test_cases/deps/public/TARGETS b/tests/test_cases/deps/public/TARGETS new file mode 100644 index 0000000..bc1807a --- /dev/null +++ b/tests/test_cases/deps/public/TARGETS @@ -0,0 +1,36 @@ +{ "foo": + { "type": ["@", "rules", "CC", "library"] + , "name": ["foo"] + , "hdrs": ["foo.hpp"] + , "srcs": ["foo.cpp"] + , "stage": ["foo"] + } +, "bar": + { "type": ["@", "rules", "CC", "library"] + , "name": ["bar"] + , "hdrs": ["bar.hpp"] + , "srcs": ["bar.cpp"] + , "deps": ["foo"] + , "stage": ["bar"] + } +, "main_includes_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main"] + , "srcs": ["main_includes_foo.cpp"] + , "private-deps": ["bar"] + } +, "main_links_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main"] + , "srcs": ["main_links_foo.cpp"] + , "private-deps": ["bar"] + } +, "main_links_bar_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main"] + , "srcs": ["main_links_bar_foo.cpp"] + , "private-deps": ["bar"] + } +, "install_bar": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["bar"]} +} diff --git a/tests/test_cases/deps/public/bar.cpp b/tests/test_cases/deps/public/bar.cpp new file mode 100644 index 0000000..f2a779a --- /dev/null +++ b/tests/test_cases/deps/public/bar.cpp @@ -0,0 +1,7 @@ +#include "bar.hpp" +#include <iostream> + +int bar(Foo *foo) { + std::cout << "bar\n"; + return (foo == nullptr) ? -1 : foo->foo(); +} diff --git a/tests/test_cases/deps/public/bar.hpp b/tests/test_cases/deps/public/bar.hpp new file mode 100644 index 0000000..ec9c165 --- /dev/null +++ b/tests/test_cases/deps/public/bar.hpp @@ -0,0 +1,8 @@ +#ifndef BAR_HPP +#define BAR_HPP + +#include "foo/foo.hpp" + +int bar(Foo *foo); + +#endif diff --git a/tests/test_cases/deps/public/foo.cpp b/tests/test_cases/deps/public/foo.cpp new file mode 100644 index 0000000..6899c7a --- /dev/null +++ b/tests/test_cases/deps/public/foo.cpp @@ -0,0 +1,7 @@ +#include "foo.hpp" +#include <iostream> + +int Foo::foo() { + std::cout << "foo\n"; + return 0; +} diff --git a/tests/test_cases/deps/public/foo.hpp b/tests/test_cases/deps/public/foo.hpp new file mode 100644 index 0000000..025f3ef --- /dev/null +++ b/tests/test_cases/deps/public/foo.hpp @@ -0,0 +1,8 @@ +#ifndef FOO_HPP +#define FOO_HPP + +struct Foo { + int foo(); +}; + +#endif diff --git a/tests/test_cases/deps/public/main_includes_foo.cpp b/tests/test_cases/deps/public/main_includes_foo.cpp new file mode 100644 index 0000000..e8a85b6 --- /dev/null +++ b/tests/test_cases/deps/public/main_includes_foo.cpp @@ -0,0 +1,9 @@ +// test that foo.hpp is available (despite unused here) + +#include "foo/foo.hpp" +#include <iostream> + +int main() { + std::cout << "main\n"; + return 0; +} diff --git a/tests/test_cases/deps/public/main_links_bar_foo.cpp b/tests/test_cases/deps/public/main_links_bar_foo.cpp new file mode 100644 index 0000000..02c2966 --- /dev/null +++ b/tests/test_cases/deps/public/main_links_bar_foo.cpp @@ -0,0 +1,10 @@ +// test that foo is linked after bar + +#include "bar/bar.hpp" +#include <iostream> + +int main() { + std::cout << "main\n"; + Foo foo{}; + return bar(&foo); +} diff --git a/tests/test_cases/deps/public/main_links_foo.cpp b/tests/test_cases/deps/public/main_links_foo.cpp new file mode 100644 index 0000000..f9cc308 --- /dev/null +++ b/tests/test_cases/deps/public/main_links_foo.cpp @@ -0,0 +1,10 @@ +// test that foo is linked + +#include "foo/foo.hpp" +#include <iostream> + +int main() { + std::cout << "main\n"; + Foo{}.foo(); + return 0; +} diff --git a/tests/test_cases/deps/shared/TARGETS b/tests/test_cases/deps/shared/TARGETS new file mode 100644 index 0000000..9db7fb8 --- /dev/null +++ b/tests/test_cases/deps/shared/TARGETS @@ -0,0 +1,104 @@ +{ "foo": + { "type": ["@", "rules", "CC", "library"] + , "shared": ["yes"] + , "name": ["foo"] + , "soversion": ["1", "2", "3"] + , "hdrs": ["foo.hpp"] + , "srcs": ["foo.cpp"] + , "stage": ["foo"] + } +, "foo_s": + { "type": ["@", "rules", "CC", "library"] + , "name": ["foo"] + , "hdrs": ["foo.hpp"] + , "srcs": ["foo.cpp"] + , "stage": ["foo"] + } +, "bar": + { "type": ["@", "rules", "CC", "library"] + , "shared": ["yes"] + , "name": ["bar"] + , "hdrs": ["bar.hpp"] + , "srcs": ["bar.cpp"] + , "stage": ["bar"] + , "private-deps": ["foo"] + } +, "bar_s": + { "type": ["@", "rules", "CC", "library"] + , "name": ["bar"] + , "hdrs": ["bar.hpp"] + , "srcs": ["bar.cpp"] + , "stage": ["bar"] + , "private-deps": ["foo"] + } +, "baz": + { "type": ["@", "rules", "CC", "library"] + , "name": ["baz"] + , "shared": ["yes"] + , "hdrs": ["baz.hpp"] + , "srcs": ["baz.cpp"] + , "stage": ["baz"] + , "private-deps": ["foo_s"] + } +, "main_uses_foo": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main_uses_foo"] + , "srcs": ["main_uses_foo.cpp"] + , "private-deps": ["foo"] + } +, "test_uses_foo": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_foo"] + , "srcs": ["test_uses_foo.cpp"] + , "private-deps": ["foo"] + } +, "main_uses_bar": + { "type": ["@", "rules", "CC", "binary"] + , "name": ["main_uses_bar"] + , "srcs": ["main_uses_bar.cpp"] + , "private-deps": ["bar"] + } +, "test_uses_bar": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_bar"] + , "srcs": ["test_uses_bar.cpp"] + , "private-deps": ["bar"] + } +, "test_uses_bar_s": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_bar_s"] + , "srcs": ["test_uses_bar.cpp"] + , "private-deps": ["bar_s"] + } +, "test_uses_baz": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_uses_baz"] + , "srcs": ["test_uses_baz.cpp"] + , "private-deps": ["baz"] + } +, "test_uses_main": + { "type": ["@", "rules", "shell/test", "script"] + , "name": ["test_uses_main"] + , "test": ["test_uses_main.sh"] + , "deps": ["main_uses_bar"] + } +, "test_diamond": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["test_diamond"] + , "srcs": ["test_diamond.cpp"] + , "private-deps": ["foo_s", "baz"] + } +, "install_foo": + { "type": ["@", "rules", "CC", "install-with-deps"] + , "targets": ["foo"] + , "flat-libs": ["yes"] + } +, "install_bar_s": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["bar_s"]} +, "install_baz": + {"type": ["@", "rules", "CC", "install-with-deps"], "targets": ["baz"]} +, "install_main": + { "type": ["@", "rules", "CC", "install-with-deps"] + , "targets": ["main_uses_bar"] + } +} diff --git a/tests/test_cases/deps/shared/bar.cpp b/tests/test_cases/deps/shared/bar.cpp new file mode 100644 index 0000000..dfce0e8 --- /dev/null +++ b/tests/test_cases/deps/shared/bar.cpp @@ -0,0 +1,8 @@ +#include "foo/foo.hpp" +#include "bar.hpp" +#include <iostream> + +int bar() { + std::cout << "bar\n"; + return foo(); +} diff --git a/tests/test_cases/deps/shared/bar.hpp b/tests/test_cases/deps/shared/bar.hpp new file mode 100644 index 0000000..94d4f16 --- /dev/null +++ b/tests/test_cases/deps/shared/bar.hpp @@ -0,0 +1,6 @@ +#ifndef BAR_HPP +#define BAR_HPP + +int bar(); + +#endif diff --git a/tests/test_cases/deps/shared/baz.cpp b/tests/test_cases/deps/shared/baz.cpp new file mode 100644 index 0000000..fae4845 --- /dev/null +++ b/tests/test_cases/deps/shared/baz.cpp @@ -0,0 +1,8 @@ +#include "foo/foo.hpp" +#include "baz.hpp" +#include <iostream> + +int baz() { + std::cout << "baz\n"; + return foo(); +} diff --git a/tests/test_cases/deps/shared/baz.hpp b/tests/test_cases/deps/shared/baz.hpp new file mode 100644 index 0000000..643cf65 --- /dev/null +++ b/tests/test_cases/deps/shared/baz.hpp @@ -0,0 +1,6 @@ +#ifndef BAZ_HPP +#define BAZ_HPP + +int baz(); + +#endif diff --git a/tests/test_cases/deps/shared/foo.cpp b/tests/test_cases/deps/shared/foo.cpp new file mode 100644 index 0000000..f985022 --- /dev/null +++ b/tests/test_cases/deps/shared/foo.cpp @@ -0,0 +1,7 @@ +#include "foo.hpp" +#include <iostream> + +int foo() { + std::cout << "foo\n"; + return 0; +} diff --git a/tests/test_cases/deps/shared/foo.hpp b/tests/test_cases/deps/shared/foo.hpp new file mode 100644 index 0000000..1a28686 --- /dev/null +++ b/tests/test_cases/deps/shared/foo.hpp @@ -0,0 +1,6 @@ +#ifndef FOO_HPP +#define FOO_HPP + +int foo(); + +#endif diff --git a/tests/test_cases/deps/shared/main_uses_bar.cpp b/tests/test_cases/deps/shared/main_uses_bar.cpp new file mode 100644 index 0000000..9cfc855 --- /dev/null +++ b/tests/test_cases/deps/shared/main_uses_bar.cpp @@ -0,0 +1,8 @@ +#include "bar/bar.hpp" +#include <iostream> + +int main() { + std::cout << "main\n"; + bar(); + return 0; +} diff --git a/tests/test_cases/deps/shared/main_uses_foo.cpp b/tests/test_cases/deps/shared/main_uses_foo.cpp new file mode 100644 index 0000000..0fb3bb6 --- /dev/null +++ b/tests/test_cases/deps/shared/main_uses_foo.cpp @@ -0,0 +1,8 @@ +#include "foo/foo.hpp" +#include <iostream> + +int main() { + std::cout << "main\n"; + foo(); + return 0; +} diff --git a/tests/test_cases/deps/shared/test_diamond.cpp b/tests/test_cases/deps/shared/test_diamond.cpp new file mode 100644 index 0000000..9298230 --- /dev/null +++ b/tests/test_cases/deps/shared/test_diamond.cpp @@ -0,0 +1,4 @@ +#include "baz/baz.hpp" +#include "foo/foo.hpp" + +int main() { return foo() + baz(); } diff --git a/tests/test_cases/deps/shared/test_uses_bar.cpp b/tests/test_cases/deps/shared/test_uses_bar.cpp new file mode 100644 index 0000000..c2076ec --- /dev/null +++ b/tests/test_cases/deps/shared/test_uses_bar.cpp @@ -0,0 +1,3 @@ +#include "bar/bar.hpp" + +int main() { return bar(); } diff --git a/tests/test_cases/deps/shared/test_uses_baz.cpp b/tests/test_cases/deps/shared/test_uses_baz.cpp new file mode 100644 index 0000000..02d67f9 --- /dev/null +++ b/tests/test_cases/deps/shared/test_uses_baz.cpp @@ -0,0 +1,3 @@ +#include "baz/baz.hpp" + +int main() { return baz(); } diff --git a/tests/test_cases/deps/shared/test_uses_foo.cpp b/tests/test_cases/deps/shared/test_uses_foo.cpp new file mode 100644 index 0000000..88feb93 --- /dev/null +++ b/tests/test_cases/deps/shared/test_uses_foo.cpp @@ -0,0 +1,3 @@ +#include "foo/foo.hpp" + +int main() { return foo(); } diff --git a/tests/test_cases/deps/shared/test_uses_main.sh b/tests/test_cases/deps/shared/test_uses_main.sh new file mode 100644 index 0000000..ab8672f --- /dev/null +++ b/tests/test_cases/deps/shared/test_uses_main.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +./main_uses_bar | grep main +./main_uses_bar | grep bar +./main_uses_bar | grep foo diff --git a/tests/test_rules/EXPRESSIONS b/tests/test_rules/EXPRESSIONS new file mode 100644 index 0000000..f1ca6f4 --- /dev/null +++ b/tests/test_rules/EXPRESSIONS @@ -0,0 +1,46 @@ +{ "stage_singleton_field": + { "vars": ["fieldname", "transition", "location"] + , "expression": + { "type": "assert_non_empty" + , "msg": + ["No artifact specified in field", {"type": "var", "name": "fieldname"}] + , "$1": + { "type": "disjoint_map_union" + , "msg": + [ "Expecting (essentially) a single artifact in field" + , {"type": "var", "name": "fieldname"} + ] + , "$1": + { "type": "foreach" + , "var": "src" + , "range": + {"type": "FIELD", "name": {"type": "var", "name": "fieldname"}} + , "body": + { "type": "disjoint_map_union" + , "$1": + { "type": "foreach" + , "var": "artifact" + , "range": + { "type": "values" + , "$1": + { "type": "DEP_ARTIFACTS" + , "dep": {"type": "var", "name": "src"} + , "transition": + { "type": "var" + , "name": "transition" + , "default": {"type": "empty_map"} + } + } + } + , "body": + { "type": "singleton_map" + , "key": {"type": "var", "name": "location"} + , "value": {"type": "var", "name": "artifact"} + } + } + } + } + } + } + } +} diff --git a/tests/test_rules/README.md b/tests/test_rules/README.md new file mode 100644 index 0000000..5a1baed --- /dev/null +++ b/tests/test_rules/README.md @@ -0,0 +1,28 @@ +# Test Rules + +This is a test rule that supports building and installing multiple targets with +a given set of rules. For each target, it can be specified whether building it +should fail or succeed. After processing all targets, additional assertions +(list of shell commands) can be run. + +## Setup + +The test rules expect to find the following three bindings: + - `[["@", "test-rules", "", "tree"]]`, which contains a single tree artifact + with the rules to test. + - `[["@", "test-just", "", ""]]`, which contains a single executable artifact + that is the JustBuild binary to use for the tests. + - `[["@", "test-libs", "", "tree"]]`, which contains a single tree artifact + that holds the file trees of external libraries. + +## Rule `["test_rules", "test_case"]` + +Define a test case for rule tests. + +| Field | Description | +| ----- | ----------- | +| `"name"` | Name of the test (multiple entries are joined). | +| `"libs"` | Paths to external libraries' trees provided by the `"test-libs"` repository. From within a test cases, the library's tree can be accessed via `["@", "<libname>", "", "tree"]`. | +| `"targets"` | Target names to build and install. Each target name is prefixed by `"+"` or `"-"`, indicating if the build should fail or not. Targets that build successfully will be installed to a directory named identical to the target name (without the prefix). | +| `"asserts"` | List of commands to execute after all targets were processed. To access artifacts from installed targets, use the corresponding target name as prefix dir (e.g., target `"+foo"` installs to `"./foo/"`). | +| `"data"` | The directory that contains the project with the targets to test. | diff --git a/tests/test_rules/RULES b/tests/test_rules/RULES new file mode 100644 index 0000000..f53efba --- /dev/null +++ b/tests/test_rules/RULES @@ -0,0 +1,204 @@ +{ "test_case": + { "doc": ["Define a test case for rule tests."] + , "string_fields": ["name", "libs", "targets", "asserts"] + , "target_fields": ["data"] + , "field_doc": + { "name": ["Name of the test (multiple entries are joined)."] + , "libs": + [ "Paths to external libraries' trees provided by the \"test-libs\"" + , "repository. From within a test cases, the library's tree can be" + , "accessed via [\"@\", \"<libpath>\", \"\", \"tree\"]." + ] + , "targets": + [ "Target names to build and install. Each target name is prefixed by" + , "\"+\" or \"-\", indicating if the build should fail or not." + , "Targets that build successfully will be installed to a directory" + , "named identical to the target name (without the prefix)." + ] + , "asserts": + [ "List of commands to execute after all targets were processed. To" + , "access artifacts from installed targets, use the corresponding target" + , "name as prefix dir (e.g., target \"+foo\" installs to \"./foo/\")." + ] + , "data": + ["The directory that contains the project with the targets to test."] + } + , "tainted": ["test"] + , "implicit": + { "runner": ["test_runner.py"] + , "rules": [["@", "test-rules", "", "tree"]] + , "just": [["@", "test-just", "", ""]] + , "libs_tree": [["@", "test-libs", "", "tree"]] + } + , "imports": {"stage_artifact": "stage_singleton_field"} + , "expression": + { "type": "let*" + , "bindings": + [ ["name", {"type": "join", "$1": {"type": "FIELD", "name": "name"}}] + , ["fieldname", "just"] + , ["location", "bin/just"] + , ["just", {"type": "CALL_EXPRESSION", "name": "stage_artifact"}] + , ["fieldname", "rules"] + , ["location", "rules"] + , ["rules", {"type": "CALL_EXPRESSION", "name": "stage_artifact"}] + , [ "imports" + , { "type": "singleton_map" + , "key": "imports/TARGETS" + , "value": + { "type": "BLOB" + , "data": "{\"tree\":{\"type\":\"install\",\"dirs\":[[[\"TREE\",null,\".\"],\".\"]]}}" + } + } + ] + , ["fieldname", "libs_tree"] + , ["location", "libs"] + , ["libs", {"type": "CALL_EXPRESSION", "name": "stage_artifact"}] + , ["fieldname", "data"] + , ["location", "work"] + , ["work", {"type": "CALL_EXPRESSION", "name": "stage_artifact"}] + , ["fieldname", "runner"] + , ["location", "runner"] + , ["runner", {"type": "CALL_EXPRESSION", "name": "stage_artifact"}] + , ["targets", {"type": "FIELD", "name": "targets"}] + , ["asserts", {"type": "FIELD", "name": "asserts"}] + , [ "work_bindings" + , { "type": "map_union" + , "$1": + { "type": "++" + , "$1": + [ [{"type": "singleton_map", "key": "rules", "value": "rules"}] + , { "type": "foreach" + , "range": {"type": "FIELD", "name": "libs"} + , "var": "libpath" + , "body": + { "type": "singleton_map" + , "key": {"type": "var", "name": "libpath"} + , "value": {"type": "var", "name": "libpath"} + } + } + ] + } + } + ] + , [ "work_deps" + , { "type": "map_union" + , "$1": + { "type": "++" + , "$1": + [ [ { "type": "let*" + , "bindings": + [ ["workspace_root", ["file", "rules"]] + , ["rules", {"type": "env", "vars": ["workspace_root"]}] + ] + , "body": {"type": "env", "vars": ["rules"]} + } + ] + , { "type": "foreach" + , "range": {"type": "FIELD", "name": "libs"} + , "var": "libpath" + , "body": + { "type": "let*" + , "bindings": + [ [ "workspace_root" + , [ "file" + , { "type": "join" + , "$1": ["libs/", {"type": "var", "name": "libpath"}] + } + ] + ] + , ["target_root", ["file", "imports"]] + ] + , "body": + { "type": "singleton_map" + , "key": {"type": "var", "name": "libpath"} + , "value": + { "type": "env" + , "vars": ["workspace_root", "target_root"] + } + } + } + } + ] + } + } + ] + , [ "repos" + , { "type": "singleton_map" + , "key": "repos.json" + , "value": + { "type": "BLOB" + , "data": + { "type": "json_encode" + , "$1": + { "type": "let*" + , "bindings": + [ ["workspace_root", ["file", "work"]] + , ["bindings", {"type": "var", "name": "work_bindings"}] + , [ "work" + , {"type": "env", "vars": ["workspace_root", "bindings"]} + ] + , [ "repositories" + , { "type": "map_union" + , "$1": + [ {"type": "env", "vars": ["work"]} + , {"type": "var", "name": "work_deps"} + ] + } + ] + , ["main", "work"] + ] + , "body": {"type": "env", "vars": ["main", "repositories"]} + } + } + } + } + ] + , [ "config" + , { "type": "singleton_map" + , "key": "config.json" + , "value": + { "type": "BLOB" + , "data": + { "type": "json_encode" + , "$1": {"type": "env", "vars": ["targets", "asserts"]} + } + } + } + ] + , [ "results" + , { "type": "ACTION" + , "inputs": + { "type": "map_union" + , "$1": + [ {"type": "var", "name": "runner"} + , {"type": "var", "name": "rules"} + , {"type": "var", "name": "just"} + , {"type": "var", "name": "imports"} + , {"type": "var", "name": "libs"} + , {"type": "var", "name": "repos"} + , {"type": "var", "name": "work"} + , {"type": "var", "name": "config"} + ] + } + , "outs": ["stdout", "stderr", "result", "time-start", "time-stop"] + , "cmd": ["./runner"] + , "may_fail": ["test"] + , "fail_message": + { "type": "join" + , "$1": ["Rule test ", {"type": "var", "name": "name"}, " failed"] + } + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": {"type": "var", "name": "results"} + , "runfiles": + { "type": "singleton_map" + , "key": {"type": "var", "name": "name"} + , "value": {"type": "TREE", "$1": {"type": "var", "name": "results"}} + } + } + } + } +} diff --git a/tests/test_rules/TARGETS b/tests/test_rules/TARGETS new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/tests/test_rules/TARGETS @@ -0,0 +1 @@ +{} diff --git a/tests/test_rules/test_runner.py b/tests/test_rules/test_runner.py new file mode 100755 index 0000000..976f041 --- /dev/null +++ b/tests/test_rules/test_runner.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import os +import subprocess +import time + +time_start = time.time() +time_stop = 0 +result = "UNKNOWN" +stderr = "" +stdout = "" + + +def dump_results(): + with open("result", "w") as f: + f.write("%s\n" % (result, )) + with open("time-start", "w") as f: + f.write("%d\n" % (time_start, )) + with open("time-stop", "w") as f: + f.write("%d\n" % (time_stop, )) + with open("stdout", "w") as f: + f.write("%s\n" % (stdout, )) + with open("stderr", "w") as f: + f.write("%s\n" % (stderr, )) + + +dump_results() + +with open('config.json') as f: + config = json.load(f) + +os.makedirs("./outs") + +# install targets +failed_targets = 0 +stdout += "Test targets:\n" +for t in config.get('targets', []): + target = t[1:] + should_fail = t[0] == "-" + ret = subprocess.run([ + "./bin/just", "install", "--local-build-root", "./build_root", "-C", + "repos.json", "-o", "/".join(["./outs", target]), target + ], + capture_output=True) + success = ret.returncode != 0 if should_fail else ret.returncode == 0 + failed_targets += 0 if success else 1 + stdout += f" [{'PASS' if success else 'FAIL'}] {target}\n" + stderr += "".join([ + f"stdout/stderr of test target '{target}':\n", + ret.stdout.decode("utf-8"), + ret.stderr.decode("utf-8"), "\n" + ]) +stdout += f" {failed_targets} targets failed\n" + +# run asserts +failed_asserts = 0 +stdout += "Test asserts:\n" +for cmd in config.get('asserts', []): + ret = subprocess.run(cmd, cwd="./outs", shell=True, capture_output=True) + success = ret.returncode == 0 + failed_asserts += 0 if success else 1 + stdout += f" [{'PASS' if success else 'FAIL'}] {cmd}\n" + stderr += "".join([ + f"stdout/stderr of test assert '{cmd}':\n", + ret.stdout.decode("utf-8"), + ret.stderr.decode("utf-8"), "\n" + ]) +stdout += f" {failed_asserts} asserts failed\n" + +retval = min(failed_targets + failed_asserts, 125) +result = "PASS" if retval == 0 else "FAIL" + +time_stop = time.time() +dump_results() +exit(retval) |