From 32292572be63bf1725d34e4c071cd6690ecd43e8 Mon Sep 17 00:00:00 2001 From: HÃ¥vard Pettersen Date: Wed, 6 Jan 2021 14:49:48 +0000 Subject: add string_id and simplify multi-handle container add more testing static instance instead of lazy singleton use logging for leak detection drop label_t type alias --- .../shared_string_repo/shared_string_repo_test.cpp | 159 +++++++++++++++++---- 1 file changed, 131 insertions(+), 28 deletions(-) (limited to 'vespalib/src/tests/shared_string_repo/shared_string_repo_test.cpp') diff --git a/vespalib/src/tests/shared_string_repo/shared_string_repo_test.cpp b/vespalib/src/tests/shared_string_repo/shared_string_repo_test.cpp index e8f39c88afe..d560513e24d 100644 --- a/vespalib/src/tests/shared_string_repo/shared_string_repo_test.cpp +++ b/vespalib/src/tests/shared_string_repo/shared_string_repo_test.cpp @@ -13,6 +13,7 @@ using namespace vespalib; using make_string_short::fmt; using Handle = SharedStringRepo::Handle; +using Handles = SharedStringRepo::Handles; bool verbose = false; double budget = 0.10; @@ -30,12 +31,7 @@ std::vector make_strings(size_t cnt) { } std::vector copy_strings(const std::vector &strings) { - std::vector result; - result.reserve(strings.size()); - for (const auto &str: strings) { - result.push_back(str); - } - return result; + return strings; } std::vector> copy_and_hash(const std::vector &strings) { @@ -75,20 +71,27 @@ std::vector get_strings(const std::vector &handles) { return strings; } -std::unique_ptr make_strong_handles(const std::vector &strings) { - auto result = std::make_unique(strings.size()); +std::unique_ptr make_strong_handles(const std::vector &strings) { + auto result = std::make_unique(); + result->reserve(strings.size()); for (const auto &str: strings) { result->add(str); } return result; } -std::unique_ptr make_weak_handles(const SharedStringRepo::HandleView &view) { - auto result = std::make_unique(view.handles().size()); - for (uint32_t handle: view.handles()) { - result->add(handle); +std::unique_ptr copy_strong_handles(const SharedStringRepo::Handles &handles) { + const auto &view = handles.view(); + auto result = std::make_unique(); + result->reserve(view.size()); + for (const auto &handle: view) { + result->push_back(handle); } - return result; + return result; +} + +std::unique_ptr> make_weak_handles(const SharedStringRepo::Handles &handles) { + return std::make_unique>(handles.view()); } //----------------------------------------------------------------------------- @@ -183,8 +186,9 @@ struct Fixture { std::vector copy_handles_result; std::vector resolve_again_result; std::vector get_result; - std::unique_ptr strong; - std::unique_ptr weak; + std::unique_ptr strong; + std::unique_ptr strong_copy; + std::unique_ptr> weak; auto copy_strings_task = [&](){ copy_strings_result = copy_strings(work); }; auto copy_and_hash_task = [&](){ copy_and_hash_result = copy_and_hash(work); }; auto local_enum_task = [&](){ local_enum_result = local_enum(work); }; @@ -195,8 +199,10 @@ struct Fixture { auto reclaim_task = [&]() { resolve_again_result.clear(); }; auto reclaim_last_task = [&]() { resolve_result.clear(); }; auto make_strong_task = [&]() { strong = make_strong_handles(work); }; - auto make_weak_task = [&]() { weak = make_weak_handles(strong->view()); }; + auto copy_strong_task = [&]() { strong_copy = copy_strong_handles(*strong); }; + auto make_weak_task = [&]() { weak = make_weak_handles(*strong); }; auto free_weak_task = [&]() { weak.reset(); }; + auto free_strong_copy_task = [&]() { strong_copy.reset(); }; auto free_strong_task = [&]() { strong.reset(); }; measure_task("[01] copy strings", is_master, copy_strings_task); measure_task("[02] copy and hash", is_master, copy_and_hash_task); @@ -211,36 +217,117 @@ struct Fixture { copy_handles_result.clear(); measure_task("[09] reclaim last", is_master, reclaim_last_task); measure_task("[10] make strong handles", is_master, make_strong_task); - measure_task("[11] make weak handles", is_master, make_weak_task); - measure_task("[12] free weak handles", is_master, free_weak_task); - measure_task("[13] free strong handles", is_master, free_strong_task); + measure_task("[11] copy strong handles", is_master, copy_strong_task); + measure_task("[12] make weak handles", is_master, make_weak_task); + measure_task("[13] free weak handles", is_master, free_weak_task); + measure_task("[14] free strong handles copy", is_master, free_strong_copy_task); + measure_task("[15] free strong handles", is_master, free_strong_task); } } }; //----------------------------------------------------------------------------- -TEST("require that basic usage works") { +void verify_eq(const Handle &a, const Handle &b) { + EXPECT_TRUE(a == b); + EXPECT_TRUE(a.id() == b.id()); + EXPECT_FALSE(a != b); + EXPECT_FALSE(a.id() != b.id()); + EXPECT_FALSE(a < b); + EXPECT_FALSE(a.id() < b.id()); + EXPECT_FALSE(b < a); + EXPECT_FALSE(b.id() < a.id()); +} + +void verify_not_eq(const Handle &a, const Handle &b) { + EXPECT_FALSE(a == b); + EXPECT_FALSE(a.id() == b.id()); + EXPECT_TRUE(a != b); + EXPECT_TRUE(a.id() != b.id()); + EXPECT_NOT_EQUAL((a < b), (b < a)); + EXPECT_NOT_EQUAL((a.id() < b.id()), (b.id() < a.id())); +} + +//----------------------------------------------------------------------------- + +TEST("require that basic handle usage works") { Handle empty; Handle foo("foo"); Handle bar("bar"); Handle empty2; Handle foo2("foo"); - Handle bar2(bar); - EXPECT_EQUAL(empty.id(), 0u); - EXPECT_TRUE(empty.id() != foo.id()); - EXPECT_TRUE(empty.id() != bar.id()); - EXPECT_TRUE(foo.id() != bar.id()); - EXPECT_EQUAL(empty.id(), empty2.id()); - EXPECT_EQUAL(foo.id(), foo2.id()); - EXPECT_EQUAL(bar.id(), bar2.id()); + Handle bar2("bar"); + + EXPECT_EQUAL(SharedStringRepo::stats().active_entries, 2u); + + TEST_DO(verify_eq(empty, empty2)); + TEST_DO(verify_eq(foo, foo2)); + TEST_DO(verify_eq(bar, bar2)); + + TEST_DO(verify_not_eq(empty, foo)); + TEST_DO(verify_not_eq(empty, bar)); + TEST_DO(verify_not_eq(foo, bar)); + + EXPECT_TRUE(empty.id() == string_id()); + EXPECT_TRUE(empty2.id() == string_id()); EXPECT_EQUAL(empty.as_string(), vespalib::string("")); + EXPECT_EQUAL(empty2.as_string(), vespalib::string("")); EXPECT_EQUAL(foo.as_string(), vespalib::string("foo")); EXPECT_EQUAL(bar.as_string(), vespalib::string("bar")); EXPECT_EQUAL(foo2.as_string(), vespalib::string("foo")); EXPECT_EQUAL(bar2.as_string(), vespalib::string("bar")); } +TEST("require that handles can be copied") { + Handle a("foo"); + Handle b(a); + Handle c; + c = b; + EXPECT_EQUAL(SharedStringRepo::stats().active_entries, 1u); + EXPECT_TRUE(a.id() == b.id()); + EXPECT_TRUE(b.id() == c.id()); + EXPECT_EQUAL(c.as_string(), vespalib::string("foo")); +} + +TEST("require that handles can be moved") { + Handle a("foo"); + Handle b(std::move(a)); + Handle c; + c = std::move(b); + EXPECT_EQUAL(SharedStringRepo::stats().active_entries, 1u); + EXPECT_TRUE(a.id() == string_id()); + EXPECT_TRUE(b.id() == string_id()); + EXPECT_EQUAL(c.as_string(), vespalib::string("foo")); +} + +TEST("require that handle/string can be obtained from string_id") { + Handle a("str"); + Handle b = Handle::handle_from_id(a.id()); + EXPECT_EQUAL(SharedStringRepo::stats().active_entries, 1u); + EXPECT_EQUAL(Handle::string_from_id(b.id()), vespalib::string("str")); +} + +//----------------------------------------------------------------------------- + +TEST("require that basic multi-handle usage works") { + Handles a; + a.reserve(4); + Handle foo("foo"); + Handle bar("bar"); + EXPECT_TRUE(a.add("foo") == foo.id()); + EXPECT_TRUE(a.add("bar") == bar.id()); + a.push_back(foo.id()); + a.push_back(bar.id()); + Handles b(std::move(a)); + EXPECT_EQUAL(SharedStringRepo::stats().active_entries, 2u); + EXPECT_EQUAL(a.view().size(), 0u); + EXPECT_EQUAL(b.view().size(), 4u); + EXPECT_TRUE(b.view()[0] == foo.id()); + EXPECT_TRUE(b.view()[1] == bar.id()); + EXPECT_TRUE(b.view()[2] == foo.id()); + EXPECT_TRUE(b.view()[3] == bar.id()); +} + //----------------------------------------------------------------------------- TEST_MT_F("test shared string repo operations with 1 threads", 1, Fixture(num_threads)) { @@ -273,6 +360,22 @@ TEST_MT_F("test shared string repo operations with 64 threads", 64, Fixture(num_ //----------------------------------------------------------------------------- +#if 0 +// verify leak-detection and reporting + +TEST("leak some handles on purpose") { + new Handle("leaked string"); + new Handle("also leaked"); + new Handle("even more leak"); +} +#endif + +TEST("require that no handles have leaked during testing") { + EXPECT_EQUAL(SharedStringRepo::stats().active_entries, 0u); +} + +//----------------------------------------------------------------------------- + int main(int argc, char **argv) { TEST_MASTER.init(__FILE__); if ((argc == 2) && (argv[1] == std::string("verbose"))) { -- cgit v1.2.3