diff options
author | innokentii <innokentii@yandex-team.com> | 2022-09-09 13:56:14 +0300 |
---|---|---|
committer | innokentii <innokentii@yandex-team.com> | 2022-09-09 13:56:14 +0300 |
commit | 7cd934b41bf8f1487cbb4eb783a1e7e7e0a8cbdc (patch) | |
tree | 685d3025cdc4b14befe8b9fd9c1448adadd321f9 /library/cpp/actors/util/shared_data_ut.cpp | |
parent | 695f38b2d33b4c1962bc3ae11737025406116832 (diff) | |
download | ydb-7cd934b41bf8f1487cbb4eb783a1e7e7e0a8cbdc.tar.gz |
Move TSharedData to actors lib
fix MemoryTrack usages
move MemoryTrack to utils
move TSharedData to actors lib
Diffstat (limited to 'library/cpp/actors/util/shared_data_ut.cpp')
-rw-r--r-- | library/cpp/actors/util/shared_data_ut.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/library/cpp/actors/util/shared_data_ut.cpp b/library/cpp/actors/util/shared_data_ut.cpp new file mode 100644 index 0000000000..8ed0df6866 --- /dev/null +++ b/library/cpp/actors/util/shared_data_ut.cpp @@ -0,0 +1,186 @@ +#include "shared_data.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include <util/generic/hash.h> +#include <util/generic/deque.h> +#include <util/system/sys_alloc.h> + +namespace NActors { + + Y_UNIT_TEST_SUITE(TSharedDataTest) { + + Y_UNIT_TEST(BasicBehavior) { + auto data = TSharedData::Copy("Hello", 5); + UNIT_ASSERT(data.IsPrivate()); + UNIT_ASSERT(!data.IsShared()); + UNIT_ASSERT_VALUES_EQUAL(data.size(), 5u); + UNIT_ASSERT_VALUES_EQUAL(data.end() - data.begin(), 5u); + UNIT_ASSERT_VALUES_EQUAL(data.mutable_end() - data.mutable_begin(), 5u); + UNIT_ASSERT(data.begin() == data.data()); + UNIT_ASSERT(data.mutable_data() == data.data()); + UNIT_ASSERT(data.mutable_begin() == data.mutable_data()); + + UNIT_ASSERT_VALUES_EQUAL(data.ToString(), TString("Hello")); + UNIT_ASSERT_VALUES_EQUAL(::memcmp(data.data(), "Hello", 5), 0); + + auto link = data; + UNIT_ASSERT(!link.IsPrivate()); + UNIT_ASSERT(!data.IsPrivate()); + UNIT_ASSERT(link.IsShared()); + UNIT_ASSERT(data.IsShared()); + UNIT_ASSERT(link.data() == data.data()); + UNIT_ASSERT(link.size() == data.size()); + + link = { }; + UNIT_ASSERT(link.IsPrivate()); + UNIT_ASSERT(data.IsPrivate()); + UNIT_ASSERT(!link.IsShared()); + UNIT_ASSERT(!data.IsShared()); + + UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice()), TString("Hello")); + UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1)), TString("ello")); + UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1, 3)), TString("ell")); + UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(1, 100)), TString("ello")); + UNIT_ASSERT_VALUES_EQUAL(TString(data.Slice(0, 4)), TString("Hell")); + } + + Y_UNIT_TEST(TrimBehavior) { + auto data = TSharedData::Uninitialized(42); + + UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u); + UNIT_ASSERT(data.data() != nullptr); + + // Trim to non-zero does not change addresses + const char* ptr1 = data.data(); + data.Trim(31); + const char* ptr2 = data.data(); + + UNIT_ASSERT_VALUES_EQUAL(data.size(), 31u); + UNIT_ASSERT(ptr1 == ptr2); + + // Trim to zero releases underlying data + data.Trim(0); + + UNIT_ASSERT_VALUES_EQUAL(data.size(), 0u); + UNIT_ASSERT(data.data() == nullptr); + } + + class TCustomOwner : public TSharedData::IOwner { + using THeader = TSharedData::THeader; + + public: + TSharedData Allocate(size_t size) { + char* raw = reinterpret_cast<char*>(y_allocate(sizeof(THeader) + size)); + THeader* header = reinterpret_cast<THeader*>(raw); + header->RefCount = 1; + header->Owner = this; + char* data = raw + sizeof(THeader); + Y_VERIFY(Allocated_.insert(data).second); + return TSharedData::AttachUnsafe(data, size); + } + + void Deallocate(char* data) noexcept { + Y_VERIFY(Allocated_.erase(data) > 0); + char* raw = data - sizeof(THeader); + y_deallocate(raw); + Deallocated_.push_back(data); + } + + char* NextDeallocated() { + char* result = nullptr; + if (Deallocated_) { + result = Deallocated_.front(); + Deallocated_.pop_front(); + } + return result; + } + + private: + THashSet<void*> Allocated_; + TDeque<char*> Deallocated_; + }; + + Y_UNIT_TEST(CustomOwner) { + TCustomOwner owner; + const char* ptr; + + // Test destructor releases data + { + auto data = owner.Allocate(42); + UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u); + ptr = data.data(); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + } + + UNIT_ASSERT(owner.NextDeallocated() == ptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + + // Test assignment releases data + { + auto data = owner.Allocate(42); + UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u); + ptr = data.data(); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + data = { }; + } + + UNIT_ASSERT(owner.NextDeallocated() == ptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + + // Test copies keep references correctly + { + auto data = owner.Allocate(42); + UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u); + ptr = data.data(); + auto copy = data; + UNIT_ASSERT_VALUES_EQUAL(copy.size(), 42u); + UNIT_ASSERT(copy.data() == ptr); + data = { }; + UNIT_ASSERT_VALUES_EQUAL(data.size(), 0u); + UNIT_ASSERT(data.data() == nullptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + } + + UNIT_ASSERT(owner.NextDeallocated() == ptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + + // Test assignment releases correct data + { + auto data1 = owner.Allocate(42); + UNIT_ASSERT_VALUES_EQUAL(data1.size(), 42u); + auto data2 = owner.Allocate(31); + UNIT_ASSERT_VALUES_EQUAL(data2.size(), 31u); + ptr = data1.data(); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + data1 = data2; + UNIT_ASSERT(owner.NextDeallocated() == ptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + ptr = data2.data(); + UNIT_ASSERT_VALUES_EQUAL(data1.size(), 31u); + UNIT_ASSERT(data1.data() == ptr); + } + + UNIT_ASSERT(owner.NextDeallocated() == ptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + + // Test moves don't produce dangling references + { + auto data = owner.Allocate(42); + UNIT_ASSERT_VALUES_EQUAL(data.size(), 42u); + ptr = data.data(); + auto moved = std::move(data); + UNIT_ASSERT_VALUES_EQUAL(moved.size(), 42u); + UNIT_ASSERT(moved.data() == ptr); + UNIT_ASSERT_VALUES_EQUAL(data.size(), 0u); + UNIT_ASSERT(data.data() == nullptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + } + + UNIT_ASSERT(owner.NextDeallocated() == ptr); + UNIT_ASSERT(owner.NextDeallocated() == nullptr); + } + + } + +} |