diff options
author | Klaus Aehlig <klaus.aehlig@huawei.com> | 2025-03-26 12:08:54 +0100 |
---|---|---|
committer | Klaus Aehlig <klaus.aehlig@huawei.com> | 2025-04-07 16:09:43 +0200 |
commit | 4cd12f7ba531c255aa3945bd5bc1a6a1ab0bc7bc (patch) | |
tree | 995f8faf1cf10056303386dd14b14143cd4a015e /test/buildtool/build_engine | |
parent | eb101e14097d02c74a1e34927a08bba4b7d739c5 (diff) | |
download | justbuild-4cd12f7ba531c255aa3945bd5bc1a6a1ab0bc7bc.tar.gz |
Defined rules: add TREE_OVERLAY and DISJOINT_TREE_OVERLAY function
Diffstat (limited to 'test/buildtool/build_engine')
5 files changed, 252 insertions, 33 deletions
diff --git a/test/buildtool/build_engine/target_map/TARGETS b/test/buildtool/build_engine/target_map/TARGETS index e477393e..67d35ade 100644 --- a/test/buildtool/build_engine/target_map/TARGETS +++ b/test/buildtool/build_engine/target_map/TARGETS @@ -70,6 +70,7 @@ , ["@", "src", "src/buildtool/common", "config"] , ["@", "src", "src/buildtool/common", "statistics"] , ["@", "src", "src/buildtool/common", "tree"] + , ["@", "src", "src/buildtool/common", "tree_overlay"] , ["@", "src", "src/buildtool/common/remote", "remote_common"] , ["@", "src", "src/buildtool/common/remote", "retry_config"] , ["@", "src", "src/buildtool/crypto", "hash_function"] @@ -117,39 +118,9 @@ , "test_data": { "type": ["@", "rules", "data", "staged"] , "srcs": - [ "data_src/a/b/targets_here/c/d/foo" - , "data_src/file_reference/hello.txt" - , "data_src/foo" - , "data_src/simple_rules/implicit_script.sh" - , "data_src/simple_targets/bar.txt" - , "data_src/simple_targets/baz.txt" - , "data_src/simple_targets/foo.txt" - , "data_src/tree/foo.txt" - , "data_src/tree/tree/foo.txt" - , "data_src/x/foo" - , "data_src/x/x/foo" - , "data_src/x/x/x/foo" - , "data_src/x/x/x/x/foo" - , "data_src/x/x/x/x/x/foo" - , "data_targets/TARGETS" - , "data_targets/a/b/targets_here/TARGETS" - , "data_targets/bad_targets/TARGETS" - , "data_targets/config_targets/TARGETS" - , "data_targets/file_reference/TARGETS" - , "data_targets/result/TARGETS" - , "data_targets/simple_rules/TARGETS" - , "data_targets/simple_targets/TARGETS" - , "data_targets/symlink_reference/TARGETS" - , "data_targets/tree/TARGETS" - , "data_targets/x/TARGETS" - , "data_targets/x/x/TARGETS" - , "data_targets/x/x/x/TARGETS" - , "data_targets/x/x/x/x/TARGETS" - , "data_targets/x/x/x/x/x/TARGETS" - , "data_rules/result/RULES" - , "data_rules/rule/RULES" - , "data_rules/simple_rules/RULES" - , "data_rules/tree/RULES" + [ ["TREE", null, "data_src"] + , ["TREE", null, "data_targets"] + , ["TREE", null, "data_rules"] ] , "stage": ["test", "buildtool", "build_engine", "target_map"] } diff --git a/test/buildtool/build_engine/target_map/data_rules/tree_overlay/RULES b/test/buildtool/build_engine/target_map/data_rules/tree_overlay/RULES new file mode 100644 index 00000000..eb809da4 --- /dev/null +++ b/test/buildtool/build_engine/target_map/data_rules/tree_overlay/RULES @@ -0,0 +1,55 @@ +{ "overlay": + { "target_fields": ["deps"] + , "expression": + { "type": "let*" + , "bindings": + [ [ "deps" + , { "type": "foreach" + , "range": {"type": "FIELD", "name": "deps"} + , "body": + {"type": "DEP_ARTIFACTS", "dep": {"type": "var", "name": "_"}} + } + ] + , [ "overlay tree" + , {"type": "TREE_OVERLAY", "$1": {"type": "var", "name": "deps"}} + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": + { "type": "singleton_map" + , "key": "it" + , "value": {"type": "var", "name": "overlay tree"} + } + } + } + } +, "disjoint overlay": + { "target_fields": ["deps"] + , "expression": + { "type": "let*" + , "bindings": + [ [ "deps" + , { "type": "foreach" + , "range": {"type": "FIELD", "name": "deps"} + , "body": + {"type": "DEP_ARTIFACTS", "dep": {"type": "var", "name": "_"}} + } + ] + , [ "overlay tree" + , { "type": "DISJOINT_TREE_OVERLAY" + , "$1": {"type": "var", "name": "deps"} + } + ] + ] + , "body": + { "type": "RESULT" + , "artifacts": + { "type": "singleton_map" + , "key": "it" + , "value": {"type": "var", "name": "overlay tree"} + } + } + } + } +} diff --git a/test/buildtool/build_engine/target_map/data_src/tree_overlay/x b/test/buildtool/build_engine/target_map/data_src/tree_overlay/x new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/buildtool/build_engine/target_map/data_src/tree_overlay/x diff --git a/test/buildtool/build_engine/target_map/data_targets/tree_overlay/TARGETS b/test/buildtool/build_engine/target_map/data_targets/tree_overlay/TARGETS new file mode 100644 index 00000000..088d47de --- /dev/null +++ b/test/buildtool/build_engine/target_map/data_targets/tree_overlay/TARGETS @@ -0,0 +1,6 @@ +{ "empty": {"type": ["tree_overlay", "overlay"]} +, "one stage": {"type": ["tree_overlay", "overlay"], "deps": ["x"]} +, "disjoint empty": {"type": ["tree_overlay", "disjoint overlay"]} +, "disjoint one stage": + {"type": ["tree_overlay", "disjoint overlay"], "deps": ["x"]} +} diff --git a/test/buildtool/build_engine/target_map/target_map.test.cpp b/test/buildtool/build_engine/target_map/target_map.test.cpp index 87698b13..0b51355b 100644 --- a/test/buildtool/build_engine/target_map/target_map.test.cpp +++ b/test/buildtool/build_engine/target_map/target_map.test.cpp @@ -46,6 +46,7 @@ #include "src/buildtool/common/repository_config.hpp" #include "src/buildtool/common/statistics.hpp" #include "src/buildtool/common/tree.hpp" +#include "src/buildtool/common/tree_overlay.hpp" #include "src/buildtool/crypto/hash_function.hpp" #include "src/buildtool/execution_api/common/api_bundle.hpp" #include "src/buildtool/execution_api/local/config.hpp" @@ -1500,6 +1501,192 @@ TEST_CASE("trees", "[target_map]") { } } +TEST_CASE("tree_overlays", "[target_map]") { + auto const storage_config = TestStorageConfig::Create(); + auto const storage = Storage::Create(&storage_config.Get()); + + auto repo_config = SetupConfig(); + auto directory_entries = + BuildMaps::Base::CreateDirectoryEntriesMap(&repo_config); + auto source = BuildMaps::Base::CreateSourceTargetMap( + &directory_entries, + &repo_config, + storage_config.Get().hash_function.GetType()); + auto targets_file_map = + BuildMaps::Base::CreateTargetsFileMap(&repo_config, 0); + auto rule_file_map = BuildMaps::Base::CreateRuleFileMap(&repo_config, 0); + static auto expressions_file_map = + BuildMaps::Base::CreateExpressionFileMap(&repo_config, 0); + auto expr_map = BuildMaps::Base::CreateExpressionMap(&expressions_file_map, + &repo_config); + auto rule_map = + BuildMaps::Base::CreateRuleMap(&rule_file_map, &expr_map, &repo_config); + BuildMaps::Target::ResultTargetMap result_map{0}; + Statistics stats{}; + Progress exports_progress{}; + + auto serve_config = TestServeConfig::ReadFromEnvironment(); + REQUIRE(serve_config); + + LocalExecutionConfig local_exec_config{}; + + // pack the local context instances to be passed to ApiBundle + LocalContext const local_context{.exec_config = &local_exec_config, + .storage_config = &storage_config.Get(), + .storage = &storage}; + + Auth auth{}; + RetryConfig retry_config{}; + RemoteExecutionConfig remote_exec_config{}; + + // pack the remote context instances to be passed to ApiBundle + RemoteContext const remote_context{.auth = &auth, + .retry_config = &retry_config, + .exec_config = &remote_exec_config}; + + auto const apis = ApiBundle::Create(&local_context, + &remote_context, + /*repo_config=*/nullptr); + + auto serve = + ServeApi::Create(*serve_config, &local_context, &remote_context, &apis); + + AnalyseContext ctx{.repo_config = &repo_config, + .storage = &storage, + .statistics = &stats, + .progress = &exports_progress, + .serve = serve ? &*serve : nullptr}; + + auto absent_target_variables_map = + BuildMaps::Target::CreateAbsentTargetVariablesMap(&ctx, 0); + + auto absent_target_map = BuildMaps::Target::CreateAbsentTargetMap( + &ctx, &result_map, &absent_target_variables_map, 0); + + auto target_map = BuildMaps::Target::CreateTargetMap(&ctx, + &source, + &targets_file_map, + &rule_map, + &directory_entries, + &absent_target_map, + &result_map); + + AnalysedTargetPtr result; + bool error{false}; + std::string error_msg; + auto empty_config = Configuration{Expression::FromJson(R"({})"_json)}; + + SECTION("empty") { + error = false; + error_msg = "NONE"; + { + TaskSystem ts; + target_map.ConsumeAfterKeysReady( + &ts, + {BuildMaps::Target::ConfiguredTarget{ + .target = + BuildMaps::Base::EntityName{ + "", "tree_overlay", "empty"}, + .config = empty_config}}, + [&result](auto values) { result = *values[0]; }, + [&error, &error_msg](std::string const& msg, bool /*unused*/) { + error = true; + error_msg = msg; + }); + } + CHECK(not error); + CHECK(error_msg == "NONE"); + CHECK(result->TreeOverlays().size() == 1); + CHECK(result->TreeOverlays()[0]->ToJson()["trees"] == + nlohmann::json::array()); + CHECK(result->TreeOverlays()[0]->ToJson()["disjoint"] == false); + } + + SECTION("implicit tree") { + error = false; + error_msg = "NONE"; + { + TaskSystem ts; + target_map.ConsumeAfterKeysReady( + &ts, + {BuildMaps::Target::ConfiguredTarget{ + .target = + BuildMaps::Base::EntityName{ + "", "tree_overlay", "one stage"}, + .config = empty_config}}, + [&result](auto values) { result = *values[0]; }, + [&error, &error_msg](std::string const& msg, bool /*unused*/) { + error = true; + error_msg = msg; + }); + } + CHECK(not error); + CHECK(error_msg == "NONE"); + CHECK(result->Trees().size() == 1); + CHECK(result->Trees()[0]->ToJson()["x"]["type"] == "LOCAL"); + CHECK(result->TreeOverlays().size() == 1); + CHECK(result->TreeOverlays()[0]->ToJson()["trees"].size() == 1); + CHECK(result->TreeOverlays()[0]->ToJson()["trees"][0]["type"] == + "TREE"); + CHECK(result->TreeOverlays()[0]->ToJson()["disjoint"] == false); + } + + SECTION("disjoint empty") { + error = false; + error_msg = "NONE"; + { + TaskSystem ts; + target_map.ConsumeAfterKeysReady( + &ts, + {BuildMaps::Target::ConfiguredTarget{ + .target = + BuildMaps::Base::EntityName{ + "", "tree_overlay", "disjoint empty"}, + .config = empty_config}}, + [&result](auto values) { result = *values[0]; }, + [&error, &error_msg](std::string const& msg, bool /*unused*/) { + error = true; + error_msg = msg; + }); + } + CHECK(not error); + CHECK(error_msg == "NONE"); + CHECK(result->TreeOverlays().size() == 1); + CHECK(result->TreeOverlays()[0]->ToJson()["trees"] == + nlohmann::json::array()); + CHECK(result->TreeOverlays()[0]->ToJson()["disjoint"] == true); + } + + SECTION("disjoint implicit tree") { + error = false; + error_msg = "NONE"; + { + TaskSystem ts; + target_map.ConsumeAfterKeysReady( + &ts, + {BuildMaps::Target::ConfiguredTarget{ + .target = + BuildMaps::Base::EntityName{ + "", "tree_overlay", "disjoint one stage"}, + .config = empty_config}}, + [&result](auto values) { result = *values[0]; }, + [&error, &error_msg](std::string const& msg, bool /*unused*/) { + error = true; + error_msg = msg; + }); + } + CHECK(not error); + CHECK(error_msg == "NONE"); + CHECK(result->Trees().size() == 1); + CHECK(result->Trees()[0]->ToJson()["x"]["type"] == "LOCAL"); + CHECK(result->TreeOverlays().size() == 1); + CHECK(result->TreeOverlays()[0]->ToJson()["trees"].size() == 1); + CHECK(result->TreeOverlays()[0]->ToJson()["trees"][0]["type"] == + "TREE"); + CHECK(result->TreeOverlays()[0]->ToJson()["disjoint"] == true); + } +} + TEST_CASE("RESULT error reporting", "[target_map]") { auto const storage_config = TestStorageConfig::Create(); auto const storage = Storage::Create(&storage_config.Get()); |