upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
331
android/system/chre/util/tests/array_queue_test.cc
Normal file
331
android/system/chre/util/tests/array_queue_test.cc
Normal file
|
@ -0,0 +1,331 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "chre/util/array_queue.h"
|
||||
|
||||
using chre::ArrayQueue;
|
||||
|
||||
namespace {
|
||||
constexpr int kMaxTestCapacity = 10;
|
||||
int destructor_count[kMaxTestCapacity];
|
||||
int constructor_count;
|
||||
|
||||
class DummyElement {
|
||||
public:
|
||||
DummyElement() {
|
||||
constructor_count++;
|
||||
};
|
||||
DummyElement(int i) {
|
||||
val_ = i;
|
||||
constructor_count++;
|
||||
};
|
||||
~DummyElement() {
|
||||
if (val_ >= 0 && val_ < kMaxTestCapacity) {
|
||||
destructor_count[val_]++;
|
||||
}
|
||||
};
|
||||
void setValue(int i) {
|
||||
val_ = i;
|
||||
}
|
||||
|
||||
private:
|
||||
int val_ = kMaxTestCapacity - 1;
|
||||
};
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, IsEmptyInitially) {
|
||||
ArrayQueue<int, 4> q;
|
||||
EXPECT_TRUE(q.empty());
|
||||
EXPECT_EQ(0, q.size());
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, SimplePushPop) {
|
||||
ArrayQueue<int, 3> q;
|
||||
EXPECT_TRUE(q.push(1));
|
||||
EXPECT_TRUE(q.push(2));
|
||||
q.pop();
|
||||
EXPECT_TRUE(q.push(3));
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, TestSize) {
|
||||
ArrayQueue<int, 2> q;
|
||||
q.push(1);
|
||||
EXPECT_EQ(1, q.size());
|
||||
q.push(2);
|
||||
EXPECT_EQ(2, q.size());
|
||||
q.pop();
|
||||
EXPECT_EQ(1, q.size());
|
||||
q.pop();
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, TestEmpty) {
|
||||
ArrayQueue<int, 2> q;
|
||||
q.push(1);
|
||||
EXPECT_FALSE(q.empty());
|
||||
q.push(2);
|
||||
EXPECT_FALSE(q.empty());
|
||||
q.pop();
|
||||
EXPECT_FALSE(q.empty());
|
||||
q.pop();
|
||||
EXPECT_TRUE(q.empty());
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, PopWhenEmpty) {
|
||||
ArrayQueue<int, 4> q;
|
||||
q.pop();
|
||||
EXPECT_EQ(0, q.size());
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, PushWhenFull) {
|
||||
ArrayQueue<int, 2> q;
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
EXPECT_FALSE(q.push(3));
|
||||
}
|
||||
|
||||
TEST(ArrayQueueDeathTest, FrontWhenEmpty) {
|
||||
ArrayQueue<int, 4> q;
|
||||
EXPECT_DEATH(q.front(), "");
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, TestFront) {
|
||||
ArrayQueue<int, 3> q;
|
||||
q.push(1);
|
||||
EXPECT_EQ(1, q.front());
|
||||
q.pop();
|
||||
q.push(2);
|
||||
EXPECT_EQ(2, q.front());
|
||||
}
|
||||
|
||||
TEST(ArrayQueueDeathTest, InvalidSubscript) {
|
||||
ArrayQueue<int, 2> q;
|
||||
EXPECT_DEATH(q[0], "");
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, Subscript) {
|
||||
ArrayQueue<int, 2> q;
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
EXPECT_EQ(1, q[0]);
|
||||
EXPECT_EQ(2, q[1]);
|
||||
q.pop();
|
||||
EXPECT_EQ(2, q[0]);
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, RemoveWithInvalidIndex) {
|
||||
ArrayQueue<int, 3> q;
|
||||
EXPECT_FALSE(q.remove(0));
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, RemoveWithIndex) {
|
||||
ArrayQueue<int, 3> q;
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
q.remove(0);
|
||||
EXPECT_EQ(2, q.front());
|
||||
EXPECT_EQ(1, q.size());
|
||||
q.push(3);
|
||||
q.remove(1);
|
||||
EXPECT_EQ(2, q.front());
|
||||
EXPECT_EQ(1, q.size());
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, DestructorCalledOnPop) {
|
||||
for (size_t i = 0; i < kMaxTestCapacity; ++i) {
|
||||
destructor_count[i] = 0;
|
||||
}
|
||||
|
||||
ArrayQueue<DummyElement, 3> q;
|
||||
DummyElement e;
|
||||
q.push(e);
|
||||
q.push(e);
|
||||
|
||||
q.front().setValue(0);
|
||||
q.pop();
|
||||
EXPECT_EQ(1, destructor_count[0]);
|
||||
|
||||
q.front().setValue(1);
|
||||
q.pop();
|
||||
EXPECT_EQ(1, destructor_count[1]);
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, ElementsDestructedWhenQueueDestructed) {
|
||||
for (size_t i = 0; i < kMaxTestCapacity; ++i) {
|
||||
destructor_count[i] = 0;
|
||||
}
|
||||
|
||||
// Put q and e in the scope so their destructor will be called going
|
||||
// out of scope.
|
||||
{ ArrayQueue<DummyElement, 4> q;
|
||||
DummyElement e;
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
q.push(e);
|
||||
q[i].setValue(i);
|
||||
}
|
||||
|
||||
q.~ArrayQueue();
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
EXPECT_EQ(1, destructor_count[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check destructor count.
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
EXPECT_EQ(1, destructor_count[i]);
|
||||
}
|
||||
EXPECT_EQ(0, destructor_count[3]);
|
||||
EXPECT_EQ(1, destructor_count[kMaxTestCapacity - 1]);
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, EmplaceTest) {
|
||||
constructor_count = 0;
|
||||
ArrayQueue<DummyElement, 2> q;
|
||||
|
||||
EXPECT_TRUE(q.emplace(0));
|
||||
EXPECT_EQ(1, constructor_count);
|
||||
EXPECT_EQ(1, q.size());
|
||||
|
||||
EXPECT_TRUE(q.emplace(1));
|
||||
EXPECT_EQ(2, constructor_count);
|
||||
EXPECT_EQ(2, q.size());
|
||||
|
||||
EXPECT_FALSE(q.emplace(2));
|
||||
EXPECT_EQ(2, constructor_count);
|
||||
EXPECT_EQ(2, q.size());
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, EmptyQueueIterator) {
|
||||
ArrayQueue<int, 4> q;
|
||||
|
||||
ArrayQueue<int, 4>::iterator it = q.begin();
|
||||
EXPECT_TRUE(it == q.end());
|
||||
EXPECT_FALSE(it != q.end());
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, SimpleIterator) {
|
||||
ArrayQueue<int, 4> q;
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
q.push(i);
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
for (ArrayQueue<int, 4>::iterator it = q.begin(); it != q.end(); ++it) {
|
||||
EXPECT_EQ(q[index++], *it);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
ArrayQueue<int, 4>::iterator it = q.begin();
|
||||
while (it != q.end()) {
|
||||
EXPECT_EQ(q[index++], *it++);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
q.pop();
|
||||
q.push(i + 3);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
it = q.begin();
|
||||
while (it != q.end()) {
|
||||
EXPECT_EQ(q[index++], *it++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, IteratorAndPush) {
|
||||
ArrayQueue<int, 4> q;
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
q.push(i);
|
||||
}
|
||||
|
||||
ArrayQueue<int, 4>::iterator it_b = q.begin();
|
||||
ArrayQueue<int, 4>::iterator it_e = q.end();
|
||||
q.push(3);
|
||||
|
||||
size_t index = 0;
|
||||
while (it_b != it_e) {
|
||||
EXPECT_EQ(q[index++], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, IteratorAndPop) {
|
||||
ArrayQueue<int, 4> q;
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
q.push(i);
|
||||
}
|
||||
|
||||
ArrayQueue<int, 4>::iterator it_b = q.begin();
|
||||
q.pop();
|
||||
it_b++;
|
||||
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
EXPECT_EQ(q[i], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, IteratorAndRemove) {
|
||||
ArrayQueue<int, 4> q;
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
q.push(i);
|
||||
}
|
||||
|
||||
ArrayQueue<int, 4>::iterator it_b = q.begin();
|
||||
q.remove(1);
|
||||
|
||||
EXPECT_EQ(q[0], *it_b);
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, IteratorAndEmplace) {
|
||||
ArrayQueue<int, 4> q;
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
q.push(i);
|
||||
}
|
||||
|
||||
ArrayQueue<int, 4>::iterator it_b = q.begin();
|
||||
ArrayQueue<int, 4>::iterator it_e = q.end();
|
||||
q.emplace(3);
|
||||
|
||||
size_t index = 0;
|
||||
while (it_b != it_e) {
|
||||
EXPECT_EQ(q[index++], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, SimpleConstIterator) {
|
||||
ArrayQueue<int, 4> q;
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
q.push(i);
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
for (ArrayQueue<int, 4>::const_iterator cit = q.cbegin();
|
||||
cit != q.cend(); ++cit) {
|
||||
EXPECT_EQ(q[index++], *cit);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
ArrayQueue<int, 4>::const_iterator cit = q.cbegin();
|
||||
while (cit != q.cend()) {
|
||||
EXPECT_EQ(q[index++], *cit++);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
q.pop();
|
||||
q.push(i + 3);
|
||||
}
|
||||
|
||||
index = 0;
|
||||
cit = q.cbegin();
|
||||
while (cit != q.cend()) {
|
||||
EXPECT_EQ(q[index++], *cit++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ArrayQueueTest, Full) {
|
||||
ArrayQueue<size_t, 4> q;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
EXPECT_FALSE(q.full());
|
||||
q.push(i);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(q.full());
|
||||
}
|
36
android/system/chre/util/tests/blocking_queue_test.cc
Normal file
36
android/system/chre/util/tests/blocking_queue_test.cc
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/fixed_size_blocking_queue.h"
|
||||
|
||||
using chre::FixedSizeBlockingQueue;
|
||||
|
||||
TEST(FixedSizeBlockingQueue, IsEmptyByDefault) {
|
||||
FixedSizeBlockingQueue<int, 16> blockingQueue;
|
||||
ASSERT_TRUE(blockingQueue.empty());
|
||||
}
|
||||
|
||||
TEST(FixedSizeBlockingQueue, PushPopVerifyOrder) {
|
||||
FixedSizeBlockingQueue<int, 16> blockingQueue;
|
||||
|
||||
ASSERT_TRUE(blockingQueue.push(0x1337));
|
||||
ASSERT_TRUE(blockingQueue.push(0xcafe));
|
||||
|
||||
ASSERT_EQ(blockingQueue.pop(), 0x1337);
|
||||
ASSERT_EQ(blockingQueue.pop(), 0xcafe);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/conditional_lock_guard.h"
|
||||
|
||||
using chre::ConditionalLockGuard;
|
||||
|
||||
class MockMutex {
|
||||
public:
|
||||
MockMutex() : mLockCount(0) {}
|
||||
|
||||
void lock() {
|
||||
mLockCount++;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
mLockCount--;
|
||||
}
|
||||
|
||||
int getLockCount() {
|
||||
return mLockCount;
|
||||
}
|
||||
|
||||
private:
|
||||
int mLockCount;
|
||||
};
|
||||
|
||||
TEST(ConditionalLockGuard, LockUnlock) {
|
||||
MockMutex mutex;
|
||||
ASSERT_EQ(mutex.getLockCount(), 0);
|
||||
|
||||
{
|
||||
ConditionalLockGuard<MockMutex> lock(mutex, true);
|
||||
EXPECT_EQ(mutex.getLockCount(), 1);
|
||||
}
|
||||
|
||||
EXPECT_EQ(mutex.getLockCount(), 0);
|
||||
}
|
||||
|
||||
TEST(ConditionalLockGuard, DontLock) {
|
||||
MockMutex mutex;
|
||||
ASSERT_EQ(mutex.getLockCount(), 0);
|
||||
|
||||
{
|
||||
ConditionalLockGuard<MockMutex> lock(mutex, false);
|
||||
EXPECT_EQ(mutex.getLockCount(), 0);
|
||||
}
|
||||
|
||||
EXPECT_EQ(mutex.getLockCount(), 0);
|
||||
}
|
908
android/system/chre/util/tests/dynamic_vector_test.cc
Normal file
908
android/system/chre/util/tests/dynamic_vector_test.cc
Normal file
|
@ -0,0 +1,908 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/dynamic_vector.h"
|
||||
#include "chre/util/macros.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
using chre::DynamicVector;
|
||||
|
||||
namespace {
|
||||
constexpr int kMaxTestCapacity = 10;
|
||||
int gDestructorCount[kMaxTestCapacity];
|
||||
|
||||
class Dummy {
|
||||
public:
|
||||
~Dummy() {
|
||||
if (mValue >= 0) {
|
||||
gDestructorCount[mValue]++;
|
||||
}
|
||||
};
|
||||
void setValue(int value) {
|
||||
mValue = value;
|
||||
}
|
||||
int getValue() {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
private:
|
||||
int mValue = -1;
|
||||
};
|
||||
|
||||
void resetDestructorCounts() {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gDestructorCount); i++) {
|
||||
gDestructorCount[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, EmptyByDefault) {
|
||||
DynamicVector<int> vector;
|
||||
EXPECT_EQ(vector.data(), nullptr);
|
||||
EXPECT_TRUE(vector.empty());
|
||||
EXPECT_EQ(vector.size(), 0);
|
||||
EXPECT_EQ(vector.capacity(), 0);
|
||||
vector.clear();
|
||||
}
|
||||
|
||||
TEST(DynamicVector, PushBackAndRead) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_TRUE(vector.push_back(0x1337));
|
||||
EXPECT_EQ(vector.size(), 1);
|
||||
EXPECT_EQ(vector.capacity(), 1);
|
||||
EXPECT_EQ(vector.data(), &vector[0]);
|
||||
EXPECT_FALSE(vector.empty());
|
||||
EXPECT_EQ(vector[0], 0x1337);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, PushBackReserveAndReadTrivialType) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_TRUE(vector.emplace_back(0x1337));
|
||||
ASSERT_TRUE(vector.push_back(0xface));
|
||||
int x = 0xcafe;
|
||||
ASSERT_TRUE(vector.push_back(std::move(x)));
|
||||
ASSERT_TRUE(vector.insert(vector.size(), 0xd00d));
|
||||
EXPECT_EQ(vector.size(), 4);
|
||||
EXPECT_EQ(vector.capacity(), 4);
|
||||
EXPECT_EQ(vector[0], 0x1337);
|
||||
EXPECT_EQ(vector[1], 0xface);
|
||||
EXPECT_EQ(vector[2], 0xcafe);
|
||||
EXPECT_EQ(vector[3], 0xd00d);
|
||||
|
||||
ASSERT_TRUE(vector.reserve(8));
|
||||
EXPECT_EQ(vector.size(), 4);
|
||||
EXPECT_EQ(vector.capacity(), 8);
|
||||
EXPECT_EQ(vector[0], 0x1337);
|
||||
EXPECT_EQ(vector[1], 0xface);
|
||||
EXPECT_EQ(vector[2], 0xcafe);
|
||||
EXPECT_EQ(vector[3], 0xd00d);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, CompareEqual) {
|
||||
DynamicVector<int> lhs;
|
||||
ASSERT_TRUE(lhs.push_back(0x1337));
|
||||
ASSERT_TRUE(lhs.push_back(0xface));
|
||||
DynamicVector<int> rhs;
|
||||
ASSERT_TRUE(rhs.push_back(0x1337));
|
||||
ASSERT_TRUE(rhs.push_back(0xface));
|
||||
|
||||
ASSERT_EQ(lhs, rhs); // equal vectors
|
||||
|
||||
ASSERT_TRUE(lhs.push_back(0xb00c));
|
||||
ASSERT_FALSE(lhs == rhs); // different size
|
||||
|
||||
ASSERT_TRUE(rhs.push_back(0xc00b));
|
||||
ASSERT_FALSE(lhs == rhs); // equal size different elements
|
||||
}
|
||||
|
||||
constexpr int kConstructedMagic = 0xdeadbeef;
|
||||
|
||||
class MovableButNonCopyable : public chre::NonCopyable {
|
||||
public:
|
||||
MovableButNonCopyable(int value) : mValue(value) {}
|
||||
|
||||
MovableButNonCopyable(MovableButNonCopyable&& other) {
|
||||
mValue = other.mValue;
|
||||
other.mValue = -1;
|
||||
}
|
||||
|
||||
MovableButNonCopyable& operator=(MovableButNonCopyable&& other) {
|
||||
assert(mMagic == kConstructedMagic);
|
||||
mValue = other.mValue;
|
||||
other.mValue = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int getValue() const {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
private:
|
||||
int mMagic = kConstructedMagic;
|
||||
int mValue;
|
||||
};
|
||||
|
||||
TEST(DynamicVector, PushBackReserveAndReadMovableButNonCopyable) {
|
||||
DynamicVector<MovableButNonCopyable> vector;
|
||||
ASSERT_TRUE(vector.emplace_back(0x1337));
|
||||
ASSERT_TRUE(vector.emplace_back(0xface));
|
||||
MovableButNonCopyable mbnc(0xcafe);
|
||||
ASSERT_TRUE(vector.push_back(std::move(mbnc)));
|
||||
EXPECT_EQ(mbnc.getValue(), -1);
|
||||
MovableButNonCopyable mbnc2(0xd00d);
|
||||
ASSERT_TRUE(vector.insert(vector.size(), std::move(mbnc2)));
|
||||
EXPECT_EQ(mbnc2.getValue(), -1);
|
||||
|
||||
ASSERT_TRUE(vector.reserve(8));
|
||||
EXPECT_EQ(vector[0].getValue(), 0x1337);
|
||||
EXPECT_EQ(vector[1].getValue(), 0xface);
|
||||
EXPECT_EQ(vector[2].getValue(), 0xcafe);
|
||||
EXPECT_EQ(vector[3].getValue(), 0xd00d);
|
||||
EXPECT_EQ(vector.size(), 4);
|
||||
EXPECT_EQ(vector.capacity(), 8);
|
||||
}
|
||||
|
||||
class CopyableButNonMovable {
|
||||
public:
|
||||
CopyableButNonMovable(int value) : mValue(value) {}
|
||||
|
||||
CopyableButNonMovable(const CopyableButNonMovable& other) {
|
||||
mValue = other.mValue;
|
||||
}
|
||||
|
||||
CopyableButNonMovable& operator=(const CopyableButNonMovable& other) {
|
||||
assert(mMagic == kConstructedMagic);
|
||||
mValue = other.mValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CopyableButNonMovable(CopyableButNonMovable&& other) = delete;
|
||||
CopyableButNonMovable& operator=(CopyableButNonMovable&& other) = delete;
|
||||
|
||||
int getValue() const {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
private:
|
||||
int mMagic = kConstructedMagic;
|
||||
int mValue;
|
||||
};
|
||||
|
||||
TEST(DynamicVector, PushBackReserveAndReadCopyableButNonMovable) {
|
||||
DynamicVector<CopyableButNonMovable> vector;
|
||||
ASSERT_TRUE(vector.emplace_back(0x1337));
|
||||
ASSERT_TRUE(vector.emplace_back(0xface));
|
||||
CopyableButNonMovable cbnm(0xcafe);
|
||||
ASSERT_TRUE(vector.push_back(cbnm));
|
||||
CopyableButNonMovable cbnm2(0xd00d);
|
||||
ASSERT_TRUE(vector.insert(vector.size(), cbnm2));
|
||||
|
||||
ASSERT_TRUE(vector.reserve(8));
|
||||
EXPECT_EQ(vector[0].getValue(), 0x1337);
|
||||
EXPECT_EQ(vector[1].getValue(), 0xface);
|
||||
EXPECT_EQ(vector[2].getValue(), 0xcafe);
|
||||
EXPECT_EQ(vector[3].getValue(), 0xd00d);
|
||||
EXPECT_EQ(vector.size(), 4);
|
||||
EXPECT_EQ(vector.capacity(), 8);
|
||||
}
|
||||
|
||||
class MovableAndCopyable {
|
||||
public:
|
||||
MovableAndCopyable(int value) : mValue(value) {}
|
||||
|
||||
MovableAndCopyable(const MovableAndCopyable& other) {
|
||||
mValue = other.mValue;
|
||||
}
|
||||
|
||||
MovableAndCopyable(MovableAndCopyable&& other) {
|
||||
// The move constructor multiplies the value by 2 so that we can see that it
|
||||
// was used
|
||||
mValue = other.mValue * 2;
|
||||
}
|
||||
|
||||
MovableAndCopyable& operator=(const MovableAndCopyable& other) {
|
||||
assert(mMagic == kConstructedMagic);
|
||||
mValue = other.mValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MovableAndCopyable& operator=(MovableAndCopyable&& other) {
|
||||
assert(mMagic == kConstructedMagic);
|
||||
mValue = other.mValue * 2;
|
||||
other.mValue = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int getValue() const {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
private:
|
||||
int mMagic = kConstructedMagic;
|
||||
int mValue;
|
||||
};
|
||||
|
||||
TEST(DynamicVector, ReservePrefersMove) {
|
||||
// Ensure that preference is given to std::move in reserve()
|
||||
DynamicVector<MovableAndCopyable> vector;
|
||||
|
||||
// Reserve enough space for the first two elements.
|
||||
ASSERT_TRUE(vector.reserve(2));
|
||||
ASSERT_TRUE(vector.emplace_back(1000));
|
||||
ASSERT_TRUE(vector.emplace_back(2000));
|
||||
|
||||
// Reserve more than enough space causing a move to be required.
|
||||
ASSERT_TRUE(vector.reserve(4));
|
||||
|
||||
// Move on this type results in a multiplication by 2. Verify that all
|
||||
// elements have been multiplied by 2.
|
||||
EXPECT_EQ(vector[0].getValue(), 2000);
|
||||
EXPECT_EQ(vector[1].getValue(), 4000);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple test helper object to count number of construction and destructions.
|
||||
*/
|
||||
class Foo {
|
||||
public:
|
||||
/**
|
||||
* Construct an object storing a simple integer. Increment the number of
|
||||
* objects that have been constructed of this type.
|
||||
*/
|
||||
Foo(int value) : value(value) {
|
||||
sConstructedCounter++;
|
||||
}
|
||||
|
||||
Foo(const Foo& other) {
|
||||
value = other.value;
|
||||
sConstructedCounter++;
|
||||
}
|
||||
|
||||
Foo(Foo&& other) = delete;
|
||||
|
||||
/**
|
||||
* Tear down the object, decrementing the number of objects that have been
|
||||
* constructed of this type.
|
||||
*/
|
||||
~Foo() {
|
||||
sConstructedCounter--;
|
||||
}
|
||||
|
||||
//! The number of objects of this type that have been constructed.
|
||||
static ssize_t sConstructedCounter;
|
||||
|
||||
//! The value stored in the object to verify the contents of this object after
|
||||
//! construction.
|
||||
int value;
|
||||
};
|
||||
|
||||
//! Storage for the Foo reference counter.
|
||||
ssize_t Foo::sConstructedCounter = 0;
|
||||
|
||||
TEST(DynamicVector, EmplaceBackAndDestruct) {
|
||||
Foo::sConstructedCounter = 0;
|
||||
{
|
||||
DynamicVector<Foo> vector;
|
||||
ASSERT_TRUE(vector.emplace_back(1000));
|
||||
ASSERT_TRUE(vector.emplace_back(2000));
|
||||
ASSERT_TRUE(vector.emplace_back(3000));
|
||||
ASSERT_TRUE(vector.emplace_back(4000));
|
||||
|
||||
ASSERT_EQ(vector[0].value, 1000);
|
||||
ASSERT_EQ(vector[1].value, 2000);
|
||||
ASSERT_EQ(vector[2].value, 3000);
|
||||
ASSERT_EQ(vector[3].value, 4000);
|
||||
|
||||
EXPECT_EQ(Foo::sConstructedCounter, 4);
|
||||
}
|
||||
|
||||
EXPECT_EQ(Foo::sConstructedCounter, 0);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, InsertEmpty) {
|
||||
DynamicVector<int> vector;
|
||||
EXPECT_CHRE_ASSERT(EXPECT_FALSE(vector.insert(1, 0x1337)));
|
||||
|
||||
// Insert to empty vector
|
||||
ASSERT_TRUE(vector.insert(0, 0x1337));
|
||||
EXPECT_EQ(vector[0], 0x1337);
|
||||
|
||||
// Insert at end triggering grow
|
||||
ASSERT_EQ(vector.capacity(), 1);
|
||||
EXPECT_TRUE(vector.insert(1, 0xface));
|
||||
EXPECT_EQ(vector[0], 0x1337);
|
||||
EXPECT_EQ(vector[1], 0xface);
|
||||
|
||||
// Insert at beginning triggering grow
|
||||
ASSERT_EQ(vector.capacity(), 2);
|
||||
EXPECT_TRUE(vector.insert(0, 0xcafe));
|
||||
EXPECT_EQ(vector[0], 0xcafe);
|
||||
EXPECT_EQ(vector[1], 0x1337);
|
||||
EXPECT_EQ(vector[2], 0xface);
|
||||
|
||||
// Insert at middle with spare capacity
|
||||
ASSERT_EQ(vector.capacity(), 4);
|
||||
EXPECT_TRUE(vector.insert(1, 0xdead));
|
||||
EXPECT_EQ(vector[0], 0xcafe);
|
||||
EXPECT_EQ(vector[1], 0xdead);
|
||||
EXPECT_EQ(vector[2], 0x1337);
|
||||
EXPECT_EQ(vector[3], 0xface);
|
||||
|
||||
// Insert at middle triggering grow
|
||||
ASSERT_EQ(vector.capacity(), 4);
|
||||
EXPECT_TRUE(vector.insert(2, 0xbeef));
|
||||
EXPECT_EQ(vector[0], 0xcafe);
|
||||
EXPECT_EQ(vector[1], 0xdead);
|
||||
EXPECT_EQ(vector[2], 0xbeef);
|
||||
EXPECT_EQ(vector[3], 0x1337);
|
||||
EXPECT_EQ(vector[4], 0xface);
|
||||
|
||||
// Insert at beginning with spare capacity
|
||||
ASSERT_EQ(vector.capacity(), 8);
|
||||
ASSERT_EQ(vector.size(), 5);
|
||||
EXPECT_TRUE(vector.insert(0, 0xabad));
|
||||
EXPECT_EQ(vector[0], 0xabad);
|
||||
EXPECT_EQ(vector[1], 0xcafe);
|
||||
EXPECT_EQ(vector[2], 0xdead);
|
||||
EXPECT_EQ(vector[3], 0xbeef);
|
||||
EXPECT_EQ(vector[4], 0x1337);
|
||||
EXPECT_EQ(vector[5], 0xface);
|
||||
|
||||
// Insert at end with spare capacity
|
||||
ASSERT_EQ(vector.size(), 6);
|
||||
EXPECT_TRUE(vector.insert(vector.size(), 0xc0de));
|
||||
EXPECT_EQ(vector[0], 0xabad);
|
||||
EXPECT_EQ(vector[1], 0xcafe);
|
||||
EXPECT_EQ(vector[2], 0xdead);
|
||||
EXPECT_EQ(vector[3], 0xbeef);
|
||||
EXPECT_EQ(vector[4], 0x1337);
|
||||
EXPECT_EQ(vector[5], 0xface);
|
||||
EXPECT_EQ(vector[6], 0xc0de);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, PushBackInsertInMiddleAndRead) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_TRUE(vector.push_back(0x1337));
|
||||
ASSERT_TRUE(vector.push_back(0xface));
|
||||
ASSERT_TRUE(vector.push_back(0xcafe));
|
||||
ASSERT_TRUE(vector.insert(1, 0xbeef));
|
||||
|
||||
ASSERT_EQ(vector[0], 0x1337);
|
||||
ASSERT_EQ(vector[1], 0xbeef);
|
||||
ASSERT_EQ(vector[2], 0xface);
|
||||
ASSERT_EQ(vector[3], 0xcafe);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, PushBackAndErase) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_TRUE(vector.push_back(0x1337));
|
||||
ASSERT_TRUE(vector.push_back(0xcafe));
|
||||
ASSERT_TRUE(vector.push_back(0xbeef));
|
||||
ASSERT_TRUE(vector.push_back(0xface));
|
||||
|
||||
vector.erase(1);
|
||||
|
||||
ASSERT_EQ(vector[0], 0x1337);
|
||||
ASSERT_EQ(vector[1], 0xbeef);
|
||||
ASSERT_EQ(vector[2], 0xface);
|
||||
ASSERT_EQ(vector.size(), 3);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, FindEmpty) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_EQ(vector.find(0), 0);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, FindWithElements) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_TRUE(vector.push_back(0x1337));
|
||||
ASSERT_TRUE(vector.push_back(0xcafe));
|
||||
ASSERT_TRUE(vector.push_back(0xbeef));
|
||||
|
||||
ASSERT_EQ(vector.find(0x1337), 0);
|
||||
ASSERT_EQ(vector.find(0xcafe), 1);
|
||||
ASSERT_EQ(vector.find(0xbeef), 2);
|
||||
ASSERT_EQ(vector.find(1000), 3);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, EraseDestructorCalled) {
|
||||
resetDestructorCounts();
|
||||
|
||||
DynamicVector<Dummy> vector;
|
||||
vector.reserve(4);
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
vector.emplace_back();
|
||||
vector[i].setValue(i);
|
||||
}
|
||||
|
||||
// last item before erase is '3'.
|
||||
vector.erase(1);
|
||||
EXPECT_EQ(0, gDestructorCount[0]);
|
||||
EXPECT_EQ(0, gDestructorCount[1]);
|
||||
EXPECT_EQ(0, gDestructorCount[2]);
|
||||
EXPECT_EQ(1, gDestructorCount[3]);
|
||||
|
||||
// last item before erase is still '3'.
|
||||
vector.erase(2);
|
||||
EXPECT_EQ(0, gDestructorCount[0]);
|
||||
EXPECT_EQ(0, gDestructorCount[1]);
|
||||
EXPECT_EQ(0, gDestructorCount[2]);
|
||||
EXPECT_EQ(2, gDestructorCount[3]);
|
||||
|
||||
// last item before erase is now '2'.
|
||||
vector.erase(0);
|
||||
EXPECT_EQ(0, gDestructorCount[0]);
|
||||
EXPECT_EQ(0, gDestructorCount[1]);
|
||||
EXPECT_EQ(1, gDestructorCount[2]);
|
||||
EXPECT_EQ(2, gDestructorCount[3]);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, Clear) {
|
||||
resetDestructorCounts();
|
||||
|
||||
DynamicVector<Dummy> vector;
|
||||
vector.reserve(4);
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
vector.emplace_back();
|
||||
vector[i].setValue(i);
|
||||
}
|
||||
|
||||
vector.clear();
|
||||
EXPECT_EQ(vector.size(), 0);
|
||||
EXPECT_EQ(vector.capacity(), 4);
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
EXPECT_EQ(gDestructorCount[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that a vector wrapping an array doesn't call the destructor when
|
||||
// the vector is destructed
|
||||
TEST(DynamicVector, WrapDoesntCallDestructor) {
|
||||
resetDestructorCounts();
|
||||
|
||||
Dummy array[4];
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
array[i].setValue(i);
|
||||
}
|
||||
|
||||
{
|
||||
DynamicVector<Dummy> vector;
|
||||
vector.wrap(array, ARRAY_SIZE(array));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
EXPECT_EQ(gDestructorCount[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that a wrapped vector does call the destructor when it's expected
|
||||
// as part of an API call
|
||||
TEST(DynamicVector, WrapExplicitlyCallsDestructor) {
|
||||
resetDestructorCounts();
|
||||
|
||||
Dummy array[4];
|
||||
constexpr size_t kSize = ARRAY_SIZE(array);
|
||||
static_assert(ARRAY_SIZE(array) <= ARRAY_SIZE(gDestructorCount),
|
||||
"gDestructorCount array must fit test array");
|
||||
for (size_t i = 0; i < kSize; ++i) {
|
||||
array[i].setValue(i);
|
||||
}
|
||||
DynamicVector<Dummy> vector;
|
||||
vector.wrap(array, ARRAY_SIZE(array));
|
||||
|
||||
vector.erase(kSize - 1);
|
||||
for (size_t i = 0; i < kSize - 1; i++) {
|
||||
EXPECT_EQ(gDestructorCount[i], 0);
|
||||
}
|
||||
EXPECT_EQ(gDestructorCount[kSize - 1], 1);
|
||||
|
||||
vector.clear();
|
||||
for (size_t i = 0; i < kSize; ++i) {
|
||||
EXPECT_EQ(gDestructorCount[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVectorDeathTest, SwapWithInvalidIndex) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
EXPECT_DEATH(vector.swap(0, 2), "");
|
||||
}
|
||||
|
||||
TEST(DynamicVectorDeathTest, SwapWithInvalidIndices) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
EXPECT_DEATH(vector.swap(2, 3), "");
|
||||
}
|
||||
|
||||
TEST(DynamicVector, Swap) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
|
||||
vector.swap(0, 1);
|
||||
EXPECT_EQ(vector[0], 0xcafe);
|
||||
EXPECT_EQ(vector[1], 0x1337);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, BackFront) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0x1337);
|
||||
EXPECT_EQ(vector.front(), 0x1337);
|
||||
EXPECT_EQ(vector.back(), 0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
EXPECT_EQ(vector.front(), 0x1337);
|
||||
EXPECT_EQ(vector.back(), 0xcafe);
|
||||
vector.erase(0);
|
||||
EXPECT_EQ(vector.front(), 0xcafe);
|
||||
EXPECT_EQ(vector.back(), 0xcafe);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, Iterator) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
size_t index = 0;
|
||||
for (DynamicVector<int>::iterator it = vector.begin();
|
||||
it != vector.end(); ++it) {
|
||||
EXPECT_EQ(vector[index++], *it);
|
||||
}
|
||||
|
||||
DynamicVector<int>::iterator it = vector.begin() + vector.size() - 1;
|
||||
EXPECT_EQ(vector[vector.size() - 1], *it);
|
||||
|
||||
it = vector.begin() + vector.size();
|
||||
EXPECT_TRUE(it == vector.end());
|
||||
}
|
||||
|
||||
TEST(DynamicVector, ConstIterator) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
size_t index = 0;
|
||||
for (DynamicVector<int>::const_iterator cit = vector.cbegin();
|
||||
cit != vector.cend(); ++cit) {
|
||||
EXPECT_EQ(vector[index++], *cit);
|
||||
}
|
||||
|
||||
DynamicVector<int>::const_iterator cit = vector.cbegin() + vector.size() - 1;
|
||||
EXPECT_EQ(vector[vector.size() - 1], *cit);
|
||||
|
||||
cit = vector.cbegin() + vector.size();
|
||||
EXPECT_TRUE(cit == vector.cend());
|
||||
}
|
||||
|
||||
TEST(DynamicVector, IteratorAndPushBack) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
size_t oldCapacity = vector.capacity();
|
||||
|
||||
DynamicVector<int>::iterator it_b = vector.begin();
|
||||
DynamicVector<int>::iterator it_e = vector.end();
|
||||
|
||||
vector.push_back(3);
|
||||
ASSERT_TRUE(oldCapacity == vector.capacity());
|
||||
|
||||
size_t index = 0;
|
||||
for (; it_b != it_e; ++it_b) {
|
||||
EXPECT_EQ(vector[index++], *it_b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, IteratorAndEmplaceBack) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
size_t oldCapacity = vector.capacity();
|
||||
|
||||
DynamicVector<int>::iterator it_b = vector.begin();
|
||||
DynamicVector<int>::iterator it_e = vector.end();
|
||||
|
||||
vector.emplace_back(3);
|
||||
ASSERT_TRUE(oldCapacity == vector.capacity());
|
||||
|
||||
size_t index = 0;
|
||||
for (; it_b != it_e; ++it_b) {
|
||||
EXPECT_EQ(vector[index++], *it_b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, IteratorAndReserve) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
size_t oldCapacity = vector.capacity();
|
||||
|
||||
DynamicVector<int>::iterator it_b = vector.begin();
|
||||
DynamicVector<int>::iterator it_e = vector.end();
|
||||
|
||||
vector.reserve(oldCapacity);
|
||||
ASSERT_TRUE(oldCapacity == vector.capacity());
|
||||
|
||||
size_t index = 0;
|
||||
for (; it_b != it_e; ++it_b) {
|
||||
EXPECT_EQ(vector[index++], *it_b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, IteratorAndInsert) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
size_t oldCapacity = vector.capacity();
|
||||
|
||||
DynamicVector<int>::iterator it_b = vector.begin();
|
||||
|
||||
vector.insert(2, 3);
|
||||
ASSERT_TRUE(oldCapacity == vector.capacity());
|
||||
|
||||
size_t index = 0;
|
||||
while (index < 2) {
|
||||
EXPECT_EQ(vector[index++], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, IteratorAndErase) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
DynamicVector<int>::iterator it_b = vector.begin();
|
||||
|
||||
vector.erase(2);
|
||||
|
||||
size_t index = 0;
|
||||
while (index < 2) {
|
||||
EXPECT_EQ(vector[index++], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, IteratorAndSwap) {
|
||||
DynamicVector<int> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
vector.push_back(3);
|
||||
|
||||
DynamicVector<int>::iterator it_b = vector.begin();
|
||||
|
||||
vector.swap(1, 3);
|
||||
|
||||
size_t index = 0;
|
||||
while (index < 4) {
|
||||
if (index != 1 && index != 3) {
|
||||
EXPECT_EQ(vector[index], *it_b);
|
||||
}
|
||||
index++;
|
||||
it_b++;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, MoveConstruct) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_TRUE(vector.push_back(0));
|
||||
ASSERT_TRUE(vector.push_back(1));
|
||||
ASSERT_TRUE(vector.push_back(2));
|
||||
|
||||
DynamicVector<int> movedVector(std::move(vector));
|
||||
EXPECT_EQ(vector.data(), nullptr);
|
||||
EXPECT_NE(movedVector.data(), nullptr);
|
||||
EXPECT_EQ(vector.size(), 0);
|
||||
EXPECT_EQ(movedVector.size(), 3);
|
||||
EXPECT_EQ(vector.capacity(), 0);
|
||||
EXPECT_EQ(movedVector.capacity(), 4);
|
||||
}
|
||||
|
||||
// Tests basic functionality of a vector wrapping an array
|
||||
TEST(DynamicVector, Wrap) {
|
||||
constexpr size_t kSize = 4;
|
||||
int buf[kSize];
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
buf[i] = i;
|
||||
}
|
||||
|
||||
DynamicVector<int> vector;
|
||||
EXPECT_TRUE(vector.owns_data());
|
||||
vector.wrap(buf, kSize);
|
||||
EXPECT_FALSE(vector.owns_data());
|
||||
EXPECT_EQ(vector.size(), kSize);
|
||||
EXPECT_EQ(vector.capacity(), kSize);
|
||||
EXPECT_EQ(vector.data(), buf);
|
||||
|
||||
EXPECT_CHRE_ASSERT(EXPECT_FALSE(vector.reserve(8)));
|
||||
EXPECT_CHRE_ASSERT(EXPECT_FALSE(vector.push_back(-1)));
|
||||
EXPECT_CHRE_ASSERT(EXPECT_FALSE(vector.emplace_back(-1)));
|
||||
EXPECT_CHRE_ASSERT(EXPECT_FALSE(vector.insert(1, -1)));
|
||||
EXPECT_CHRE_ASSERT(EXPECT_FALSE(vector.copy_array(buf, kSize)));
|
||||
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
EXPECT_EQ(vector[i], i);
|
||||
}
|
||||
|
||||
vector.erase(0);
|
||||
for (size_t i = 0; i < kSize - 1; i++) {
|
||||
EXPECT_EQ(vector[i], i + 1);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(vector.push_back(kSize + 1));
|
||||
EXPECT_EQ(vector.back(), kSize + 1);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, MoveWrappedVector) {
|
||||
constexpr size_t kSize = 4;
|
||||
int buf[kSize];
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
buf[i] = i;
|
||||
}
|
||||
|
||||
DynamicVector<int> vector1;
|
||||
vector1.wrap(buf, kSize);
|
||||
|
||||
DynamicVector<int> vector2 = std::move(vector1);
|
||||
EXPECT_TRUE(vector1.owns_data());
|
||||
EXPECT_EQ(vector1.size(), 0);
|
||||
EXPECT_EQ(vector1.capacity(), 0);
|
||||
EXPECT_EQ(vector1.data(), nullptr);
|
||||
|
||||
EXPECT_FALSE(vector2.owns_data());
|
||||
EXPECT_EQ(vector2.size(), kSize);
|
||||
EXPECT_EQ(vector2.capacity(), kSize);
|
||||
EXPECT_EQ(vector2.data(), buf);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, Unwrap) {
|
||||
constexpr size_t kSize = 4;
|
||||
int buf[kSize];
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
buf[i] = i;
|
||||
}
|
||||
|
||||
DynamicVector<int> vec;
|
||||
vec.wrap(buf, kSize);
|
||||
ASSERT_FALSE(vec.owns_data());
|
||||
|
||||
vec.unwrap();
|
||||
EXPECT_TRUE(vec.owns_data());
|
||||
EXPECT_EQ(vec.size(), 0);
|
||||
EXPECT_EQ(vec.capacity(), 0);
|
||||
EXPECT_EQ(vec.data(), nullptr);
|
||||
|
||||
EXPECT_TRUE(vec.push_back(1));
|
||||
}
|
||||
|
||||
TEST(DynamicVector, CopyArray) {
|
||||
constexpr size_t kSize = 4;
|
||||
int buf[kSize];
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
buf[i] = i;
|
||||
}
|
||||
|
||||
DynamicVector<int> vec;
|
||||
ASSERT_TRUE(vec.copy_array(buf, kSize));
|
||||
EXPECT_TRUE(vec.owns_data());
|
||||
|
||||
EXPECT_EQ(vec.size(), kSize);
|
||||
EXPECT_EQ(vec.capacity(), kSize);
|
||||
EXPECT_NE(vec.data(), buf);
|
||||
|
||||
EXPECT_TRUE(vec.push_back(kSize));
|
||||
EXPECT_EQ(vec.size(), kSize + 1);
|
||||
EXPECT_GE(vec.capacity(), kSize + 1);
|
||||
|
||||
for (size_t i = 0; i < kSize + 1; i++) {
|
||||
EXPECT_EQ(vec[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, CopyArrayHandlesDestructor) {
|
||||
resetDestructorCounts();
|
||||
constexpr size_t kSize = 4;
|
||||
|
||||
{
|
||||
DynamicVector<Dummy> vec;
|
||||
{
|
||||
Dummy array[kSize];
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
array[i].setValue(i);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(vec.copy_array(array, kSize));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
EXPECT_EQ(gDestructorCount[i], 1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
ASSERT_TRUE(vec[i].getValue() == i);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < kSize; i++) {
|
||||
EXPECT_EQ(gDestructorCount[i], 2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DynamicVector, CopyEmptyArray) {
|
||||
DynamicVector<int> vec;
|
||||
|
||||
EXPECT_TRUE(vec.copy_array(nullptr, 0));
|
||||
EXPECT_EQ(vec.size(), 0);
|
||||
|
||||
vec.emplace_back(1);
|
||||
EXPECT_TRUE(vec.copy_array(nullptr, 0));
|
||||
EXPECT_EQ(vec.size(), 0);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, PrepareForPush) {
|
||||
DynamicVector<int> vector;
|
||||
EXPECT_EQ(vector.size(), 0);
|
||||
EXPECT_EQ(vector.capacity(), 0);
|
||||
|
||||
// Perform an initial prepareForPush operation which causes a size of one.
|
||||
ASSERT_TRUE(vector.prepareForPush());
|
||||
EXPECT_EQ(vector.size(), 0);
|
||||
EXPECT_EQ(vector.capacity(), 1);
|
||||
ASSERT_TRUE(vector.push_back(0xcafe));
|
||||
EXPECT_EQ(vector.size(), 1);
|
||||
EXPECT_EQ(vector.capacity(), 1);
|
||||
|
||||
// Verify that it becomes larger
|
||||
ASSERT_TRUE(vector.prepareForPush());
|
||||
EXPECT_EQ(vector[0], 0xcafe);
|
||||
EXPECT_EQ(vector.size(), 1);
|
||||
EXPECT_EQ(vector.capacity(), 2);
|
||||
|
||||
// The vector should not become any larger than necessary.
|
||||
ASSERT_TRUE(vector.prepareForPush());
|
||||
EXPECT_EQ(vector[0], 0xcafe);
|
||||
EXPECT_EQ(vector.size(), 1);
|
||||
EXPECT_EQ(vector.capacity(), 2);
|
||||
}
|
||||
|
||||
TEST(DynamicVector, RidiculouslyHugeReserveFails) {
|
||||
DynamicVector<int> vector;
|
||||
ASSERT_FALSE(vector.reserve(SIZE_MAX));
|
||||
}
|
||||
|
||||
TEST(DynamicVector, PopBack) {
|
||||
DynamicVector<int> vector;
|
||||
constexpr size_t kSize = 4;
|
||||
for (int i = 0; i < kSize; i++) {
|
||||
vector.push_back(i);
|
||||
}
|
||||
|
||||
for (int i = kSize - 1; i >= 0; i--) {
|
||||
EXPECT_EQ(vector.back(), i);
|
||||
vector.pop_back();
|
||||
}
|
||||
EXPECT_TRUE(vector.empty());
|
||||
}
|
302
android/system/chre/util/tests/fixed_size_vector_test.cc
Normal file
302
android/system/chre/util/tests/fixed_size_vector_test.cc
Normal file
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/fixed_size_vector.h"
|
||||
|
||||
using chre::FixedSizeVector;
|
||||
|
||||
namespace {
|
||||
constexpr int kMaxTestCapacity = 10;
|
||||
int destructor_count[kMaxTestCapacity];
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
~Foo() {
|
||||
if (mValue >= 0) {
|
||||
destructor_count[mValue]++;
|
||||
}
|
||||
};
|
||||
void setValue(int value) {
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
private:
|
||||
int mValue = -1;
|
||||
};
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, EmptyWithCapacityWithDefault) {
|
||||
FixedSizeVector<int, 8> testVector;
|
||||
ASSERT_NE(testVector.data(), nullptr);
|
||||
ASSERT_EQ(testVector.size(), 0);
|
||||
ASSERT_EQ(testVector.capacity(), 8);
|
||||
ASSERT_TRUE(testVector.empty());
|
||||
ASSERT_FALSE(testVector.full());
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, PushBackOneAndRead) {
|
||||
FixedSizeVector<int, 8> testVector;
|
||||
testVector.push_back(0x1337);
|
||||
ASSERT_NE(testVector.data(), nullptr);
|
||||
ASSERT_EQ(testVector.size(), 1);
|
||||
ASSERT_EQ(testVector.capacity(), 8);
|
||||
ASSERT_FALSE(testVector.empty());
|
||||
ASSERT_FALSE(testVector.full());
|
||||
ASSERT_EQ(testVector[0], 0x1337);
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, PushBackUntilFullAndRead) {
|
||||
FixedSizeVector<int, 4> testVector;
|
||||
testVector.push_back(1000);
|
||||
testVector.push_back(2000);
|
||||
testVector.push_back(3000);
|
||||
testVector.push_back(4000);
|
||||
|
||||
ASSERT_NE(testVector.data(), nullptr);
|
||||
ASSERT_TRUE(testVector.full());
|
||||
ASSERT_FALSE(testVector.empty());
|
||||
ASSERT_EQ(testVector.size(), 4);
|
||||
ASSERT_EQ(testVector[0], 1000);
|
||||
ASSERT_EQ(testVector[1], 2000);
|
||||
ASSERT_EQ(testVector[2], 3000);
|
||||
ASSERT_EQ(testVector[3], 4000);
|
||||
|
||||
ASSERT_EQ(testVector.data()[0], 1000);
|
||||
ASSERT_EQ(testVector.data()[1], 2000);
|
||||
ASSERT_EQ(testVector.data()[2], 3000);
|
||||
ASSERT_EQ(testVector.data()[3], 4000);
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, PushBackAndErase) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
vector.push_back(0xbeef);
|
||||
vector.push_back(0xface);
|
||||
|
||||
vector.erase(1);
|
||||
ASSERT_EQ(vector[0], 0x1337);
|
||||
ASSERT_EQ(vector.data()[0], 0x1337);
|
||||
ASSERT_EQ(vector[1], 0xbeef);
|
||||
ASSERT_EQ(vector.data()[1], 0xbeef);
|
||||
ASSERT_EQ(vector[2], 0xface);
|
||||
ASSERT_EQ(vector.data()[2], 0xface);
|
||||
ASSERT_EQ(vector.size(), 3);
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, EraseDestructorCalled) {
|
||||
FixedSizeVector<Foo, 4> vector;
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
vector.push_back(Foo());
|
||||
vector[i].setValue(i);
|
||||
}
|
||||
|
||||
// last item before erase is '3'.
|
||||
vector.erase(1);
|
||||
EXPECT_EQ(0, destructor_count[0]);
|
||||
EXPECT_EQ(0, destructor_count[1]);
|
||||
EXPECT_EQ(0, destructor_count[2]);
|
||||
EXPECT_EQ(1, destructor_count[3]);
|
||||
|
||||
// last item before erase is still '3'.
|
||||
vector.erase(2);
|
||||
EXPECT_EQ(0, destructor_count[0]);
|
||||
EXPECT_EQ(0, destructor_count[1]);
|
||||
EXPECT_EQ(0, destructor_count[2]);
|
||||
EXPECT_EQ(2, destructor_count[3]);
|
||||
|
||||
// last item before erase is now '2'.
|
||||
vector.erase(0);
|
||||
EXPECT_EQ(0, destructor_count[0]);
|
||||
EXPECT_EQ(0, destructor_count[1]);
|
||||
EXPECT_EQ(1, destructor_count[2]);
|
||||
EXPECT_EQ(2, destructor_count[3]);
|
||||
}
|
||||
|
||||
TEST(FixedSizeVectorDeathTest, SwapWithInvalidIndex) {
|
||||
FixedSizeVector<int, 4> vector;
|
||||
vector.push_back(0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
EXPECT_DEATH(vector.swap(0, 2), "");
|
||||
}
|
||||
|
||||
TEST(FixedSizeVectorDeathTest, SwapWithInvalidIndices) {
|
||||
FixedSizeVector<int, 4> vector;
|
||||
vector.push_back(0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
EXPECT_DEATH(vector.swap(2, 3), "");
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, Swap) {
|
||||
FixedSizeVector<int, 4> vector;
|
||||
vector.push_back(0x1337);
|
||||
vector.push_back(0xcafe);
|
||||
|
||||
vector.swap(0, 1);
|
||||
EXPECT_EQ(vector[0], 0xcafe);
|
||||
EXPECT_EQ(vector[1], 0x1337);
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, ResizeLarger) {
|
||||
FixedSizeVector<int, 4> vector;
|
||||
vector.resize(4);
|
||||
EXPECT_EQ(vector.size(), 4);
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, ResizeSmaller) {
|
||||
destructor_count[0] = 0;
|
||||
|
||||
FixedSizeVector<Foo, 4> vector;
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
vector.push_back(Foo());
|
||||
vector[i].setValue(0);
|
||||
}
|
||||
|
||||
EXPECT_EQ(vector.size(), 3);
|
||||
EXPECT_EQ(destructor_count[0], 0);
|
||||
vector.resize(2);
|
||||
EXPECT_EQ(vector.size(), 2);
|
||||
EXPECT_EQ(destructor_count[0], 1);
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, Iterator) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
size_t index = 0;
|
||||
for (FixedSizeVector<int, 8>::iterator it = vector.begin();
|
||||
it != vector.end(); ++it) {
|
||||
EXPECT_EQ(vector[index++], *it);
|
||||
}
|
||||
|
||||
FixedSizeVector<int, 8>::iterator it = vector.begin() + vector.size() - 1;
|
||||
EXPECT_EQ(vector[vector.size() - 1], *it);
|
||||
|
||||
it = vector.begin() + vector.size();
|
||||
EXPECT_TRUE(it == vector.end());
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, ConstIterator) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
size_t index = 0;
|
||||
for (FixedSizeVector<int, 8>::const_iterator cit = vector.cbegin();
|
||||
cit != vector.cend(); ++cit) {
|
||||
EXPECT_EQ(vector[index++], *cit);
|
||||
}
|
||||
|
||||
FixedSizeVector<int, 8>::const_iterator cit =
|
||||
vector.cbegin() + vector.size() - 1;
|
||||
EXPECT_EQ(vector[vector.size() - 1], *cit);
|
||||
|
||||
cit = vector.cbegin() + vector.size();
|
||||
EXPECT_TRUE(cit == vector.cend());
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, IteratorAndPushBack) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
FixedSizeVector<int, 8>::iterator it_b = vector.begin();
|
||||
FixedSizeVector<int, 8>::iterator it_e = vector.end();
|
||||
|
||||
vector.push_back(3);
|
||||
|
||||
size_t index = 0;
|
||||
while (it_b != it_e) {
|
||||
EXPECT_EQ(vector[index++], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, IteratorAndEmplaceBack) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
FixedSizeVector<int, 8>::iterator it_b = vector.begin();
|
||||
FixedSizeVector<int, 8>::iterator it_e = vector.end();
|
||||
|
||||
vector.emplace_back(3);
|
||||
|
||||
size_t index = 0;
|
||||
while (it_b != it_e) {
|
||||
EXPECT_EQ(vector[index++], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, IteratorAndErase) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
|
||||
FixedSizeVector<int, 8>::iterator it_b = vector.begin();
|
||||
|
||||
vector.erase(2);
|
||||
|
||||
size_t index = 0;
|
||||
while (index < 2) {
|
||||
EXPECT_EQ(vector[index++], *it_b++);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, IteratorAndSwap) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
vector.push_back(3);
|
||||
|
||||
FixedSizeVector<int, 8>::iterator it_b = vector.begin();
|
||||
|
||||
vector.swap(1, 3);
|
||||
|
||||
size_t index = 0;
|
||||
while (index < 4) {
|
||||
if (index != 1 && index != 3) {
|
||||
EXPECT_EQ(vector[index], *it_b);
|
||||
}
|
||||
index++;
|
||||
it_b++;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FixedSizeVector, IteratorAndResize) {
|
||||
FixedSizeVector<int, 8> vector;
|
||||
vector.push_back(0);
|
||||
vector.push_back(1);
|
||||
vector.push_back(2);
|
||||
vector.push_back(3);
|
||||
|
||||
FixedSizeVector<int, 8>::iterator it_b = vector.begin();
|
||||
|
||||
vector.resize(2);
|
||||
|
||||
size_t index = 0;
|
||||
while (index < 2) {
|
||||
EXPECT_EQ(vector[index++], *it_b++);
|
||||
}
|
||||
}
|
114
android/system/chre/util/tests/heap_test.cc
Normal file
114
android/system/chre/util/tests/heap_test.cc
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "chre/util/heap.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
using chre::DynamicVector;
|
||||
using chre::FixedSizeVector;
|
||||
|
||||
TEST(HeapDeathTest, PushHeapWhenEmpty) {
|
||||
DynamicVector<int> v;
|
||||
std::less<int> comp;
|
||||
EXPECT_DEATH(chre::push_heap(v, comp), "");
|
||||
}
|
||||
|
||||
TEST(HeapDeathTest, PopHeapWhenEmpty) {
|
||||
DynamicVector<int> v;
|
||||
std::less<int> comp;
|
||||
EXPECT_DEATH(chre::pop_heap(v, comp), "");
|
||||
}
|
||||
|
||||
TEST(HeapTest, NestedPushPopHeap) {
|
||||
DynamicVector<int> v;
|
||||
std::less<int> comp;
|
||||
|
||||
// generate random test data
|
||||
const size_t MaxSize = 1000;
|
||||
std::array<int, MaxSize> array;
|
||||
std::array<int, MaxSize> array_sorted;
|
||||
std::srand(0xcafe);
|
||||
for (size_t i = 0; i < MaxSize; ++i) {
|
||||
array[i] = std::rand();
|
||||
array_sorted[i] = array[i];
|
||||
}
|
||||
|
||||
// make sure the popped data is in the right order of various array sizes.
|
||||
for (size_t s = 1; s < MaxSize + 1; ++s) {
|
||||
for (size_t i = 0; i < s; ++i) {
|
||||
v.push_back(array[i]);
|
||||
chre::push_heap(v, comp);
|
||||
}
|
||||
|
||||
std::sort(array_sorted.begin(), array_sorted.begin() + s, std::greater<int>());
|
||||
|
||||
for (size_t i = 0; i < s; ++i) {
|
||||
chre::pop_heap(v, comp);
|
||||
EXPECT_EQ(array_sorted[i], v[v.size() - 1]);
|
||||
v.erase(v.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HeapDeathTest, RemoveHeapWithInvalidIndex) {
|
||||
DynamicVector<int> v;
|
||||
std::less<int> comp;
|
||||
|
||||
v.push_back(0);
|
||||
chre::push_heap(v, comp);
|
||||
EXPECT_DEATH(chre::remove_heap(v, 1, comp), "");
|
||||
}
|
||||
|
||||
TEST(HeapTest, NestedRemoveHeap) {
|
||||
DynamicVector<int> v;
|
||||
std::less<int> comp;
|
||||
|
||||
// generate random test data
|
||||
const size_t MaxSize = 1000;
|
||||
std::array<int, MaxSize> array;
|
||||
std::array<int, MaxSize> array_sorted;
|
||||
std::srand(0xcafe);
|
||||
for (size_t i = 0; i < MaxSize; ++i) {
|
||||
array[i] = std::rand();
|
||||
array_sorted[i] = array[i];
|
||||
}
|
||||
|
||||
for (size_t s = 1; s < MaxSize + 1; ++s) {
|
||||
for (size_t i = 0; i < s; ++i) {
|
||||
v.push_back(array[i]);
|
||||
chre::push_heap(v, comp);
|
||||
}
|
||||
|
||||
std::sort(array_sorted.begin(), array_sorted.begin() + s, std::greater<int>());
|
||||
|
||||
// randomly remove one
|
||||
chre::remove_heap(v, std::rand() % s, comp);
|
||||
int data = v[v.size() - 1];
|
||||
v.erase(v.size() - 1);
|
||||
|
||||
for (size_t i = 0; i < s; ++i) {
|
||||
if (array_sorted[i] == data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
chre::pop_heap(v, comp);
|
||||
EXPECT_EQ(array_sorted[i], v[v.size() - 1]);
|
||||
v.erase(v.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HeapTest, FixedSizeVectorMinHeap) {
|
||||
FixedSizeVector<int, 16> v;
|
||||
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
v.push_back(i);
|
||||
chre::push_heap(v, std::greater<int>());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
chre::pop_heap(v, std::greater<int>());
|
||||
EXPECT_EQ(i, v[v.size() - 1]);
|
||||
v.erase(v.size() - 1);
|
||||
}
|
||||
}
|
53
android/system/chre/util/tests/lock_guard_test.cc
Normal file
53
android/system/chre/util/tests/lock_guard_test.cc
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/lock_guard.h"
|
||||
|
||||
using chre::LockGuard;
|
||||
|
||||
class MockMutex {
|
||||
public:
|
||||
MockMutex() : mLockCount(0) {}
|
||||
|
||||
void lock() {
|
||||
mLockCount++;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
mLockCount--;
|
||||
}
|
||||
|
||||
int getLockCount() {
|
||||
return mLockCount;
|
||||
}
|
||||
|
||||
private:
|
||||
int mLockCount;
|
||||
};
|
||||
|
||||
TEST(LockGuard, LockUnlock) {
|
||||
MockMutex mutex;
|
||||
EXPECT_EQ(mutex.getLockCount(), 0);
|
||||
|
||||
{
|
||||
LockGuard<MockMutex> lock(mutex);
|
||||
EXPECT_EQ(mutex.getLockCount(), 1);
|
||||
}
|
||||
|
||||
EXPECT_EQ(mutex.getLockCount(), 0);
|
||||
}
|
101
android/system/chre/util/tests/memory_pool_test.cc
Normal file
101
android/system/chre/util/tests/memory_pool_test.cc
Normal file
|
@ -0,0 +1,101 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/memory_pool.h"
|
||||
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
using chre::MemoryPool;
|
||||
|
||||
TEST(MemoryPool, ExhaustPool) {
|
||||
MemoryPool<int, 3> memoryPool;
|
||||
ASSERT_NE(memoryPool.allocate(), nullptr);
|
||||
ASSERT_NE(memoryPool.allocate(), nullptr);
|
||||
ASSERT_NE(memoryPool.allocate(), nullptr);
|
||||
ASSERT_EQ(memoryPool.allocate(), nullptr);
|
||||
}
|
||||
|
||||
TEST(MemoryPool, ExhaustPoolThenDeallocateOneAndAllocateOne) {
|
||||
MemoryPool<int, 3> memoryPool;
|
||||
|
||||
// Exhaust the pool.
|
||||
int *element1 = memoryPool.allocate();
|
||||
int *element2 = memoryPool.allocate();
|
||||
int *element3 = memoryPool.allocate();
|
||||
|
||||
// Perform some simple assignments. There is a chance we crash here if things
|
||||
// are not implemented correctly.
|
||||
*element1 = 0xcafe;
|
||||
*element2 = 0xbeef;
|
||||
*element3 = 0xface;
|
||||
|
||||
// Free one element and then allocate another.
|
||||
memoryPool.deallocate(element1);
|
||||
element1 = memoryPool.allocate();
|
||||
ASSERT_NE(element1, nullptr);
|
||||
|
||||
// Ensure that the pool remains exhausted.
|
||||
ASSERT_EQ(memoryPool.allocate(), nullptr);
|
||||
|
||||
// Perform another simple assignment. There is a hope that this can crash if
|
||||
// the pointer returned is very bad (like nullptr).
|
||||
*element1 = 0xfade;
|
||||
|
||||
// Verify that the values stored were not corrupted by the deallocate
|
||||
// allocate cycle.
|
||||
ASSERT_EQ(*element1, 0xfade);
|
||||
ASSERT_EQ(*element2, 0xbeef);
|
||||
ASSERT_EQ(*element3, 0xface);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pair an allocated pointer with the expected value that should be stored in
|
||||
* that location.
|
||||
*/
|
||||
struct AllocationExpectedValuePair {
|
||||
size_t *allocation;
|
||||
size_t expectedValue;
|
||||
};
|
||||
|
||||
TEST(MemoryPool, ExhaustPoolThenRandomDeallocate) {
|
||||
// The number of times to allocate and deallocate in random order.
|
||||
const size_t kStressTestCount = 64;
|
||||
|
||||
// Construct a memory pool and a vector to maintain a list of all allocations.
|
||||
const size_t kMemoryPoolSize = 64;
|
||||
MemoryPool<size_t, kMemoryPoolSize> memoryPool;
|
||||
std::vector<AllocationExpectedValuePair> allocations;
|
||||
|
||||
for (size_t i = 0; i < kStressTestCount; i++) {
|
||||
// Exhaust the memory pool.
|
||||
for (size_t j = 0; j < kMemoryPoolSize; j++) {
|
||||
AllocationExpectedValuePair allocation = {
|
||||
.allocation = memoryPool.allocate(),
|
||||
.expectedValue = j,
|
||||
};
|
||||
|
||||
*allocation.allocation = j;
|
||||
allocations.push_back(allocation);
|
||||
}
|
||||
|
||||
// Seed a random number generator with the loop iteration so that order is
|
||||
// preserved across test runs.
|
||||
std::mt19937 randomGenerator(i);
|
||||
|
||||
while (!allocations.empty()) {
|
||||
// Generate a number with a uniform distribution between zero and the number
|
||||
// of allocations remaining.
|
||||
std::uniform_int_distribution<> distribution(0, allocations.size() - 1);
|
||||
size_t deallocateIndex = distribution(randomGenerator);
|
||||
|
||||
// Verify the expected value and free the allocation.
|
||||
ASSERT_EQ(*allocations[deallocateIndex].allocation,
|
||||
allocations[deallocateIndex].expectedValue);
|
||||
memoryPool.deallocate(allocations[deallocateIndex].allocation);
|
||||
|
||||
// Remove the freed allocation from the allocation list.
|
||||
allocations.erase(allocations.begin() + deallocateIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
140
android/system/chre/util/tests/optional_test.cc
Normal file
140
android/system/chre/util/tests/optional_test.cc
Normal file
|
@ -0,0 +1,140 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/non_copyable.h"
|
||||
#include "chre/util/optional.h"
|
||||
|
||||
using chre::Optional;
|
||||
|
||||
TEST(Optional, NoValueByDefault) {
|
||||
Optional<int> myInt;
|
||||
EXPECT_FALSE(myInt.has_value());
|
||||
}
|
||||
|
||||
TEST(Optional, NonDefaultValueByDefault) {
|
||||
Optional<int> myInt(0x1337);
|
||||
EXPECT_TRUE(myInt.has_value());
|
||||
EXPECT_EQ(*myInt, 0x1337);
|
||||
}
|
||||
|
||||
TEST(Optional, NonDefaultMovedValueByDefault) {
|
||||
Optional<int> myInt(std::move(0x1337));
|
||||
EXPECT_TRUE(myInt.has_value());
|
||||
EXPECT_EQ(*myInt, 0x1337);
|
||||
}
|
||||
|
||||
TEST(Optional, CopyAssignAndRead) {
|
||||
Optional<int> myInt;
|
||||
EXPECT_FALSE(myInt.has_value());
|
||||
myInt = 0x1337;
|
||||
EXPECT_EQ(*myInt, 0x1337);
|
||||
EXPECT_TRUE(myInt.has_value());
|
||||
myInt.reset();
|
||||
EXPECT_FALSE(myInt.has_value());
|
||||
}
|
||||
|
||||
TEST(Optional, MoveAssignAndRead) {
|
||||
Optional<int> myInt;
|
||||
EXPECT_FALSE(myInt.has_value());
|
||||
myInt = std::move(0xcafe);
|
||||
EXPECT_TRUE(myInt.has_value());
|
||||
EXPECT_EQ(*myInt, 0xcafe);
|
||||
}
|
||||
|
||||
TEST(Optional, OptionalMoveAssignAndRead) {
|
||||
Optional<int> myInt(0x1337);
|
||||
Optional<int> myMovedInt;
|
||||
EXPECT_FALSE(myMovedInt.has_value());
|
||||
myMovedInt = std::move(myInt);
|
||||
EXPECT_TRUE(myInt.has_value());
|
||||
EXPECT_TRUE(myMovedInt.has_value());
|
||||
EXPECT_EQ(*myMovedInt, 0x1337);
|
||||
}
|
||||
|
||||
TEST(Optional, OptionalCopyAssignAndRead) {
|
||||
Optional<int> myInt(0x1337);
|
||||
Optional<int> myCopiedInt;
|
||||
EXPECT_FALSE(myCopiedInt.has_value());
|
||||
myCopiedInt = myInt;
|
||||
EXPECT_TRUE(myInt.has_value());
|
||||
EXPECT_TRUE(myCopiedInt.has_value());
|
||||
EXPECT_EQ(*myInt, 0x1337);
|
||||
EXPECT_EQ(*myCopiedInt, 0x1337);
|
||||
}
|
||||
|
||||
static constexpr int kInvalidValue = -1;
|
||||
|
||||
class MovableButNonCopyable : public chre::NonCopyable {
|
||||
public:
|
||||
MovableButNonCopyable() = default;
|
||||
MovableButNonCopyable(int value) : mValue(value) {}
|
||||
MovableButNonCopyable(MovableButNonCopyable&& other) {
|
||||
mValue = other.mValue;
|
||||
other.mValue = kInvalidValue;
|
||||
}
|
||||
|
||||
MovableButNonCopyable& operator=(MovableButNonCopyable&& other) {
|
||||
assert(mMagic == kConstructedMagic);
|
||||
mValue = other.mValue;
|
||||
other.mValue = kInvalidValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MovableButNonCopyable() {
|
||||
mMagic = kUninitializedMagic;
|
||||
mValue = kUninitializedMagic;
|
||||
}
|
||||
|
||||
int getValue() const {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int kConstructedMagic = 0xfeedc0fe;
|
||||
static constexpr int kUninitializedMagic = 0xdeadbeef;
|
||||
|
||||
int mMagic = kConstructedMagic;
|
||||
int mValue = kInvalidValue;
|
||||
};
|
||||
|
||||
TEST(Optional, UninitializedAssignment) {
|
||||
constexpr int kValue1 = 0xd00d;
|
||||
constexpr int kValue2 = 0xcafe;
|
||||
MovableButNonCopyable transferee1(kValue1);
|
||||
MovableButNonCopyable transferee2(kValue2);
|
||||
|
||||
Optional<MovableButNonCopyable> container;
|
||||
EXPECT_FALSE(container.has_value());
|
||||
|
||||
container = std::move(transferee1);
|
||||
EXPECT_TRUE(container.has_value());
|
||||
EXPECT_EQ(container->getValue(), kValue1);
|
||||
EXPECT_EQ(transferee1.getValue(), kInvalidValue);
|
||||
|
||||
container.reset();
|
||||
EXPECT_FALSE(container.has_value());
|
||||
|
||||
container = std::move(transferee2);
|
||||
EXPECT_TRUE(container.has_value());
|
||||
EXPECT_EQ(container->getValue(), kValue2);
|
||||
EXPECT_EQ(transferee2.getValue(), kInvalidValue);
|
||||
}
|
||||
|
||||
// TODO: should add some tests to cover the possible assignment outcomes between
|
||||
// two Optional instances (e.g. assign one w/o value to one w/value, etc)
|
258
android/system/chre/util/tests/priority_queue_test.cc
Normal file
258
android/system/chre/util/tests/priority_queue_test.cc
Normal file
|
@ -0,0 +1,258 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "chre/util/priority_queue.h"
|
||||
|
||||
using chre::PriorityQueue;
|
||||
|
||||
namespace {
|
||||
class DummyElement {
|
||||
public:
|
||||
DummyElement() {};
|
||||
DummyElement(int index, int value) {
|
||||
mValue = value;
|
||||
mIndex = index;
|
||||
};
|
||||
~DummyElement() {};
|
||||
void setValue(int value) {
|
||||
mValue = value;
|
||||
}
|
||||
int getValue() const {
|
||||
return mValue;
|
||||
}
|
||||
int getIndex() const {
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
int mIndex = -1;
|
||||
int mValue = -1;
|
||||
};
|
||||
|
||||
bool compareFunction(const DummyElement& left, const DummyElement& right) {
|
||||
return left.getValue() > right.getValue();
|
||||
};
|
||||
|
||||
class CompareClass {
|
||||
public:
|
||||
bool operator() (const DummyElement& left, const DummyElement& right) const {
|
||||
return left.getValue() > right.getValue();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(PriorityQueueTest, IsEmptyInitially) {
|
||||
PriorityQueue<int> q;
|
||||
EXPECT_TRUE(q.empty());
|
||||
EXPECT_EQ(0, q.size());
|
||||
EXPECT_EQ(0, q.capacity());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, SimplePushPop) {
|
||||
PriorityQueue<int> q;
|
||||
|
||||
EXPECT_TRUE(q.push(0));
|
||||
EXPECT_TRUE(q.push(2));
|
||||
EXPECT_TRUE(q.push(3));
|
||||
EXPECT_TRUE(q.push(1));
|
||||
q.pop();
|
||||
EXPECT_TRUE(q.push(4));
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, TestSize) {
|
||||
PriorityQueue<int> q;
|
||||
|
||||
q.push(1);
|
||||
EXPECT_EQ(1, q.size());
|
||||
q.push(2);
|
||||
EXPECT_EQ(2, q.size());
|
||||
q.pop();
|
||||
EXPECT_EQ(1, q.size());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, TestEmpty) {
|
||||
PriorityQueue<int> q;
|
||||
|
||||
q.push(1);
|
||||
EXPECT_FALSE(q.empty());
|
||||
q.push(2);
|
||||
EXPECT_FALSE(q.empty());
|
||||
q.pop();
|
||||
EXPECT_FALSE(q.empty());
|
||||
q.pop();
|
||||
EXPECT_TRUE(q.empty());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, TestCapacity) {
|
||||
PriorityQueue<int> q;
|
||||
|
||||
q.push(1);
|
||||
EXPECT_EQ(1, q.capacity());
|
||||
q.push(2);
|
||||
EXPECT_EQ(2, q.capacity());
|
||||
q.push(3);
|
||||
EXPECT_EQ(4, q.capacity());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, PopWhenEmpty) {
|
||||
PriorityQueue<int> q;
|
||||
q.pop();
|
||||
EXPECT_EQ(0, q.size());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueDeathTest, TopWhenEmpty) {
|
||||
PriorityQueue<int> q;
|
||||
EXPECT_DEATH(q.top(), "");
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, TestTop) {
|
||||
PriorityQueue<int> q;
|
||||
q.push(1);
|
||||
EXPECT_EQ(1, q.top());
|
||||
q.push(2);
|
||||
q.push(3);
|
||||
EXPECT_EQ(3, q.top());
|
||||
q.pop();
|
||||
EXPECT_EQ(2, q.top());
|
||||
q.pop();
|
||||
EXPECT_EQ(1, q.top());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueDeathTest, InvalidSubscript) {
|
||||
PriorityQueue<int> q;
|
||||
EXPECT_DEATH(q[0], "");
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, Subscript) {
|
||||
PriorityQueue<int> q;
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
EXPECT_EQ(2, q[0]);
|
||||
EXPECT_EQ(1, q[1]);
|
||||
|
||||
q.pop();
|
||||
EXPECT_EQ(1, q[0]);
|
||||
}
|
||||
|
||||
TEST(PriorityQueueDeathTest, RemoveWithInvalidIndex) {
|
||||
PriorityQueue<int> q;
|
||||
EXPECT_DEATH(q.remove(0), "");
|
||||
EXPECT_EQ(0, q.size());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, RemoveWithIndex) {
|
||||
PriorityQueue<int> q;
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
q.remove(0);
|
||||
EXPECT_EQ(1, q.top());
|
||||
EXPECT_EQ(1, q.size());
|
||||
|
||||
q.push(3);
|
||||
q.remove(1);
|
||||
EXPECT_EQ(3, q.top());
|
||||
EXPECT_EQ(1, q.size());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, CompareGreater) {
|
||||
PriorityQueue<int, std::greater<int>> q;
|
||||
|
||||
EXPECT_TRUE(q.push(0));
|
||||
EXPECT_TRUE(q.push(2));
|
||||
EXPECT_TRUE(q.push(3));
|
||||
EXPECT_TRUE(q.push(1));
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
EXPECT_EQ(i, q.top());
|
||||
q.pop();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, EmplaceCompareLambda) {
|
||||
auto cmp = [](const DummyElement& left, const DummyElement& right) {
|
||||
return left.getValue() > right.getValue();
|
||||
};
|
||||
PriorityQueue<DummyElement, decltype(cmp)> q(cmp);
|
||||
|
||||
EXPECT_TRUE(q.emplace(0, 0));
|
||||
EXPECT_TRUE(q.emplace(1, 2));
|
||||
EXPECT_TRUE(q.emplace(2, 1));
|
||||
EXPECT_EQ(3, q.size());
|
||||
|
||||
EXPECT_EQ(0, q.top().getValue());
|
||||
EXPECT_EQ(0, q.top().getIndex());
|
||||
|
||||
q.pop();
|
||||
EXPECT_EQ(1, q.top().getValue());
|
||||
EXPECT_EQ(2, q.top().getIndex());
|
||||
|
||||
q.pop();
|
||||
EXPECT_EQ(2, q.top().getValue());
|
||||
EXPECT_EQ(1, q.top().getIndex());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, EmplaceCompareFunction) {
|
||||
PriorityQueue<DummyElement,
|
||||
std::function<bool(const DummyElement&, const DummyElement&)>>
|
||||
q(compareFunction);
|
||||
|
||||
EXPECT_TRUE(q.emplace(0, 0));
|
||||
EXPECT_TRUE(q.emplace(1, 2));
|
||||
EXPECT_TRUE(q.emplace(2, 1));
|
||||
EXPECT_EQ(3, q.size());
|
||||
|
||||
EXPECT_EQ(0, q.top().getValue());
|
||||
EXPECT_EQ(0, q.top().getIndex());
|
||||
|
||||
q.pop();
|
||||
EXPECT_EQ(1, q.top().getValue());
|
||||
EXPECT_EQ(2, q.top().getIndex());
|
||||
|
||||
q.pop();
|
||||
EXPECT_EQ(2, q.top().getValue());
|
||||
EXPECT_EQ(1, q.top().getIndex());
|
||||
}
|
||||
|
||||
TEST(PriorityQueueTest, EmplaceCompareClass) {
|
||||
PriorityQueue<DummyElement, CompareClass> q;
|
||||
|
||||
EXPECT_TRUE(q.emplace(0, 0));
|
||||
EXPECT_TRUE(q.emplace(1, 2));
|
||||
EXPECT_TRUE(q.emplace(2, 1));
|
||||
EXPECT_EQ(3, q.size());
|
||||
|
||||
EXPECT_EQ(0, q.top().getValue());
|
||||
EXPECT_EQ(0, q.top().getIndex());
|
||||
|
||||
q.pop();
|
||||
EXPECT_EQ(1, q.top().getValue());
|
||||
EXPECT_EQ(2, q.top().getIndex());
|
||||
|
||||
q.pop();
|
||||
EXPECT_EQ(2, q.top().getValue());
|
||||
EXPECT_EQ(1, q.top().getIndex());
|
||||
}
|
||||
|
||||
TEST(PriorityQueuetest, Iterator) {
|
||||
PriorityQueue<int> q;
|
||||
q.push(0);
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
|
||||
PriorityQueue<int>::iterator it = q.begin();
|
||||
EXPECT_EQ(q[0], *it);
|
||||
|
||||
it += q.size();
|
||||
EXPECT_TRUE(it == q.end());
|
||||
}
|
||||
|
||||
TEST(PriorityQueuetest, ConstIterator) {
|
||||
PriorityQueue<int> q;
|
||||
q.push(0);
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
|
||||
PriorityQueue<int>::const_iterator cit = q.cbegin();
|
||||
EXPECT_EQ(q[0], *cit);
|
||||
|
||||
cit += q.size();
|
||||
EXPECT_TRUE(cit == q.cend());
|
||||
}
|
44
android/system/chre/util/tests/singleton_test.cc
Normal file
44
android/system/chre/util/tests/singleton_test.cc
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/singleton.h"
|
||||
|
||||
using chre::Singleton;
|
||||
|
||||
TEST(Singleton, Lifecycle) {
|
||||
EXPECT_FALSE(Singleton<int>::isInitialized());
|
||||
EXPECT_EQ(Singleton<int>::get(), nullptr);
|
||||
|
||||
Singleton<int>::init(0x1337);
|
||||
ASSERT_NE(Singleton<int>::get(), nullptr);
|
||||
EXPECT_TRUE(Singleton<int>::isInitialized());
|
||||
EXPECT_EQ(*Singleton<int>::get(), 0x1337);
|
||||
Singleton<int>::init(0xcafe);
|
||||
ASSERT_NE(Singleton<int>::get(), nullptr);
|
||||
EXPECT_TRUE(Singleton<int>::isInitialized());
|
||||
EXPECT_EQ(*Singleton<int>::get(), 0x1337);
|
||||
|
||||
Singleton<int>::deinit();
|
||||
EXPECT_EQ(Singleton<int>::get(), nullptr);
|
||||
EXPECT_FALSE(Singleton<int>::isInitialized());
|
||||
|
||||
Singleton<int>::init(0xface);
|
||||
ASSERT_NE(Singleton<int>::get(), nullptr);
|
||||
EXPECT_TRUE(Singleton<int>::isInitialized());
|
||||
EXPECT_EQ(*Singleton<int>::get(), 0xface);
|
||||
}
|
192
android/system/chre/util/tests/time_test.cc
Normal file
192
android/system/chre/util/tests/time_test.cc
Normal file
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/time.h"
|
||||
|
||||
using chre::Seconds;
|
||||
using chre::Milliseconds;
|
||||
using chre::Microseconds;
|
||||
using chre::Nanoseconds;
|
||||
using chre::kOneSecondInNanoseconds;
|
||||
using chre::kOneMillisecondInNanoseconds;
|
||||
using chre::kOneMicrosecondInNanoseconds;
|
||||
|
||||
// Tests for Time constants
|
||||
TEST(Time, CheckTimeConversionConstants) {
|
||||
EXPECT_EQ(kOneSecondInNanoseconds, 1e9);
|
||||
EXPECT_EQ(kOneMillisecondInNanoseconds, 1e6);
|
||||
EXPECT_EQ(kOneMicrosecondInNanoseconds, 1e3);
|
||||
}
|
||||
|
||||
// Tests for Seconds
|
||||
TEST(Time, ConvertSecToNanosec) {
|
||||
Seconds t(5);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 5 * kOneSecondInNanoseconds);
|
||||
}
|
||||
|
||||
TEST(Time, ConvertSecToNanosecOverflowIsUint64Max) {
|
||||
Seconds t(UINT64_MAX / kOneSecondInNanoseconds + 1);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), UINT64_MAX);
|
||||
}
|
||||
|
||||
// Tests for Milliseconds
|
||||
TEST(Time, DefaultMillisecIsZero) {
|
||||
Milliseconds t;
|
||||
EXPECT_EQ(t.getMilliseconds(), 0);
|
||||
}
|
||||
|
||||
TEST(Time, GetInitialMillisec) {
|
||||
Milliseconds t(5);
|
||||
EXPECT_EQ(t.getMilliseconds(), 5);
|
||||
}
|
||||
|
||||
TEST(Time, InitializeMillisecFromNanosec) {
|
||||
Nanoseconds tNano(5 * kOneMillisecondInNanoseconds);
|
||||
Milliseconds tMilli(tNano);
|
||||
EXPECT_EQ(tMilli.getMilliseconds(), 5);
|
||||
}
|
||||
|
||||
TEST(Time, ConvertMillisecToNanosec) {
|
||||
Milliseconds t(5);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 5 * kOneMillisecondInNanoseconds);
|
||||
}
|
||||
|
||||
TEST(Time, ConvertMillisecToNanosecOverflowIsUint64Max) {
|
||||
Milliseconds t(UINT64_MAX / kOneMillisecondInNanoseconds + 1);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), UINT64_MAX);
|
||||
}
|
||||
|
||||
TEST(Time, TestMillisecEquals) {
|
||||
Milliseconds t1(5), t2(5), t3(6);
|
||||
EXPECT_TRUE(t1 == t2);
|
||||
EXPECT_FALSE(t1 == t3);
|
||||
}
|
||||
|
||||
// Tests for Microseconds
|
||||
TEST(Time, GetInitialMicrosec) {
|
||||
Microseconds t(5);
|
||||
EXPECT_EQ(t.getMicroseconds(), 5);
|
||||
}
|
||||
|
||||
TEST(Time, InitializeMicrosecFromNanosec) {
|
||||
Nanoseconds tNano(5 * kOneMicrosecondInNanoseconds);
|
||||
Microseconds tMicro(tNano);
|
||||
EXPECT_EQ(tMicro.getMicroseconds(), 5);
|
||||
}
|
||||
|
||||
TEST(Time, ConvertMicrosecToNanosec) {
|
||||
Microseconds t(5);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 5 * kOneMicrosecondInNanoseconds);
|
||||
}
|
||||
|
||||
TEST(Time, ConvertMicrosecToNanosecOverflowIsUint64Max) {
|
||||
Milliseconds t(UINT64_MAX / kOneMicrosecondInNanoseconds + 1);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), UINT64_MAX);
|
||||
}
|
||||
|
||||
// Tests for Nanoseconds
|
||||
TEST(Time, DefaultNanosecIsZero) {
|
||||
Nanoseconds t;
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 0);
|
||||
}
|
||||
|
||||
TEST(Time, GetInitialNanosec) {
|
||||
Nanoseconds t(5);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 5);
|
||||
}
|
||||
|
||||
TEST(Time, InitializeNanosecFromSec) {
|
||||
Seconds tSec(5);
|
||||
Nanoseconds tNano(tSec);
|
||||
EXPECT_EQ(tNano.toRawNanoseconds(), 5 * kOneSecondInNanoseconds);
|
||||
}
|
||||
|
||||
TEST(Time, InitializeNanosecFromMillisec) {
|
||||
Milliseconds tMilli(5);
|
||||
Nanoseconds tNano(tMilli);
|
||||
EXPECT_EQ(tNano.toRawNanoseconds(), 5 * kOneMillisecondInNanoseconds);
|
||||
}
|
||||
|
||||
TEST(Time, InitializeNanosecFromMicrosec) {
|
||||
Microseconds tMicro(5);
|
||||
Nanoseconds tNano(tMicro);
|
||||
EXPECT_EQ(tNano.toRawNanoseconds(), 5 * kOneMicrosecondInNanoseconds);
|
||||
}
|
||||
|
||||
TEST(Time, NanosecEquals) {
|
||||
Nanoseconds t1(5), t2(5), t3(6);
|
||||
EXPECT_TRUE(t1 == t2);
|
||||
EXPECT_FALSE(t1 == t3);
|
||||
}
|
||||
|
||||
TEST(Time, NanosecNotEquals) {
|
||||
Nanoseconds t1(5), t2(5), t3(6);
|
||||
EXPECT_FALSE(t1 != t2);
|
||||
EXPECT_TRUE(t1 != t3);
|
||||
}
|
||||
|
||||
TEST(Time, AddSecToNanosec) {
|
||||
Nanoseconds t = Seconds(5) + Nanoseconds(6);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 5 * kOneSecondInNanoseconds + 6);
|
||||
}
|
||||
|
||||
TEST(Time, AddSecToNanosecOverflow) {
|
||||
Nanoseconds t = Seconds(5) + Nanoseconds(UINT64_MAX);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 5 * kOneSecondInNanoseconds - 1);
|
||||
}
|
||||
|
||||
TEST(Time, AddNanosecToNanosec) {
|
||||
Nanoseconds t = Nanoseconds(6) + Nanoseconds(5);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 11);
|
||||
}
|
||||
|
||||
TEST(Time, AddNanosecToNanosecOverflow) {
|
||||
Nanoseconds t = Nanoseconds(6) + Nanoseconds(UINT64_MAX);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 5);
|
||||
}
|
||||
|
||||
TEST(Time, SubtractNanosecFromNanosec) {
|
||||
Nanoseconds t = Nanoseconds(11) - Nanoseconds(5);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), 6);
|
||||
}
|
||||
|
||||
TEST(Time, SubtractNanosecFromNanosecOverflow) {
|
||||
Nanoseconds t = Nanoseconds(5) - Nanoseconds(11);
|
||||
EXPECT_EQ(t.toRawNanoseconds(), UINT64_MAX - 5);
|
||||
}
|
||||
|
||||
TEST(Time, NanosecGreaterThanEqual) {
|
||||
Nanoseconds t1(5), t2(5), t3(6);
|
||||
EXPECT_TRUE(t2 >= t1);
|
||||
EXPECT_TRUE(t3 >= t1);
|
||||
EXPECT_FALSE(t1 >= t3);
|
||||
}
|
||||
|
||||
TEST(Time, NanosecLessThan) {
|
||||
Nanoseconds t1(5), t2(5), t3(6);
|
||||
EXPECT_FALSE(t2 < t1);
|
||||
EXPECT_FALSE(t3 < t1);
|
||||
EXPECT_TRUE(t1 < t3);
|
||||
}
|
||||
|
||||
TEST(Time, NanosecGreaterThan) {
|
||||
Nanoseconds t1(5), t2(5), t3(6);
|
||||
EXPECT_FALSE(t2 > t1);
|
||||
EXPECT_TRUE(t3 > t1);
|
||||
EXPECT_FALSE(t1 > t3);
|
||||
}
|
105
android/system/chre/util/tests/unique_ptr_test.cc
Normal file
105
android/system/chre/util/tests/unique_ptr_test.cc
Normal file
|
@ -0,0 +1,105 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "chre/util/unique_ptr.h"
|
||||
|
||||
using chre::UniquePtr;
|
||||
using chre::MakeUnique;
|
||||
using chre::MakeUniqueZeroFill;
|
||||
|
||||
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);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue