| /* |
| * Copyright 2016 The Android Open Source Project |
| * |
| * 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. |
| */ |
| |
| //#define LOG_NDEBUG 0 |
| #define LOG_TAG "AData_test" |
| |
| #include <gtest/gtest.h> |
| #include <utils/RefBase.h> |
| //#include <utils/StrongPointer.h> |
| |
| #include <media/stagefright/foundation/AData.h> |
| #include <media/stagefright/foundation/ABuffer.h> |
| |
| namespace android { |
| |
| class ADataTest : public ::testing::Test { |
| }; |
| |
| // ============ AUnion |
| |
| struct Events { |
| int dtor; |
| int ctor_empty; |
| int ctor_copy; |
| }; |
| |
| struct EventCounter : public RefBase { |
| EventCounter(int *counter, int magic=1234) : mCounter(counter), mMagic(magic) { } |
| virtual ~EventCounter() { ++*mCounter; mMagic = 0; } |
| int magic() const { return mMagic; } |
| private: |
| int *mCounter; |
| int mMagic; |
| }; |
| |
| struct DerivedCounter : public EventCounter { |
| DerivedCounter(int *counter, int magic=1234) : EventCounter(counter, magic) { } |
| }; |
| |
| TEST_F(ADataTest, AUnion_Test) { |
| AUnion<int, const char *, char> u; |
| u.emplace<int>(4); |
| u.del<int>(); |
| EXPECT_EQ(4, u.get<int>()); // verify that del<> is a no-op for trivial types, such as int. |
| // specifically, verify that it does not clear the objet memory |
| |
| u.emplace<const char *>("hello"); |
| EXPECT_STREQ("hello", u.get<const char *>()); |
| u.del<const char *>(); |
| |
| // u.del<char *>(); |
| // u.emplace<const int>(4); |
| u.emplace<void>(); |
| u.del<void>(); |
| |
| u.emplace<int>(~0); |
| u.del<int>(); |
| EXPECT_EQ(~0, u.get<int>()); |
| u.emplace<char>(0x15); |
| // verify that rest of memory after char is cleared upon construction |
| EXPECT_EQ(0, memcmp((char *)(&u) + sizeof(char), "\0\0\0", 3)); |
| EXPECT_EQ(0x15, u.get<char>()); |
| u.del<char>(); |
| |
| AUnion<EventCounter, EventCounter *> d; |
| int destructions = 0; |
| |
| d.emplace<EventCounter>(&destructions); |
| d.del<EventCounter>(); |
| EXPECT_EQ(1, destructions); |
| |
| EventCounter *ctr = new EventCounter(&destructions); |
| d.emplace<EventCounter *>(ctr); |
| d.del<EventCounter *>(); |
| EXPECT_EQ(1, destructions); |
| |
| delete ctr; |
| EXPECT_EQ(2, destructions); |
| |
| AUnion<std::shared_ptr<EventCounter>, std::unique_ptr<EventCounter>> md; |
| md.emplace<std::shared_ptr<EventCounter>>(new EventCounter(&destructions)); |
| std::shared_ptr<EventCounter> copy(md.get<std::shared_ptr<EventCounter>>()); |
| std::weak_ptr<EventCounter> weak(copy); |
| EXPECT_EQ(2, destructions); |
| |
| copy.reset(); |
| EXPECT_EQ(2, destructions); |
| md.del<std::shared_ptr<EventCounter>>(); |
| EXPECT_EQ(3, destructions); |
| EXPECT_TRUE(weak.expired()); |
| |
| md.emplace<std::unique_ptr<EventCounter>>(new EventCounter(&destructions)); |
| EXPECT_EQ(3, destructions); |
| |
| std::unique_ptr<EventCounter> unique = std::move(md.get<std::unique_ptr<EventCounter>>()); |
| EXPECT_EQ(3, destructions); |
| EXPECT_FALSE((bool)md.get<std::unique_ptr<EventCounter>>()); |
| |
| md.del<std::unique_ptr<EventCounter>>(); |
| EXPECT_EQ(3, destructions); |
| md.emplace<std::unique_ptr<EventCounter>>(std::move(unique)); |
| EXPECT_TRUE((bool)md.get<std::unique_ptr<EventCounter>>()); |
| EXPECT_EQ(3, destructions); |
| |
| md.del<std::unique_ptr<EventCounter>>(); |
| EXPECT_EQ(4, destructions); |
| } |
| |
| TEST_F(ADataTest, AData_StaticTest) { |
| using namespace std; |
| |
| static_assert(is_copy_assignable<shared_ptr<EventCounter>>::value, ""); |
| static_assert(is_copy_constructible<shared_ptr<EventCounter>>::value, ""); |
| static_assert(is_default_constructible<shared_ptr<EventCounter>>::value, ""); |
| |
| static_assert(is_copy_assignable<weak_ptr<DerivedCounter>>::value, ""); |
| static_assert(is_copy_constructible<weak_ptr<DerivedCounter>>::value, ""); |
| static_assert(is_default_constructible<weak_ptr<DerivedCounter>>::value, ""); |
| |
| static_assert(!is_copy_assignable<unique_ptr<DerivedCounter>>::value, ""); |
| static_assert(!is_copy_constructible<unique_ptr<DerivedCounter>>::value, ""); |
| static_assert(is_default_constructible<unique_ptr<DerivedCounter>>::value, ""); |
| |
| static_assert(is_copy_assignable<sp<EventCounter>>::value, ""); |
| static_assert(is_copy_constructible<sp<EventCounter>>::value, ""); |
| static_assert(is_default_constructible<sp<EventCounter>>::value, ""); |
| |
| static_assert(is_copy_assignable<wp<EventCounter>>::value, ""); |
| static_assert(is_copy_constructible<wp<EventCounter>>::value, ""); |
| static_assert(is_default_constructible<wp<EventCounter>>::value, ""); |
| |
| static_assert(is_convertible<shared_ptr<DerivedCounter>, shared_ptr<EventCounter>>::value, ""); |
| static_assert(!is_convertible<shared_ptr<EventCounter>, shared_ptr<DerivedCounter>>::value, ""); |
| |
| static_assert(is_convertible<unique_ptr<DerivedCounter>, unique_ptr<EventCounter>>::value, ""); |
| static_assert(!is_convertible<unique_ptr<EventCounter>, unique_ptr<DerivedCounter>>::value, ""); |
| |
| static_assert(is_convertible<unique_ptr<DerivedCounter>, shared_ptr<EventCounter>>::value, ""); |
| static_assert(!is_convertible<shared_ptr<DerivedCounter>, unique_ptr<EventCounter>>::value, ""); |
| |
| static_assert(is_convertible<weak_ptr<DerivedCounter>, weak_ptr<EventCounter>>::value, ""); |
| static_assert(!is_convertible<weak_ptr<EventCounter>, weak_ptr<DerivedCounter>>::value, ""); |
| |
| static_assert(is_convertible<shared_ptr<DerivedCounter>, weak_ptr<EventCounter>>::value, ""); |
| static_assert(!is_convertible<weak_ptr<DerivedCounter>, shared_ptr<EventCounter>>::value, ""); |
| |
| static_assert(is_convertible<sp<EventCounter>, sp<RefBase>>::value, ""); |
| static_assert(is_convertible<sp<RefBase>, sp<EventCounter>>::value, "YES"); |
| |
| static_assert(is_convertible<wp<EventCounter>, wp<RefBase>>::value, ""); |
| static_assert(is_convertible<wp<RefBase>, wp<EventCounter>>::value, "YES"); |
| |
| static_assert(is_convertible<sp<EventCounter>, wp<RefBase>>::value, ""); |
| static_assert(!is_convertible<wp<EventCounter>, sp<RefBase>>::value, ""); |
| } |
| |
| TEST_F(ADataTest, AData_SampleTest) { |
| AData<int, float>::Basic data; |
| int i = 1; |
| float f = 7.0f; |
| |
| data.set(5); |
| EXPECT_TRUE(data.find(&i)); |
| EXPECT_FALSE(data.find(&f)); |
| EXPECT_EQ(i, 5); |
| |
| data.set(6.0f); |
| EXPECT_FALSE(data.find(&i)); |
| EXPECT_TRUE(data.find(&f)); |
| EXPECT_EQ(f, 6.0f); |
| |
| AData<int, sp<RefBase>>::RelaxedBasic objdata; // relaxed type support |
| sp<ABuffer> buf = new ABuffer(16), buf2; |
| sp<RefBase> obj; |
| |
| objdata.set(buf); |
| EXPECT_TRUE(objdata.find(&buf2)); |
| EXPECT_EQ(buf, buf2); |
| EXPECT_FALSE(objdata.find(&i)); |
| EXPECT_TRUE(objdata.find(&obj)); |
| EXPECT_TRUE(obj == buf); |
| |
| obj = buf; |
| objdata.set(obj); // storing as sp<RefBase> |
| EXPECT_FALSE(objdata.find(&buf2)); // not stored as ABuffer(!) |
| EXPECT_TRUE(objdata.find(&obj)); |
| } |
| |
| struct SampleTypeFlagger { |
| typedef unsigned type; |
| enum Flags : type { |
| kEmpty = 100, |
| kInt, |
| kConstCharPtr, |
| kEventCounter, |
| kEventCounterPointer, |
| kEventCounterSharedPointer, |
| kEventCounterUniquePointer, |
| kEventCounterWeakPointer, |
| kEventCounterSP, |
| kEventCounterWP, |
| }; |
| constexpr static type mask = ~Flags(0); |
| constexpr static type flagFor(void*) { return kEmpty; } |
| constexpr static type flagFor(int*) { return kInt; } |
| constexpr static type flagFor(const char**) { return kConstCharPtr; } |
| constexpr static type flagFor(EventCounter*) { return kEventCounter; } |
| constexpr static type flagFor(EventCounter**) { return kEventCounterPointer; } |
| constexpr static |
| type flagFor(std::shared_ptr<EventCounter>*) { return kEventCounterSharedPointer; } |
| constexpr static |
| type flagFor(std::unique_ptr<EventCounter>*) { return kEventCounterUniquePointer; } |
| constexpr static type flagFor(std::weak_ptr<EventCounter>*) { return kEventCounterWeakPointer; } |
| constexpr static type flagFor(sp<EventCounter>*) { return kEventCounterSP; } |
| constexpr static type flagFor(wp<EventCounter>*) { return kEventCounterWP; } |
| constexpr static bool canDeleteAs(type object, type del) { return del == object; } |
| template <typename T> struct store { typedef T as_type; }; |
| }; |
| |
| TEST_F(ADataTest, AData_SimpleTest) { |
| int _int = 0; |
| const char *_constCharPtr = NULL; |
| AData<int, const char *>::Custom<SampleTypeFlagger> u; |
| EXPECT_FALSE(u.used()); |
| EXPECT_FALSE(u.find<int>(&_int)); |
| EXPECT_FALSE(u.find<const char *>(&_constCharPtr)); |
| |
| EXPECT_TRUE(u.set<int>(4)); |
| EXPECT_TRUE(u.used()); |
| EXPECT_TRUE(u.find<int>(&_int)); |
| EXPECT_EQ(4, _int); |
| EXPECT_FALSE(u.find<const char *>(&_constCharPtr)); |
| EXPECT_EQ(NULL, _constCharPtr); |
| |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.used()); |
| EXPECT_FALSE(u.find<int>(&_int)); |
| EXPECT_FALSE(u.find<const char *>(&_constCharPtr)); |
| |
| EXPECT_TRUE(u.set<int>(5)); |
| EXPECT_TRUE(u.set<int>(6)); |
| EXPECT_TRUE(u.find<int>(&_int)); |
| EXPECT_EQ(6, _int); |
| |
| EXPECT_TRUE(u.set<const char *>("hello")); |
| EXPECT_TRUE(u.used()); |
| EXPECT_FALSE(u.find<int>(&_int)); |
| EXPECT_TRUE(u.find<const char *>(&_constCharPtr)); |
| EXPECT_STREQ("hello", _constCharPtr); |
| |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.used()); |
| EXPECT_FALSE(u.find<int>(&_int)); |
| EXPECT_FALSE(u.find<const char *>(&_constCharPtr)); |
| |
| EXPECT_TRUE(u.set<const char *>("world")); |
| EXPECT_TRUE(u.set<const char *>("!!")); |
| EXPECT_TRUE(u.used()); |
| EXPECT_FALSE(u.find<int>(&_int)); |
| EXPECT_TRUE(u.find<const char *>(&_constCharPtr)); |
| EXPECT_STREQ("!!", _constCharPtr); |
| |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_TRUE(u.find(&_constCharPtr)); |
| } |
| |
| void set(std::unique_ptr<int> &dst, std::unique_ptr<int> &&src) { |
| dst = std::move(src); |
| } |
| |
| void set(std::unique_ptr<int> &dst, std::unique_ptr<int> &src) { |
| dst = std::move(src); |
| } |
| |
| TEST_F(ADataTest, AData_CopyMoveTest) { |
| int destructions = 0; |
| int _int = 0; |
| std::shared_ptr<EventCounter> _shared; |
| std::unique_ptr<EventCounter> _unique; |
| std::weak_ptr<EventCounter> _weak; |
| const std::shared_ptr<EventCounter> _constShared(new EventCounter(&destructions)); |
| const std::unique_ptr<EventCounter> _constUnique = nullptr; |
| |
| AData<int, std::weak_ptr<EventCounter>, std::shared_ptr<EventCounter>, |
| std::unique_ptr<EventCounter>>::Basic u; |
| |
| // test that data is empty |
| EXPECT_FALSE(u.used()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| |
| // test that integer can be stored and read |
| EXPECT_TRUE(u.set<int>(1)); |
| EXPECT_TRUE(u.used()); |
| EXPECT_TRUE(u.find(&_int)); |
| EXPECT_EQ(1, _int); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| |
| // test that movable type (unique_ptr) can be moved in and read out, and it moves |
| _unique = std::unique_ptr<EventCounter>(new EventCounter(&destructions, 123)); |
| EXPECT_TRUE(u.set(std::move(_unique))); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_TRUE(u.used()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_TRUE(u.remove(&_unique)); |
| EXPECT_TRUE((bool)_unique); |
| if (_unique) { |
| EXPECT_EQ(123, _unique->magic()); |
| } |
| |
| // the unique value should have been removed but still accessible as nullptr |
| EXPECT_TRUE(u.remove(&_unique)); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_EQ(1, destructions); |
| |
| // test that movable-only type (unique_ptr) can be stored without moving (and is still |
| // moved) |
| _unique = std::unique_ptr<EventCounter>(new EventCounter(&destructions, 321)); |
| EXPECT_TRUE(u.set(std::move(_unique))); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_TRUE(u.set(std::unique_ptr<EventCounter>(new EventCounter(&destructions, 1234)))); |
| EXPECT_EQ(2, destructions); |
| EXPECT_TRUE(u.remove(&_unique)); |
| EXPECT_TRUE((bool)_unique); |
| if (_unique) { |
| EXPECT_EQ(1234, _unique->magic()); |
| } |
| EXPECT_TRUE(u.set(std::move(_unique))); |
| EXPECT_EQ(2, destructions); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_EQ(3, destructions); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| |
| // u.set(_constUnique); |
| |
| // test that copiable & movable type (shared_ptr) is copied unless explicitly moved. |
| _shared = std::make_shared<EventCounter>(&destructions, 234); |
| EXPECT_EQ(1L, _shared.use_count()); |
| EXPECT_TRUE(u.set(_shared)); |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| EXPECT_EQ(2L, _shared.use_count()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_EQ(2L, _shared.use_count()); |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| // explicitly move in shared_ptr |
| EXPECT_TRUE(u.set(std::move(_shared))); |
| EXPECT_EQ(0, _shared.use_count()); // shared should be nullptr |
| EXPECT_FALSE((bool)_shared); |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_EQ(2L, _shared.use_count()); // now both u and _shared contains the object |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_EQ(2L, _shared.use_count()); // still both u and _shared contains the object |
| |
| EXPECT_TRUE(u.clear()); |
| EXPECT_TRUE(_shared.unique()); // now only _shared contains the object |
| |
| EXPECT_TRUE(u.set(_constShared)); |
| EXPECT_EQ(2L, _constShared.use_count()); // even though it is const, we can add a use count |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_EQ(3L, _shared.use_count()); // now u, _shared and _constShared contains the const object |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(1234, _shared->magic()); |
| } |
| |
| // test that weak pointer can be copied in (support for moving is from C++14 only) |
| _weak = _shared; |
| EXPECT_EQ(_weak.use_count(), _shared.use_count()); |
| EXPECT_TRUE(u.set(_weak)); |
| |
| _weak.reset(); |
| EXPECT_EQ(_weak.use_count(), 0); |
| |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.use_count(), _shared.use_count()); |
| EXPECT_EQ(_weak.lock(), _shared); |
| |
| // we can remove a weak pointer multiple times |
| _weak.reset(); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.use_count(), _shared.use_count()); |
| EXPECT_EQ(_weak.lock(), _shared); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| }; |
| |
| TEST_F(ADataTest, AData_RelaxedCopyMoveTest) { |
| int destructions = 0; |
| int _int = 0; |
| std::shared_ptr<DerivedCounter> _shared; |
| std::unique_ptr<DerivedCounter> _unique, _unique2; |
| std::weak_ptr<DerivedCounter> _weak; |
| std::shared_ptr<EventCounter> _shared_base; |
| std::unique_ptr<EventCounter> _unique_base; |
| std::weak_ptr<EventCounter> _weak_base; |
| const std::shared_ptr<DerivedCounter> _constShared(new DerivedCounter(&destructions)); |
| const std::unique_ptr<DerivedCounter> _constUnique = nullptr; |
| |
| AData<int, std::unique_ptr<EventCounter>, std::shared_ptr<EventCounter>, |
| std::weak_ptr<EventCounter>>::RelaxedBasic u; |
| |
| // test that data is empty |
| EXPECT_FALSE(u.used()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that integer can be stored and read |
| EXPECT_TRUE(u.set<int>(1)); |
| EXPECT_TRUE(u.used()); |
| EXPECT_TRUE(u.find(&_int)); |
| EXPECT_EQ(1, _int); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that movable type (unique_ptr) can be moved in and read out, and it moves |
| _unique = std::unique_ptr<DerivedCounter>(new DerivedCounter(&destructions, 123)); |
| EXPECT_TRUE(u.set(std::move(_unique))); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_TRUE(u.used()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_TRUE(u.remove(&_unique)); |
| EXPECT_TRUE((bool)_unique); |
| if (_unique) { |
| EXPECT_EQ(123, _unique->magic()); |
| } |
| |
| // the unique value should have been removed but still accessible as nullptr |
| EXPECT_TRUE(u.remove(&_unique)); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_EQ(1, destructions); |
| |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_TRUE(u.remove(&_unique_base)); |
| EXPECT_FALSE((bool)_unique_base); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that movable-only type (unique_ptr) can be stored without moving (and is still |
| // moved) |
| _unique = std::unique_ptr<DerivedCounter>(new DerivedCounter(&destructions, 321)); |
| EXPECT_TRUE(u.set(std::move(_unique))); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_TRUE(u.set(std::unique_ptr<DerivedCounter>(new DerivedCounter(&destructions, 1234)))); |
| EXPECT_EQ(2, destructions); |
| EXPECT_TRUE(u.remove(&_unique)); |
| EXPECT_TRUE((bool)_unique); |
| if (_unique) { |
| EXPECT_EQ(1234, _unique->magic()); |
| } |
| EXPECT_TRUE(u.set(std::move(_unique))); |
| EXPECT_EQ(2, destructions); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_EQ(3, destructions); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that unique pointer can be set and removed as base type (but removed as derived only |
| // if it was set as derived type) |
| _unique = std::unique_ptr<DerivedCounter>(new DerivedCounter(&destructions, 321)); |
| EXPECT_TRUE(u.set(std::move(_unique))); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_TRUE(u.remove(&_unique_base)); |
| EXPECT_TRUE((bool)_unique_base); |
| if (_unique_base) { |
| EXPECT_EQ(321, _unique_base->magic()); |
| } |
| EXPECT_TRUE(u.remove(&_unique)); |
| EXPECT_FALSE((bool)_unique); |
| |
| EXPECT_TRUE(u.set(std::move(_unique_base))); |
| EXPECT_FALSE((bool)_unique_base); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE((bool)_unique); |
| EXPECT_TRUE(u.remove(&_unique_base)); |
| EXPECT_TRUE((bool)_unique_base); |
| if (_unique_base) { |
| EXPECT_EQ(321, _unique_base->magic()); |
| } |
| |
| EXPECT_EQ(3, destructions); |
| EXPECT_TRUE(u.remove(&_unique_base)); |
| EXPECT_EQ(4, destructions); |
| EXPECT_FALSE((bool)_unique_base); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // u.set(_constUnique); |
| |
| // test that copiable & movable type (shared_ptr) is copied unless explicitly moved. |
| _shared = std::make_shared<DerivedCounter>(&destructions, 234); |
| EXPECT_EQ(1L, _shared.use_count()); |
| EXPECT_TRUE(u.set(_shared)); |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| EXPECT_EQ(2L, _shared.use_count()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| EXPECT_EQ(2L, _shared.use_count()); |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| // explicitly move in shared_ptr |
| EXPECT_TRUE(u.set(std::move(_shared))); |
| EXPECT_EQ(0, _shared.use_count()); // shared should be nullptr |
| EXPECT_FALSE((bool)_shared); |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_EQ(2L, _shared.use_count()); // now both u and _shared contains the object |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_EQ(2L, _shared.use_count()); // still both u and _shared contains the object |
| |
| EXPECT_TRUE(u.clear()); |
| EXPECT_TRUE(_shared.unique()); // now only _shared contains the object |
| |
| EXPECT_TRUE(u.set(_constShared)); |
| EXPECT_EQ(2L, _constShared.use_count()); // even though it is const, we can add a use count |
| EXPECT_TRUE(u.find(&_shared)); |
| EXPECT_EQ(3L, _shared.use_count()); // now u, _shared and _constShared contains the const object |
| EXPECT_TRUE((bool)_shared); |
| if (_shared) { |
| EXPECT_EQ(1234, _shared->magic()); |
| } |
| |
| // test that shared pointer can be set and removed as base type (but removed as derived only |
| // if it was set as derived type) |
| EXPECT_TRUE(u.find(&_shared_base)); |
| EXPECT_TRUE((bool)_shared_base); |
| if (_shared_base) { |
| EXPECT_EQ(1234, _shared_base->magic()); |
| } |
| EXPECT_EQ(4L, _shared.use_count()); // now u, _shared, _constShared and _shared_base contains |
| // the const object |
| _shared.reset(); |
| EXPECT_EQ(3L, _shared_base.use_count()); // now u, _constShared and _shared_base contains it |
| EXPECT_TRUE(u.clear()); |
| EXPECT_EQ(2L, _shared_base.use_count()); // now _constShared and _shared_base contains it |
| |
| EXPECT_TRUE(u.set(_shared_base)); // now u_ also contains it as base class |
| EXPECT_EQ(3L, _shared_base.use_count()); |
| EXPECT_FALSE(u.find(&_shared)); // cannot get it as derived type |
| EXPECT_FALSE((bool)_shared); |
| _shared_base.reset(); |
| EXPECT_TRUE(u.find(&_shared_base)); // can still get it as base type |
| EXPECT_TRUE((bool)_shared_base); |
| if (_shared_base) { |
| EXPECT_EQ(1234, _shared_base->magic()); |
| } |
| _shared = std::static_pointer_cast<DerivedCounter>(_shared_base); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that weak pointer can be copied in (support for moving is from C++14 only) |
| _weak = _shared; |
| EXPECT_EQ(_weak.use_count(), _shared.use_count()); |
| EXPECT_TRUE(u.set(_weak)); |
| |
| _weak.reset(); |
| EXPECT_EQ(_weak.use_count(), 0); |
| |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.use_count(), _shared.use_count()); |
| EXPECT_EQ(_weak.lock(), _shared); |
| |
| // we can remove a weak pointer multiple times |
| _weak.reset(); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.use_count(), _shared.use_count()); |
| EXPECT_EQ(_weak.lock(), _shared); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that weak pointer can be set and removed as base type (but removed as derived only |
| // if it was set as derived type) |
| _weak = _shared; |
| EXPECT_TRUE(u.set(_weak)); |
| EXPECT_TRUE(u.find(&_weak_base)); |
| EXPECT_FALSE(_weak_base.expired()); |
| if (!_weak_base.expired()) { |
| EXPECT_EQ(1234, _weak_base.lock()->magic()); |
| } |
| // now _shared, _constShared and _shared_base contains the const object |
| EXPECT_EQ(3L, _weak.use_count()); |
| _weak.reset(); |
| EXPECT_EQ(3L, _weak_base.use_count()); // _weak did not hold a reference |
| _shared.reset(); |
| EXPECT_EQ(2L, _weak_base.use_count()); // now u, _constShared and _shared_base contains it |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.remove(&_unique)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.remove(&_unique_base)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| EXPECT_TRUE(u.set(_weak_base)); // now u_ also contains it as base class |
| EXPECT_FALSE(u.find(&_weak)); // cannot get it as derived type |
| EXPECT_TRUE(_weak.expired()); |
| _weak_base.reset(); |
| EXPECT_TRUE(u.find(&_weak_base)); // can still get it as base type |
| EXPECT_FALSE(_weak_base.expired()); |
| if (!_weak_base.expired()) { |
| EXPECT_EQ(1234, _weak_base.lock()->magic()); |
| } |
| }; |
| |
| TEST_F(ADataTest, AData_AndroidSpTest) { |
| int destructions = 0; |
| int _int = 0; |
| sp<EventCounter> _shared; |
| wp<EventCounter> _weak; |
| const sp<EventCounter> _constShared(new EventCounter(&destructions)); |
| |
| AData<int, sp<EventCounter>, wp<EventCounter>>::Strict<uint8_t> u; |
| |
| // test that data is empty |
| EXPECT_FALSE(u.used()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| |
| // test that integer can be stored and read |
| EXPECT_TRUE(u.set<int>(1)); |
| EXPECT_TRUE(u.used()); |
| EXPECT_TRUE(u.find(&_int)); |
| EXPECT_EQ(1, _int); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| |
| // test that copiable & movable type (shared_ptr) is copied unless explicitly moved. |
| _shared = new EventCounter(&destructions, 234); |
| _weak = _shared; // used for tracking #234 |
| |
| EXPECT_TRUE(u.set(_shared)); |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| _shared.clear(); |
| EXPECT_EQ(NULL, _shared.get()); |
| EXPECT_NE(nullptr, _weak.promote().get()); // u still holds object |
| |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_TRUE(u.find(&_shared)); // now u and _shared both hold object |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| // verify the find did not move out object |
| _shared.clear(); |
| EXPECT_EQ(NULL, _shared.get()); |
| EXPECT_NE(nullptr, _weak.promote().get()); // u still holds object |
| EXPECT_TRUE(u.find(&_shared)); // now u and _shared both hold object |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| // verify that we can set object multiple times |
| EXPECT_TRUE(u.set(_shared)); |
| |
| // explicitly move in sp |
| EXPECT_TRUE(u.set(std::move(_shared))); |
| EXPECT_FALSE((bool)_shared.get()); // android also clears sp<> on move... |
| EXPECT_TRUE(u.find(&_shared)); // still can get it back |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_weak)); |
| |
| EXPECT_TRUE(u.used()); |
| EXPECT_TRUE(u.clear()); // now only _shared contains the object |
| EXPECT_FALSE(u.used()); |
| |
| // we still hold a copy |
| EXPECT_TRUE((bool)_shared.get()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); // _shared still contains the object |
| |
| EXPECT_TRUE(u.set(_constShared)); |
| EXPECT_TRUE(u.find(&_shared)); // now _shared contains _constShared |
| EXPECT_EQ(NULL, _weak.promote().get()); // original _shared is now lost |
| |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(1234, _shared->magic()); |
| } |
| EXPECT_TRUE(u.clear()); |
| |
| // test that wp can be copied in |
| _weak = _shared; |
| EXPECT_TRUE(u.set(_weak)); |
| |
| _weak.clear(); |
| |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.promote(), _shared); |
| |
| // we can remove a weak pointer multiple times |
| _weak.clear(); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.promote(), _shared); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| }; |
| |
| TEST_F(ADataTest, AData_RelaxedAndroidSpTest) { |
| int destructions = 0; |
| int _int = 0; |
| sp<EventCounter> _shared; |
| wp<EventCounter> _weak; |
| sp<RefBase> _shared_base; |
| wp<RefBase> _weak_base; |
| const sp<EventCounter> _constShared(new EventCounter(&destructions)); |
| |
| AData<int, sp<RefBase>, wp<RefBase>>::Relaxed<uint16_t> u; |
| |
| // test that data is empty |
| EXPECT_FALSE(u.used()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that integer can be stored and read |
| EXPECT_TRUE(u.set<int>(1)); |
| EXPECT_TRUE(u.used()); |
| EXPECT_TRUE(u.find(&_int)); |
| EXPECT_EQ(1, _int); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that copiable & movable type (shared_ptr) is copied unless explicitly moved. |
| _shared = new EventCounter(&destructions, 234); |
| _weak = _shared; // used for tracking #234 |
| |
| EXPECT_TRUE(u.set(_shared)); |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| _shared.clear(); |
| EXPECT_EQ(NULL, _shared.get()); |
| EXPECT_NE(nullptr, _weak.promote().get()); // u still holds object |
| |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_TRUE(u.find(&_shared)); // now u and _shared both hold object |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| // verify the find did not move out object |
| _shared.clear(); |
| EXPECT_EQ(NULL, _shared.get()); |
| EXPECT_NE(nullptr, _weak.promote().get()); // u still holds object |
| EXPECT_TRUE(u.find(&_shared)); // now u and _shared both hold object |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| |
| // verify that we can set object multiple times |
| EXPECT_TRUE(u.set(_shared)); |
| |
| // explicitly move in sp |
| EXPECT_TRUE(u.set(std::move(_shared))); |
| EXPECT_FALSE((bool)_shared.get()); // android also clears sp<> on move... |
| EXPECT_TRUE(u.find(&_shared)); // still can get it back |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(234, _shared->magic()); |
| } |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| EXPECT_TRUE(u.used()); |
| EXPECT_TRUE(u.clear()); // now only _shared contains the object |
| EXPECT_FALSE(u.used()); |
| |
| // we still hold a copy |
| EXPECT_TRUE((bool)_shared.get()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); // _shared still contains the object |
| |
| EXPECT_TRUE(u.set(_constShared)); |
| EXPECT_TRUE(u.find(&_shared)); // now _shared contains _constShared |
| EXPECT_EQ(NULL, _weak.promote().get()); // original _shared is now lost |
| |
| EXPECT_TRUE((bool)_shared.get()); |
| if (_shared.get()) { |
| EXPECT_EQ(1234, _shared->magic()); |
| } |
| EXPECT_TRUE(u.clear()); |
| |
| // test that shared pointer can be set and removed as base type (but removed as derived only |
| // if it was set as derived type) |
| EXPECT_TRUE(u.set(_constShared)); |
| EXPECT_TRUE(u.find(&_shared_base)); |
| EXPECT_TRUE((bool)_shared_base.get()); |
| if (_shared_base.get()) { |
| EXPECT_EQ(1234, static_cast<EventCounter*>(_shared_base.get())->magic()); |
| } |
| _shared.clear(); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_TRUE((bool)_shared_base.get()); |
| if (_shared_base.get()) { |
| EXPECT_EQ(1234, static_cast<EventCounter*>(_shared_base.get())->magic()); |
| } |
| |
| EXPECT_TRUE(u.set(_shared_base)); // now u contains it as base class |
| EXPECT_TRUE((bool)_shared_base.get()); |
| EXPECT_FALSE(u.find(&_shared)); // cannot get it as derived type |
| EXPECT_FALSE((bool)_shared.get()); |
| _shared_base.clear(); |
| EXPECT_TRUE(u.find(&_shared_base)); // can still get it as base type |
| EXPECT_TRUE((bool)_shared_base.get()); |
| if (_shared_base.get()) { |
| EXPECT_EQ(1234, static_cast<EventCounter*>(_shared_base.get())->magic()); |
| } |
| _shared = static_cast<DerivedCounter*>(_shared_base.get()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that wp can be copied in |
| _weak = _shared; |
| EXPECT_TRUE(u.set(_weak)); |
| |
| _weak.clear(); |
| |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.promote(), _shared); |
| |
| // we can remove a weak pointer multiple times |
| _weak.clear(); |
| EXPECT_TRUE(u.find(&_weak)); |
| EXPECT_EQ(_weak.promote(), _shared); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| // test that weak pointer can be set and removed as base type (but removed as derived only |
| // if it was set as derived type) |
| _weak = _shared; |
| EXPECT_TRUE(u.set(_weak)); |
| EXPECT_TRUE(u.find(&_weak_base)); |
| EXPECT_TRUE(_weak_base.promote().get() == _shared.get()); |
| |
| _weak.clear(); |
| _shared.clear(); |
| EXPECT_TRUE(u.clear()); |
| EXPECT_FALSE(u.find(&_int)); |
| EXPECT_FALSE(u.find(&_shared)); |
| EXPECT_FALSE(u.find(&_weak)); |
| EXPECT_FALSE(u.find(&_shared_base)); |
| EXPECT_FALSE(u.find(&_weak_base)); |
| |
| EXPECT_TRUE(u.set(_weak_base)); // now u_ also contains it as base class |
| EXPECT_FALSE(u.find(&_weak)); // cannot get it as derived type |
| EXPECT_FALSE(_weak.promote().get()); |
| _weak_base.clear(); |
| EXPECT_TRUE(u.find(&_weak_base)); // can still get it as base type |
| EXPECT_TRUE(_weak_base.promote().get()); |
| if (_weak_base.promote().get()) { |
| EXPECT_EQ(1234, static_cast<EventCounter*>(_weak_base.promote().get())->magic()); |
| } |
| }; |
| |
| TEST_F(ADataTest, AData_AssignmentTest) { |
| typedef AData<sp<ABuffer>, int32_t>::Basic Data; |
| |
| sp<ABuffer> buf1 = new ABuffer((void *)"hello", 6); |
| wp<ABuffer> buf1w = buf1; |
| |
| Data obj1; |
| obj1.set(buf1); |
| EXPECT_NE(buf1w.promote(), nullptr); |
| buf1.clear(); |
| EXPECT_NE(buf1w.promote(), nullptr); |
| obj1.clear(); |
| EXPECT_EQ(buf1w.promote(), nullptr); |
| |
| buf1 = new ABuffer((void *)"again", 6); |
| buf1w = buf1; |
| |
| obj1.set(buf1); |
| EXPECT_TRUE(obj1.used()); |
| Data obj2 = obj1; |
| |
| sp<ABuffer> buf2; |
| EXPECT_TRUE(obj2.find(&buf2)); |
| EXPECT_EQ(buf2, buf1); |
| buf1.clear(); |
| buf2.clear(); |
| EXPECT_NE(buf1w.promote(), nullptr); |
| obj1.clear(); |
| EXPECT_NE(buf1w.promote(), nullptr); |
| obj2.clear(); |
| EXPECT_EQ(buf1w.promote(), nullptr); |
| |
| buf1 = new ABuffer((void *)"still", 6); |
| buf1w = buf1; |
| |
| obj1.set(buf1); |
| EXPECT_TRUE(obj1.used()); |
| obj2 = std::move(obj1); |
| EXPECT_FALSE(obj1.used()); |
| |
| EXPECT_TRUE(obj2.find(&buf2)); |
| EXPECT_EQ(buf2, buf1); |
| buf1.clear(); |
| buf2.clear(); |
| EXPECT_NE(buf1w.promote(), nullptr); |
| obj2.clear(); |
| EXPECT_EQ(buf1w.promote(), nullptr); |
| |
| typedef AData<sp<ABuffer>, std::unique_ptr<int32_t>>::Basic Data2; |
| Data2 obj3, obj4; |
| |
| buf1 = new ABuffer((void *)"hence", 6); |
| obj3.set(buf1); |
| obj4 = std::move(obj3); |
| EXPECT_FALSE(obj3.used()); |
| EXPECT_TRUE(obj4.find(&buf2)); |
| EXPECT_EQ(buf2, buf1); |
| } |
| |
| } // namespace android |