upload android base code part6

This commit is contained in:
August 2018-08-08 17:48:24 +08:00
parent 421e214c7d
commit 4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions

View 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());
}

View 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);
}

View file

@ -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);
}

View 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());
}

View 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++);
}
}

View 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);
}
}

View 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);
}

View 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);
}
}
}

View 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)

View 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());
}

View 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);
}

View 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);
}

View 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);
}