From 619def44c1cca9f3cdf63544d5f24f2c7a7d9b77 Mon Sep 17 00:00:00 2001 From: Klaus Aehlig Date: Tue, 22 Feb 2022 17:03:21 +0100 Subject: Initial self-hosting commit This is the initial version of our tool that is able to build itself. In can be bootstrapped by ./bin/bootstrap.py Co-authored-by: Oliver Reiche Co-authored-by: Victor Moreno --- .../execution_api/local_tree_map.test.cpp | 110 +++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 test/buildtool/execution_api/local_tree_map.test.cpp (limited to 'test/buildtool/execution_api/local_tree_map.test.cpp') diff --git a/test/buildtool/execution_api/local_tree_map.test.cpp b/test/buildtool/execution_api/local_tree_map.test.cpp new file mode 100644 index 00000000..d8becced --- /dev/null +++ b/test/buildtool/execution_api/local_tree_map.test.cpp @@ -0,0 +1,110 @@ +#include +#include +#include + +#include "catch2/catch.hpp" +#include "src/buildtool/execution_api/common/local_tree_map.hpp" +#include "src/utils/cpp/atomic.hpp" + +namespace { + +[[nodiscard]] auto ToDigest(std::string const& s) { + return static_cast(ArtifactDigest{s, 0}); +} + +[[nodiscard]] auto ToInfo(std::string const& s) { + return Artifact::ObjectInfo{ArtifactDigest{s, 0}, ObjectType::File}; +} + +} // namespace + +TEST_CASE("LocalTree: empty tree", "[execution_api]") { + LocalTreeMap tree_map{}; + + auto tree = tree_map.CreateTree(); + CHECK(tree.size() == 0); + CHECK(std::all_of( + tree.begin(), tree.end(), [](auto /*unused*/) { return false; })); +} + +TEST_CASE("LocalTree: first wins", "[execution_api]") { + LocalTreeMap tree_map{}; + + auto tree = tree_map.CreateTree(); + CHECK(tree.AddInfo("foo", ToInfo("bar"))); + CHECK(tree.AddInfo("foo", ToInfo("baz"))); + CHECK(tree.size() == 1); + for (auto const& [path, oid] : tree) { + CHECK(oid->digest.hash() == "bar"); + } +} + +TEST_CASE("LocalTreeMap: first wins", "[execution_api]") { + LocalTreeMap tree_map{}; + + auto tree_1 = tree_map.CreateTree(); + CHECK(tree_1.AddInfo("foo", ToInfo("bar"))); + + auto tree_2 = tree_map.CreateTree(); + CHECK(tree_2.AddInfo("foo", ToInfo("baz"))); + + auto tree_id = ToDigest("tree"); + CHECK(tree_map.AddTree(tree_id, std::move(tree_1))); // NOLINT + CHECK(tree_map.AddTree(tree_id, std::move(tree_2))); // NOLINT + + CHECK(tree_map.HasTree(tree_id)); + + auto const* tree = tree_map.GetTree(tree_id); + REQUIRE(tree != nullptr); + CHECK(tree->size() == 1); + for (auto const& [path, oid] : *tree) { + CHECK(oid->digest.hash() == "bar"); + } +} + +TEST_CASE("LocalTreeMap: thread-safety", "[execution_api]") { + constexpr auto kNumThreads = 100; + constexpr auto kQ = 10; + + atomic starting_signal{false}; + std::vector threads{}; + threads.reserve(kNumThreads); + + LocalTreeMap tree_map{}; + + for (int id{}; id < kNumThreads; ++id) { + threads.emplace_back( + [&tree_map, &starting_signal](int tid) { + auto entry_id = std::to_string(tid); + auto tree = tree_map.CreateTree(); + REQUIRE(tree.AddInfo(entry_id, ToInfo(entry_id))); + + auto tree_id = ToDigest(std::to_string(tid / kQ)); + starting_signal.wait(false); + + // kQ-many threads try to add tree with same id + REQUIRE(tree_map.AddTree(tree_id, std::move(tree))); // NOLINT + }, + id); + } + + starting_signal = true; + starting_signal.notify_all(); + for (auto& thread : threads) { + thread.join(); + } + + for (int id{}; id <= (kNumThreads - 1) / kQ; ++id) { + auto tree_id = ToDigest(std::to_string(id)); + CHECK(tree_map.HasTree(tree_id)); + + auto const* tree = tree_map.GetTree(tree_id); + REQUIRE(tree != nullptr); + CHECK(tree->size() == 1); + for (auto const& [path, oid] : *tree) { + auto entry_id = std::stoi(oid->digest.hash()); + CHECK(entry_id >= id * kQ); + CHECK(entry_id < (id + 1) * kQ); + } + } +} -- cgit v1.2.3