/* * 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 #include //#include #include #include 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 u; u.emplace(4); u.del(); EXPECT_EQ(4, u.get()); // 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("hello"); EXPECT_STREQ("hello", u.get()); u.del(); // u.del(); // u.emplace(4); u.emplace(); u.del(); u.emplace(~0); u.del(); EXPECT_EQ(~0, u.get()); u.emplace(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()); u.del(); AUnion d; int destructions = 0; d.emplace(&destructions); d.del(); EXPECT_EQ(1, destructions); EventCounter *ctr = new EventCounter(&destructions); d.emplace(ctr); d.del(); EXPECT_EQ(1, destructions); delete ctr; EXPECT_EQ(2, destructions); AUnion, std::unique_ptr> md; md.emplace>(new EventCounter(&destructions)); std::shared_ptr copy(md.get>()); std::weak_ptr weak(copy); EXPECT_EQ(2, destructions); copy.reset(); EXPECT_EQ(2, destructions); md.del>(); EXPECT_EQ(3, destructions); EXPECT_TRUE(weak.expired()); md.emplace>(new EventCounter(&destructions)); EXPECT_EQ(3, destructions); std::unique_ptr unique = std::move(md.get>()); EXPECT_EQ(3, destructions); EXPECT_FALSE((bool)md.get>()); md.del>(); EXPECT_EQ(3, destructions); md.emplace>(std::move(unique)); EXPECT_TRUE((bool)md.get>()); EXPECT_EQ(3, destructions); md.del>(); EXPECT_EQ(4, destructions); } TEST_F(ADataTest, AData_StaticTest) { using namespace std; static_assert(is_copy_assignable>::value, ""); static_assert(is_copy_constructible>::value, ""); static_assert(is_default_constructible>::value, ""); static_assert(is_copy_assignable>::value, ""); static_assert(is_copy_constructible>::value, ""); static_assert(is_default_constructible>::value, ""); static_assert(!is_copy_assignable>::value, ""); static_assert(!is_copy_constructible>::value, ""); static_assert(is_default_constructible>::value, ""); static_assert(is_copy_assignable>::value, ""); static_assert(is_copy_constructible>::value, ""); static_assert(is_default_constructible>::value, ""); static_assert(is_copy_assignable>::value, ""); static_assert(is_copy_constructible>::value, ""); static_assert(is_default_constructible>::value, ""); static_assert(is_convertible, shared_ptr>::value, ""); static_assert(!is_convertible, shared_ptr>::value, ""); static_assert(is_convertible, unique_ptr>::value, ""); static_assert(!is_convertible, unique_ptr>::value, ""); static_assert(is_convertible, shared_ptr>::value, ""); static_assert(!is_convertible, unique_ptr>::value, ""); static_assert(is_convertible, weak_ptr>::value, ""); static_assert(!is_convertible, weak_ptr>::value, ""); static_assert(is_convertible, weak_ptr>::value, ""); static_assert(!is_convertible, shared_ptr>::value, ""); static_assert(is_convertible, sp>::value, ""); static_assert(is_convertible, sp>::value, "YES"); static_assert(is_convertible, wp>::value, ""); static_assert(is_convertible, wp>::value, "YES"); static_assert(is_convertible, wp>::value, ""); static_assert(!is_convertible, sp>::value, ""); } TEST_F(ADataTest, AData_SampleTest) { AData::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>::RelaxedBasic objdata; // relaxed type support sp buf = new ABuffer(16), buf2; sp 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 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*) { return kEventCounterSharedPointer; } constexpr static type flagFor(std::unique_ptr*) { return kEventCounterUniquePointer; } constexpr static type flagFor(std::weak_ptr*) { return kEventCounterWeakPointer; } constexpr static type flagFor(sp*) { return kEventCounterSP; } constexpr static type flagFor(wp*) { return kEventCounterWP; } constexpr static bool canDeleteAs(type object, type del) { return del == object; } template struct store { typedef T as_type; }; }; TEST_F(ADataTest, AData_SimpleTest) { int _int = 0; const char *_constCharPtr = NULL; AData::Custom u; EXPECT_FALSE(u.used()); EXPECT_FALSE(u.find(&_int)); EXPECT_FALSE(u.find(&_constCharPtr)); EXPECT_TRUE(u.set(4)); EXPECT_TRUE(u.used()); EXPECT_TRUE(u.find(&_int)); EXPECT_EQ(4, _int); EXPECT_FALSE(u.find(&_constCharPtr)); EXPECT_EQ(NULL, _constCharPtr); EXPECT_TRUE(u.clear()); EXPECT_FALSE(u.used()); EXPECT_FALSE(u.find(&_int)); EXPECT_FALSE(u.find(&_constCharPtr)); EXPECT_TRUE(u.set(5)); EXPECT_TRUE(u.set(6)); EXPECT_TRUE(u.find(&_int)); EXPECT_EQ(6, _int); EXPECT_TRUE(u.set("hello")); EXPECT_TRUE(u.used()); EXPECT_FALSE(u.find(&_int)); EXPECT_TRUE(u.find(&_constCharPtr)); EXPECT_STREQ("hello", _constCharPtr); EXPECT_TRUE(u.clear()); EXPECT_FALSE(u.used()); EXPECT_FALSE(u.find(&_int)); EXPECT_FALSE(u.find(&_constCharPtr)); EXPECT_TRUE(u.set("world")); EXPECT_TRUE(u.set("!!")); EXPECT_TRUE(u.used()); EXPECT_FALSE(u.find(&_int)); EXPECT_TRUE(u.find(&_constCharPtr)); EXPECT_STREQ("!!", _constCharPtr); EXPECT_FALSE(u.find(&_int)); EXPECT_TRUE(u.find(&_constCharPtr)); } void set(std::unique_ptr &dst, std::unique_ptr &&src) { dst = std::move(src); } void set(std::unique_ptr &dst, std::unique_ptr &src) { dst = std::move(src); } TEST_F(ADataTest, AData_CopyMoveTest) { int destructions = 0; int _int = 0; std::shared_ptr _shared; std::unique_ptr _unique; std::weak_ptr _weak; const std::shared_ptr _constShared(new EventCounter(&destructions)); const std::unique_ptr _constUnique = nullptr; AData, std::shared_ptr, std::unique_ptr>::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(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(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(new EventCounter(&destructions, 321)); EXPECT_TRUE(u.set(std::move(_unique))); EXPECT_FALSE((bool)_unique); EXPECT_TRUE(u.set(std::unique_ptr(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(&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_EQ(1L, _shared.use_count()); // 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 _shared; std::unique_ptr _unique, _unique2; std::weak_ptr _weak; std::shared_ptr _shared_base; std::unique_ptr _unique_base; std::weak_ptr _weak_base; const std::shared_ptr _constShared(new DerivedCounter(&destructions)); const std::unique_ptr _constUnique = nullptr; AData, std::shared_ptr, std::weak_ptr>::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(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(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(new DerivedCounter(&destructions, 321)); EXPECT_TRUE(u.set(std::move(_unique))); EXPECT_FALSE((bool)_unique); EXPECT_TRUE(u.set(std::unique_ptr(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(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(&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_EQ(1L, _shared.use_count()); // 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(_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 _shared; wp _weak; const sp _constShared(new EventCounter(&destructions)); AData, wp>::Strict 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(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 _shared; wp _weak; sp _shared_base; wp _weak_base; const sp _constShared(new EventCounter(&destructions)); AData, wp>::Relaxed 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(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(_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(_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(_shared_base.get())->magic()); } _shared = static_cast(_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(_weak_base.promote().get())->magic()); } }; TEST_F(ADataTest, AData_AssignmentTest) { typedef AData, int32_t>::Basic Data; sp buf1 = new ABuffer((void *)"hello", 6); wp 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 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, std::unique_ptr>::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