| #include <cstring> |
| |
| #include "gtest/gtest.h" |
| |
| #include "chre/util/unique_ptr.h" |
| |
| using chre::MakeUnique; |
| using chre::MakeUniqueZeroFill; |
| using chre::UniquePtr; |
| |
| struct Value { |
| Value(int value) : value(value) { |
| constructionCounter++; |
| } |
| |
| ~Value() { |
| constructionCounter--; |
| } |
| |
| Value &operator=(Value &&other) { |
| value = other.value; |
| return *this; |
| } |
| |
| int value; |
| static int constructionCounter; |
| }; |
| |
| int Value::constructionCounter = 0; |
| |
| TEST(UniquePtr, Construct) { |
| UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe); |
| ASSERT_FALSE(myInt.isNull()); |
| EXPECT_EQ(myInt.get()->value, 0xcafe); |
| EXPECT_EQ(myInt->value, 0xcafe); |
| EXPECT_EQ((*myInt).value, 0xcafe); |
| EXPECT_EQ(myInt[0].value, 0xcafe); |
| } |
| |
| struct BigArray { |
| int x[2048]; |
| }; |
| |
| TEST(UniquePtr, MakeUniqueZeroFill) { |
| BigArray baseline = {}; |
| auto myArray = MakeUniqueZeroFill<BigArray>(); |
| ASSERT_FALSE(myArray.isNull()); |
| // Note that this doesn't actually test things properly, because we don't |
| // guarantee that malloc is not already giving us zeroed out memory. To |
| // properly do it, we could inject the allocator, but this function is simple |
| // enough that it's not really worth the effort. |
| EXPECT_EQ(std::memcmp(&baseline, myArray.get(), sizeof(baseline)), 0); |
| } |
| |
| TEST(UniquePtr, MoveConstruct) { |
| UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe); |
| ASSERT_FALSE(myInt.isNull()); |
| Value *value = myInt.get(); |
| |
| UniquePtr<Value> moved(std::move(myInt)); |
| EXPECT_EQ(moved.get(), value); |
| EXPECT_EQ(myInt.get(), nullptr); |
| } |
| |
| TEST(UniquePtr, Move) { |
| Value::constructionCounter = 0; |
| |
| { |
| UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe); |
| ASSERT_FALSE(myInt.isNull()); |
| EXPECT_EQ(Value::constructionCounter, 1); |
| |
| UniquePtr<Value> myMovedInt = MakeUnique<Value>(0); |
| ASSERT_FALSE(myMovedInt.isNull()); |
| EXPECT_EQ(Value::constructionCounter, 2); |
| myMovedInt = std::move(myInt); |
| ASSERT_FALSE(myMovedInt.isNull()); |
| ASSERT_TRUE(myInt.isNull()); |
| EXPECT_EQ(myMovedInt.get()->value, 0xcafe); |
| } |
| |
| EXPECT_EQ(Value::constructionCounter, 0); |
| } |
| |
| TEST(UniquePtr, Release) { |
| Value::constructionCounter = 0; |
| |
| Value *value1, *value2; |
| { |
| UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe); |
| ASSERT_FALSE(myInt.isNull()); |
| EXPECT_EQ(Value::constructionCounter, 1); |
| value1 = myInt.get(); |
| EXPECT_NE(value1, nullptr); |
| value2 = myInt.release(); |
| EXPECT_EQ(value1, value2); |
| EXPECT_EQ(myInt.get(), nullptr); |
| EXPECT_TRUE(myInt.isNull()); |
| } |
| |
| EXPECT_EQ(Value::constructionCounter, 1); |
| EXPECT_EQ(value2->value, 0xcafe); |
| value2->~Value(); |
| chre::memoryFree(value2); |
| } |
| |
| TEST(UniquePtr, Reset) { |
| Value::constructionCounter = 0; |
| |
| { |
| UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe); |
| EXPECT_EQ(myInt.get()->value, 0xcafe); |
| EXPECT_EQ(Value::constructionCounter, 1); |
| myInt.reset(nullptr); |
| EXPECT_EQ(myInt.get(), nullptr); |
| EXPECT_EQ(Value::constructionCounter, 0); |
| |
| myInt = MakeUnique<Value>(0xcafe); |
| UniquePtr<Value> myInt2 = MakeUnique<Value>(0xface); |
| EXPECT_EQ(Value::constructionCounter, 2); |
| myInt.reset(myInt2.release()); |
| EXPECT_EQ(Value::constructionCounter, 1); |
| EXPECT_EQ(myInt.get()->value, 0xface); |
| EXPECT_EQ(myInt2.get(), nullptr); |
| |
| myInt.reset(); |
| EXPECT_EQ(myInt.get(), nullptr); |
| } |
| |
| EXPECT_EQ(Value::constructionCounter, 0); |
| } |
| |
| TEST(UniquePtr, EqualityOperator) { |
| Value::constructionCounter = 0; |
| |
| { |
| UniquePtr<Value> myInt = MakeUnique<Value>(0xcafe); |
| EXPECT_TRUE(myInt != nullptr); |
| |
| myInt.reset(); |
| EXPECT_TRUE(myInt == nullptr); |
| } |
| |
| EXPECT_EQ(Value::constructionCounter, 0); |
| } |