mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-22 01:11:42 +00:00
[wpiutil] Vendor llvm and update to 13.0.0 (#4224)
This commit is contained in:
@@ -35,6 +35,9 @@ SOFTWARE.
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "unit-json.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using wpi::json;
|
||||
|
||||
#include <fstream>
|
||||
|
||||
@@ -35,6 +35,7 @@ SOFTWARE.
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
|
||||
@@ -38,6 +38,7 @@ SOFTWARE.
|
||||
using wpi::json;
|
||||
using wpi::JsonTest;
|
||||
|
||||
#include <cmath>
|
||||
#include <deque>
|
||||
//#include <forward_list>
|
||||
#include <list>
|
||||
|
||||
@@ -35,6 +35,9 @@ SOFTWARE.
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "unit-json.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using wpi::json;
|
||||
|
||||
class JsonElementObjectAccessTestBase {
|
||||
|
||||
@@ -37,6 +37,7 @@ SOFTWARE.
|
||||
#include "unit-json.h"
|
||||
using wpi::json;
|
||||
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
|
||||
TEST(MessagePackDiscardedTest, Case)
|
||||
|
||||
@@ -35,6 +35,9 @@ SOFTWARE.
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "unit-json.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using wpi::json;
|
||||
|
||||
TEST(JsonPointerTest, TypesCreate)
|
||||
|
||||
49
wpiutil/src/test/native/cpp/llvm/Chrono.cpp
Normal file
49
wpiutil/src/test/native/cpp/llvm/Chrono.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//===- llvm/unittest/Support/Chrono.cpp - Time utilities tests ------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/Chrono.h"
|
||||
#include "wpi/SmallVector.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace wpi;
|
||||
using namespace wpi::sys;
|
||||
using namespace std::chrono;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(Chrono, TimeTConversion) {
|
||||
EXPECT_EQ(time_t(0), toTimeT(toTimePoint(time_t(0))));
|
||||
EXPECT_EQ(time_t(1), toTimeT(toTimePoint(time_t(1))));
|
||||
EXPECT_EQ(time_t(47), toTimeT(toTimePoint(time_t(47))));
|
||||
|
||||
TimePoint<> TP;
|
||||
EXPECT_EQ(TP, toTimePoint(toTimeT(TP)));
|
||||
TP += seconds(1);
|
||||
EXPECT_EQ(TP, toTimePoint(toTimeT(TP)));
|
||||
TP += hours(47);
|
||||
EXPECT_EQ(TP, toTimePoint(toTimeT(TP)));
|
||||
}
|
||||
|
||||
// Test that toTimePoint and toTimeT can be called with a arguments with varying
|
||||
// precisions.
|
||||
TEST(Chrono, ImplicitConversions) {
|
||||
std::time_t TimeT = 47;
|
||||
TimePoint<seconds> Sec = toTimePoint(TimeT);
|
||||
TimePoint<milliseconds> Milli = toTimePoint(TimeT);
|
||||
TimePoint<microseconds> Micro = toTimePoint(TimeT);
|
||||
TimePoint<nanoseconds> Nano = toTimePoint(TimeT);
|
||||
EXPECT_EQ(Sec, Milli);
|
||||
EXPECT_EQ(Sec, Micro);
|
||||
EXPECT_EQ(Sec, Nano);
|
||||
EXPECT_EQ(TimeT, toTimeT(Sec));
|
||||
EXPECT_EQ(TimeT, toTimeT(Milli));
|
||||
EXPECT_EQ(TimeT, toTimeT(Micro));
|
||||
EXPECT_EQ(TimeT, toTimeT(Nano));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
1712
wpiutil/src/test/native/cpp/llvm/ConvertUTFTest.cpp
Normal file
1712
wpiutil/src/test/native/cpp/llvm/ConvertUTFTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
637
wpiutil/src/test/native/cpp/llvm/DenseMapTest.cpp
Normal file
637
wpiutil/src/test/native/cpp/llvm/DenseMapTest.cpp
Normal file
@@ -0,0 +1,637 @@
|
||||
//===- llvm/unittest/ADT/DenseMapMap.cpp - DenseMap unit tests --*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
#include "wpi/DenseMap.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t getTestKey(int i, uint32_t *) { return i; }
|
||||
uint32_t getTestValue(int i, uint32_t *) { return 42 + i; }
|
||||
|
||||
uint32_t *getTestKey(int i, uint32_t **) {
|
||||
static uint32_t dummy_arr1[8192];
|
||||
assert(i < 8192 && "Only support 8192 dummy keys.");
|
||||
return &dummy_arr1[i];
|
||||
}
|
||||
uint32_t *getTestValue(int i, uint32_t **) {
|
||||
static uint32_t dummy_arr1[8192];
|
||||
assert(i < 8192 && "Only support 8192 dummy keys.");
|
||||
return &dummy_arr1[i];
|
||||
}
|
||||
|
||||
/// A test class that tries to check that construction and destruction
|
||||
/// occur correctly.
|
||||
class CtorTester {
|
||||
static std::set<CtorTester *> Constructed;
|
||||
int Value;
|
||||
|
||||
public:
|
||||
explicit CtorTester(int Value = 0) : Value(Value) {
|
||||
EXPECT_TRUE(Constructed.insert(this).second);
|
||||
}
|
||||
CtorTester(uint32_t Value) : Value(Value) {
|
||||
EXPECT_TRUE(Constructed.insert(this).second);
|
||||
}
|
||||
CtorTester(const CtorTester &Arg) : Value(Arg.Value) {
|
||||
EXPECT_TRUE(Constructed.insert(this).second);
|
||||
}
|
||||
CtorTester &operator=(const CtorTester &) = default;
|
||||
~CtorTester() {
|
||||
EXPECT_EQ(1u, Constructed.erase(this));
|
||||
}
|
||||
operator uint32_t() const { return Value; }
|
||||
|
||||
int getValue() const { return Value; }
|
||||
bool operator==(const CtorTester &RHS) const { return Value == RHS.Value; }
|
||||
};
|
||||
|
||||
std::set<CtorTester *> CtorTester::Constructed;
|
||||
|
||||
struct CtorTesterMapInfo {
|
||||
static inline CtorTester getEmptyKey() { return CtorTester(-1); }
|
||||
static inline CtorTester getTombstoneKey() { return CtorTester(-2); }
|
||||
static unsigned getHashValue(const CtorTester &Val) {
|
||||
return Val.getValue() * 37u;
|
||||
}
|
||||
static bool isEqual(const CtorTester &LHS, const CtorTester &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
CtorTester getTestKey(int i, CtorTester *) { return CtorTester(i); }
|
||||
CtorTester getTestValue(int i, CtorTester *) { return CtorTester(42 + i); }
|
||||
|
||||
// Test fixture, with helper functions implemented by forwarding to global
|
||||
// function overloads selected by component types of the type parameter. This
|
||||
// allows all of the map implementations to be tested with shared
|
||||
// implementations of helper routines.
|
||||
template <typename T>
|
||||
class DenseMapTest : public ::testing::Test {
|
||||
protected:
|
||||
T Map;
|
||||
|
||||
static typename T::key_type *const dummy_key_ptr;
|
||||
static typename T::mapped_type *const dummy_value_ptr;
|
||||
|
||||
typename T::key_type getKey(int i = 0) {
|
||||
return getTestKey(i, dummy_key_ptr);
|
||||
}
|
||||
typename T::mapped_type getValue(int i = 0) {
|
||||
return getTestValue(i, dummy_value_ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
typename T::key_type *const DenseMapTest<T>::dummy_key_ptr = nullptr;
|
||||
template <typename T>
|
||||
typename T::mapped_type *const DenseMapTest<T>::dummy_value_ptr = nullptr;
|
||||
|
||||
// Register these types for testing.
|
||||
typedef ::testing::Types<DenseMap<uint32_t, uint32_t>,
|
||||
DenseMap<uint32_t *, uint32_t *>,
|
||||
DenseMap<CtorTester, CtorTester, CtorTesterMapInfo>,
|
||||
SmallDenseMap<uint32_t, uint32_t>,
|
||||
SmallDenseMap<uint32_t *, uint32_t *>,
|
||||
SmallDenseMap<CtorTester, CtorTester, 4,
|
||||
CtorTesterMapInfo>
|
||||
> DenseMapTestTypes;
|
||||
TYPED_TEST_SUITE(DenseMapTest, DenseMapTestTypes, );
|
||||
|
||||
// Empty map tests
|
||||
TYPED_TEST(DenseMapTest, EmptyIntMapTest) {
|
||||
// Size tests
|
||||
EXPECT_EQ(0u, this->Map.size());
|
||||
EXPECT_TRUE(this->Map.empty());
|
||||
|
||||
// Iterator tests
|
||||
EXPECT_TRUE(this->Map.begin() == this->Map.end());
|
||||
|
||||
// Lookup tests
|
||||
EXPECT_FALSE(this->Map.count(this->getKey()));
|
||||
EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end());
|
||||
EXPECT_EQ(typename TypeParam::mapped_type(),
|
||||
this->Map.lookup(this->getKey()));
|
||||
}
|
||||
|
||||
// Constant map tests
|
||||
TYPED_TEST(DenseMapTest, ConstEmptyMapTest) {
|
||||
const TypeParam &ConstMap = this->Map;
|
||||
EXPECT_EQ(0u, ConstMap.size());
|
||||
EXPECT_TRUE(ConstMap.empty());
|
||||
EXPECT_TRUE(ConstMap.begin() == ConstMap.end());
|
||||
}
|
||||
|
||||
// A map with a single entry
|
||||
TYPED_TEST(DenseMapTest, SingleEntryMapTest) {
|
||||
this->Map[this->getKey()] = this->getValue();
|
||||
|
||||
// Size tests
|
||||
EXPECT_EQ(1u, this->Map.size());
|
||||
EXPECT_FALSE(this->Map.begin() == this->Map.end());
|
||||
EXPECT_FALSE(this->Map.empty());
|
||||
|
||||
// Iterator tests
|
||||
typename TypeParam::iterator it = this->Map.begin();
|
||||
EXPECT_EQ(this->getKey(), it->first);
|
||||
EXPECT_EQ(this->getValue(), it->second);
|
||||
++it;
|
||||
EXPECT_TRUE(it == this->Map.end());
|
||||
|
||||
// Lookup tests
|
||||
EXPECT_TRUE(this->Map.count(this->getKey()));
|
||||
EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.begin());
|
||||
EXPECT_EQ(this->getValue(), this->Map.lookup(this->getKey()));
|
||||
EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
|
||||
}
|
||||
|
||||
// Test clear() method
|
||||
TYPED_TEST(DenseMapTest, ClearTest) {
|
||||
this->Map[this->getKey()] = this->getValue();
|
||||
this->Map.clear();
|
||||
|
||||
EXPECT_EQ(0u, this->Map.size());
|
||||
EXPECT_TRUE(this->Map.empty());
|
||||
EXPECT_TRUE(this->Map.begin() == this->Map.end());
|
||||
}
|
||||
|
||||
// Test erase(iterator) method
|
||||
TYPED_TEST(DenseMapTest, EraseTest) {
|
||||
this->Map[this->getKey()] = this->getValue();
|
||||
this->Map.erase(this->Map.begin());
|
||||
|
||||
EXPECT_EQ(0u, this->Map.size());
|
||||
EXPECT_TRUE(this->Map.empty());
|
||||
EXPECT_TRUE(this->Map.begin() == this->Map.end());
|
||||
}
|
||||
|
||||
// Test erase(value) method
|
||||
TYPED_TEST(DenseMapTest, EraseTest2) {
|
||||
this->Map[this->getKey()] = this->getValue();
|
||||
this->Map.erase(this->getKey());
|
||||
|
||||
EXPECT_EQ(0u, this->Map.size());
|
||||
EXPECT_TRUE(this->Map.empty());
|
||||
EXPECT_TRUE(this->Map.begin() == this->Map.end());
|
||||
}
|
||||
|
||||
// Test insert() method
|
||||
TYPED_TEST(DenseMapTest, InsertTest) {
|
||||
this->Map.insert(std::make_pair(this->getKey(), this->getValue()));
|
||||
EXPECT_EQ(1u, this->Map.size());
|
||||
EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
|
||||
}
|
||||
|
||||
// Test copy constructor method
|
||||
TYPED_TEST(DenseMapTest, CopyConstructorTest) {
|
||||
this->Map[this->getKey()] = this->getValue();
|
||||
TypeParam copyMap(this->Map);
|
||||
|
||||
EXPECT_EQ(1u, copyMap.size());
|
||||
EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
|
||||
}
|
||||
|
||||
// Test copy constructor method where SmallDenseMap isn't small.
|
||||
TYPED_TEST(DenseMapTest, CopyConstructorNotSmallTest) {
|
||||
for (int Key = 0; Key < 5; ++Key)
|
||||
this->Map[this->getKey(Key)] = this->getValue(Key);
|
||||
TypeParam copyMap(this->Map);
|
||||
|
||||
EXPECT_EQ(5u, copyMap.size());
|
||||
for (int Key = 0; Key < 5; ++Key)
|
||||
EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
|
||||
}
|
||||
|
||||
// Test copying from a default-constructed map.
|
||||
TYPED_TEST(DenseMapTest, CopyConstructorFromDefaultTest) {
|
||||
TypeParam copyMap(this->Map);
|
||||
|
||||
EXPECT_TRUE(copyMap.empty());
|
||||
}
|
||||
|
||||
// Test copying from an empty map where SmallDenseMap isn't small.
|
||||
TYPED_TEST(DenseMapTest, CopyConstructorFromEmptyTest) {
|
||||
for (int Key = 0; Key < 5; ++Key)
|
||||
this->Map[this->getKey(Key)] = this->getValue(Key);
|
||||
this->Map.clear();
|
||||
TypeParam copyMap(this->Map);
|
||||
|
||||
EXPECT_TRUE(copyMap.empty());
|
||||
}
|
||||
|
||||
// Test assignment operator method
|
||||
TYPED_TEST(DenseMapTest, AssignmentTest) {
|
||||
this->Map[this->getKey()] = this->getValue();
|
||||
TypeParam copyMap = this->Map;
|
||||
|
||||
EXPECT_EQ(1u, copyMap.size());
|
||||
EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
|
||||
|
||||
// test self-assignment.
|
||||
copyMap = static_cast<TypeParam &>(copyMap);
|
||||
EXPECT_EQ(1u, copyMap.size());
|
||||
EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
|
||||
}
|
||||
|
||||
TYPED_TEST(DenseMapTest, AssignmentTestNotSmall) {
|
||||
for (int Key = 0; Key < 5; ++Key)
|
||||
this->Map[this->getKey(Key)] = this->getValue(Key);
|
||||
TypeParam copyMap = this->Map;
|
||||
|
||||
EXPECT_EQ(5u, copyMap.size());
|
||||
for (int Key = 0; Key < 5; ++Key)
|
||||
EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
|
||||
|
||||
// test self-assignment.
|
||||
copyMap = static_cast<TypeParam &>(copyMap);
|
||||
EXPECT_EQ(5u, copyMap.size());
|
||||
for (int Key = 0; Key < 5; ++Key)
|
||||
EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
|
||||
}
|
||||
|
||||
// Test swap method
|
||||
TYPED_TEST(DenseMapTest, SwapTest) {
|
||||
this->Map[this->getKey()] = this->getValue();
|
||||
TypeParam otherMap;
|
||||
|
||||
this->Map.swap(otherMap);
|
||||
EXPECT_EQ(0u, this->Map.size());
|
||||
EXPECT_TRUE(this->Map.empty());
|
||||
EXPECT_EQ(1u, otherMap.size());
|
||||
EXPECT_EQ(this->getValue(), otherMap[this->getKey()]);
|
||||
|
||||
this->Map.swap(otherMap);
|
||||
EXPECT_EQ(0u, otherMap.size());
|
||||
EXPECT_TRUE(otherMap.empty());
|
||||
EXPECT_EQ(1u, this->Map.size());
|
||||
EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
|
||||
|
||||
// Make this more interesting by inserting 100 numbers into the map.
|
||||
for (int i = 0; i < 100; ++i)
|
||||
this->Map[this->getKey(i)] = this->getValue(i);
|
||||
|
||||
this->Map.swap(otherMap);
|
||||
EXPECT_EQ(0u, this->Map.size());
|
||||
EXPECT_TRUE(this->Map.empty());
|
||||
EXPECT_EQ(100u, otherMap.size());
|
||||
for (int i = 0; i < 100; ++i)
|
||||
EXPECT_EQ(this->getValue(i), otherMap[this->getKey(i)]);
|
||||
|
||||
this->Map.swap(otherMap);
|
||||
EXPECT_EQ(0u, otherMap.size());
|
||||
EXPECT_TRUE(otherMap.empty());
|
||||
EXPECT_EQ(100u, this->Map.size());
|
||||
for (int i = 0; i < 100; ++i)
|
||||
EXPECT_EQ(this->getValue(i), this->Map[this->getKey(i)]);
|
||||
}
|
||||
|
||||
// A more complex iteration test
|
||||
TYPED_TEST(DenseMapTest, IterationTest) {
|
||||
bool visited[100];
|
||||
std::map<typename TypeParam::key_type, unsigned> visitedIndex;
|
||||
|
||||
// Insert 100 numbers into the map
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
visited[i] = false;
|
||||
visitedIndex[this->getKey(i)] = i;
|
||||
|
||||
this->Map[this->getKey(i)] = this->getValue(i);
|
||||
}
|
||||
|
||||
// Iterate over all numbers and mark each one found.
|
||||
for (typename TypeParam::iterator it = this->Map.begin();
|
||||
it != this->Map.end(); ++it)
|
||||
visited[visitedIndex[it->first]] = true;
|
||||
|
||||
// Ensure every number was visited.
|
||||
for (int i = 0; i < 100; ++i)
|
||||
ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
|
||||
}
|
||||
|
||||
// const_iterator test
|
||||
TYPED_TEST(DenseMapTest, ConstIteratorTest) {
|
||||
// Check conversion from iterator to const_iterator.
|
||||
typename TypeParam::iterator it = this->Map.begin();
|
||||
typename TypeParam::const_iterator cit(it);
|
||||
EXPECT_TRUE(it == cit);
|
||||
|
||||
// Check copying of const_iterators.
|
||||
typename TypeParam::const_iterator cit2(cit);
|
||||
EXPECT_TRUE(cit == cit2);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Simple class that counts how many moves and copy happens when growing a map
|
||||
struct CountCopyAndMove {
|
||||
static int Move;
|
||||
static int Copy;
|
||||
CountCopyAndMove() {}
|
||||
|
||||
CountCopyAndMove(const CountCopyAndMove &) { Copy++; }
|
||||
CountCopyAndMove &operator=(const CountCopyAndMove &) {
|
||||
Copy++;
|
||||
return *this;
|
||||
}
|
||||
CountCopyAndMove(CountCopyAndMove &&) { Move++; }
|
||||
CountCopyAndMove &operator=(const CountCopyAndMove &&) {
|
||||
Move++;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
int CountCopyAndMove::Copy = 0;
|
||||
int CountCopyAndMove::Move = 0;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Test initializer list construction.
|
||||
TEST(DenseMapCustomTest, InitializerList) {
|
||||
DenseMap<int, int> M({{0, 0}, {0, 1}, {1, 2}});
|
||||
EXPECT_EQ(2u, M.size());
|
||||
EXPECT_EQ(1u, M.count(0));
|
||||
EXPECT_EQ(0, M[0]);
|
||||
EXPECT_EQ(1u, M.count(1));
|
||||
EXPECT_EQ(2, M[1]);
|
||||
}
|
||||
|
||||
// Test initializer list construction.
|
||||
TEST(DenseMapCustomTest, EqualityComparison) {
|
||||
DenseMap<int, int> M1({{0, 0}, {1, 2}});
|
||||
DenseMap<int, int> M2({{0, 0}, {1, 2}});
|
||||
DenseMap<int, int> M3({{0, 0}, {1, 3}});
|
||||
|
||||
EXPECT_EQ(M1, M2);
|
||||
EXPECT_NE(M1, M3);
|
||||
}
|
||||
|
||||
// Test for the default minimum size of a DenseMap
|
||||
TEST(DenseMapCustomTest, DefaultMinReservedSizeTest) {
|
||||
// IF THIS VALUE CHANGE, please update InitialSizeTest, InitFromIterator, and
|
||||
// ReserveTest as well!
|
||||
const int ExpectedInitialBucketCount = 64;
|
||||
// Formula from DenseMap::getMinBucketToReserveForEntries()
|
||||
const int ExpectedMaxInitialEntries = ExpectedInitialBucketCount * 3 / 4 - 1;
|
||||
|
||||
DenseMap<int, CountCopyAndMove> Map;
|
||||
// Will allocate 64 buckets
|
||||
Map.reserve(1);
|
||||
unsigned MemorySize = Map.getMemorySize();
|
||||
CountCopyAndMove::Copy = 0;
|
||||
CountCopyAndMove::Move = 0;
|
||||
for (int i = 0; i < ExpectedMaxInitialEntries; ++i)
|
||||
Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
|
||||
std::forward_as_tuple(i),
|
||||
std::forward_as_tuple()));
|
||||
// Check that we didn't grow
|
||||
EXPECT_EQ(MemorySize, Map.getMemorySize());
|
||||
// Check that move was called the expected number of times
|
||||
EXPECT_EQ(ExpectedMaxInitialEntries, CountCopyAndMove::Move);
|
||||
// Check that no copy occurred
|
||||
EXPECT_EQ(0, CountCopyAndMove::Copy);
|
||||
|
||||
// Adding one extra element should grow the map
|
||||
Map.insert(std::pair<int, CountCopyAndMove>(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(ExpectedMaxInitialEntries),
|
||||
std::forward_as_tuple()));
|
||||
// Check that we grew
|
||||
EXPECT_NE(MemorySize, Map.getMemorySize());
|
||||
// Check that move was called the expected number of times
|
||||
// This relies on move-construction elision, and cannot be reliably tested.
|
||||
// EXPECT_EQ(ExpectedMaxInitialEntries + 2, CountCopyAndMove::Move);
|
||||
// Check that no copy occurred
|
||||
EXPECT_EQ(0, CountCopyAndMove::Copy);
|
||||
}
|
||||
|
||||
// Make sure creating the map with an initial size of N actually gives us enough
|
||||
// buckets to insert N items without increasing allocation size.
|
||||
TEST(DenseMapCustomTest, InitialSizeTest) {
|
||||
// Test a few different sizes, 48 is *not* a random choice: we need a value
|
||||
// that is 2/3 of a power of two to stress the grow() condition, and the power
|
||||
// of two has to be at least 64 because of minimum size allocation in the
|
||||
// DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
|
||||
// 64 default init.
|
||||
for (auto Size : {1, 2, 48, 66}) {
|
||||
DenseMap<int, CountCopyAndMove> Map(Size);
|
||||
unsigned MemorySize = Map.getMemorySize();
|
||||
CountCopyAndMove::Copy = 0;
|
||||
CountCopyAndMove::Move = 0;
|
||||
for (int i = 0; i < Size; ++i)
|
||||
Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
|
||||
std::forward_as_tuple(i),
|
||||
std::forward_as_tuple()));
|
||||
// Check that we didn't grow
|
||||
EXPECT_EQ(MemorySize, Map.getMemorySize());
|
||||
// Check that move was called the expected number of times
|
||||
EXPECT_EQ(Size, CountCopyAndMove::Move);
|
||||
// Check that no copy occurred
|
||||
EXPECT_EQ(0, CountCopyAndMove::Copy);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure creating the map with a iterator range does not trigger grow()
|
||||
TEST(DenseMapCustomTest, InitFromIterator) {
|
||||
std::vector<std::pair<int, CountCopyAndMove>> Values;
|
||||
// The size is a random value greater than 64 (hardcoded DenseMap min init)
|
||||
const int Count = 65;
|
||||
for (int i = 0; i < Count; i++)
|
||||
Values.emplace_back(i, CountCopyAndMove());
|
||||
|
||||
CountCopyAndMove::Move = 0;
|
||||
CountCopyAndMove::Copy = 0;
|
||||
DenseMap<int, CountCopyAndMove> Map(Values.begin(), Values.end());
|
||||
// Check that no move occurred
|
||||
EXPECT_EQ(0, CountCopyAndMove::Move);
|
||||
// Check that copy was called the expected number of times
|
||||
EXPECT_EQ(Count, CountCopyAndMove::Copy);
|
||||
}
|
||||
|
||||
// Make sure reserve actually gives us enough buckets to insert N items
|
||||
// without increasing allocation size.
|
||||
TEST(DenseMapCustomTest, ReserveTest) {
|
||||
// Test a few different size, 48 is *not* a random choice: we need a value
|
||||
// that is 2/3 of a power of two to stress the grow() condition, and the power
|
||||
// of two has to be at least 64 because of minimum size allocation in the
|
||||
// DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
|
||||
// 64 default init.
|
||||
for (auto Size : {1, 2, 48, 66}) {
|
||||
DenseMap<int, CountCopyAndMove> Map;
|
||||
Map.reserve(Size);
|
||||
unsigned MemorySize = Map.getMemorySize();
|
||||
CountCopyAndMove::Copy = 0;
|
||||
CountCopyAndMove::Move = 0;
|
||||
for (int i = 0; i < Size; ++i)
|
||||
Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
|
||||
std::forward_as_tuple(i),
|
||||
std::forward_as_tuple()));
|
||||
// Check that we didn't grow
|
||||
EXPECT_EQ(MemorySize, Map.getMemorySize());
|
||||
// Check that move was called the expected number of times
|
||||
EXPECT_EQ(Size, CountCopyAndMove::Move);
|
||||
// Check that no copy occurred
|
||||
EXPECT_EQ(0, CountCopyAndMove::Copy);
|
||||
}
|
||||
}
|
||||
|
||||
// Key traits that allows lookup with either an unsigned or char* key;
|
||||
// In the latter case, "a" == 0, "b" == 1 and so on.
|
||||
struct TestDenseMapInfo {
|
||||
static inline unsigned getEmptyKey() { return ~0; }
|
||||
static inline unsigned getTombstoneKey() { return ~0U - 1; }
|
||||
static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
|
||||
static unsigned getHashValue(const char* Val) {
|
||||
return (unsigned)(Val[0] - 'a') * 37U;
|
||||
}
|
||||
static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
static bool isEqual(const char* LHS, const unsigned& RHS) {
|
||||
return (unsigned)(LHS[0] - 'a') == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
// find_as() tests
|
||||
TEST(DenseMapCustomTest, FindAsTest) {
|
||||
DenseMap<unsigned, unsigned, TestDenseMapInfo> map;
|
||||
map[0] = 1;
|
||||
map[1] = 2;
|
||||
map[2] = 3;
|
||||
|
||||
// Size tests
|
||||
EXPECT_EQ(3u, map.size());
|
||||
|
||||
// Normal lookup tests
|
||||
EXPECT_EQ(1u, map.count(1));
|
||||
EXPECT_EQ(1u, map.find(0)->second);
|
||||
EXPECT_EQ(2u, map.find(1)->second);
|
||||
EXPECT_EQ(3u, map.find(2)->second);
|
||||
EXPECT_TRUE(map.find(3) == map.end());
|
||||
|
||||
// find_as() tests
|
||||
EXPECT_EQ(1u, map.find_as("a")->second);
|
||||
EXPECT_EQ(2u, map.find_as("b")->second);
|
||||
EXPECT_EQ(3u, map.find_as("c")->second);
|
||||
EXPECT_TRUE(map.find_as("d") == map.end());
|
||||
}
|
||||
|
||||
TEST(DenseMapCustomTest, SmallDenseMapInitializerList) {
|
||||
SmallDenseMap<int, int> M = {{0, 0}, {0, 1}, {1, 2}};
|
||||
EXPECT_EQ(2u, M.size());
|
||||
EXPECT_EQ(1u, M.count(0));
|
||||
EXPECT_EQ(0, M[0]);
|
||||
EXPECT_EQ(1u, M.count(1));
|
||||
EXPECT_EQ(2, M[1]);
|
||||
}
|
||||
|
||||
struct ContiguousDenseMapInfo {
|
||||
static inline unsigned getEmptyKey() { return ~0; }
|
||||
static inline unsigned getTombstoneKey() { return ~0U - 1; }
|
||||
static unsigned getHashValue(const unsigned& Val) { return Val; }
|
||||
static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
// Test that filling a small dense map with exactly the number of elements in
|
||||
// the map grows to have enough space for an empty bucket.
|
||||
TEST(DenseMapCustomTest, SmallDenseMapGrowTest) {
|
||||
SmallDenseMap<unsigned, unsigned, 32, ContiguousDenseMapInfo> map;
|
||||
// Add some number of elements, then delete a few to leave us some tombstones.
|
||||
// If we just filled the map with 32 elements we'd grow because of not enough
|
||||
// tombstones which masks the issue here.
|
||||
for (unsigned i = 0; i < 20; ++i)
|
||||
map[i] = i + 1;
|
||||
for (unsigned i = 0; i < 10; ++i)
|
||||
map.erase(i);
|
||||
for (unsigned i = 20; i < 32; ++i)
|
||||
map[i] = i + 1;
|
||||
|
||||
// Size tests
|
||||
EXPECT_EQ(22u, map.size());
|
||||
|
||||
// Try to find an element which doesn't exist. There was a bug in
|
||||
// SmallDenseMap which led to a map with num elements == small capacity not
|
||||
// having an empty bucket any more. Finding an element not in the map would
|
||||
// therefore never terminate.
|
||||
EXPECT_TRUE(map.find(32) == map.end());
|
||||
}
|
||||
|
||||
TEST(DenseMapCustomTest, LargeSmallDenseMapCompaction) {
|
||||
SmallDenseMap<unsigned, unsigned, 128, ContiguousDenseMapInfo> map;
|
||||
// Fill to < 3/4 load.
|
||||
for (unsigned i = 0; i < 95; ++i)
|
||||
map[i] = i;
|
||||
// And erase, leaving behind tombstones.
|
||||
for (unsigned i = 0; i < 95; ++i)
|
||||
map.erase(i);
|
||||
// Fill further, so that less than 1/8 are empty, but still below 3/4 load.
|
||||
for (unsigned i = 95; i < 128; ++i)
|
||||
map[i] = i;
|
||||
|
||||
EXPECT_EQ(33u, map.size());
|
||||
// Similar to the previous test, check for a non-existing element, as an
|
||||
// indirect check that tombstones have been removed.
|
||||
EXPECT_TRUE(map.find(0) == map.end());
|
||||
}
|
||||
|
||||
TEST(DenseMapCustomTest, TryEmplaceTest) {
|
||||
DenseMap<int, std::unique_ptr<int>> Map;
|
||||
std::unique_ptr<int> P(new int(2));
|
||||
auto Try1 = Map.try_emplace(0, new int(1));
|
||||
EXPECT_TRUE(Try1.second);
|
||||
auto Try2 = Map.try_emplace(0, std::move(P));
|
||||
EXPECT_FALSE(Try2.second);
|
||||
EXPECT_EQ(Try1.first, Try2.first);
|
||||
EXPECT_NE(nullptr, P);
|
||||
}
|
||||
|
||||
TEST(DenseMapCustomTest, ConstTest) {
|
||||
// Test that const pointers work okay for count and find, even when the
|
||||
// underlying map is a non-const pointer.
|
||||
DenseMap<int *, int> Map;
|
||||
int A;
|
||||
int *B = &A;
|
||||
const int *C = &A;
|
||||
Map.insert({B, 0});
|
||||
EXPECT_EQ(Map.count(B), 1u);
|
||||
EXPECT_EQ(Map.count(C), 1u);
|
||||
EXPECT_NE(Map.find(B), Map.end());
|
||||
EXPECT_NE(Map.find(C), Map.end());
|
||||
}
|
||||
|
||||
struct IncompleteStruct;
|
||||
|
||||
TEST(DenseMapCustomTest, OpaquePointerKey) {
|
||||
// Test that we can use a pointer to an incomplete type as a DenseMap key.
|
||||
// This is an important build time optimization, since many classes have
|
||||
// DenseMap members.
|
||||
DenseMap<IncompleteStruct *, int> Map;
|
||||
int Keys[3] = {0, 0, 0};
|
||||
IncompleteStruct *K1 = reinterpret_cast<IncompleteStruct *>(&Keys[0]);
|
||||
IncompleteStruct *K2 = reinterpret_cast<IncompleteStruct *>(&Keys[1]);
|
||||
IncompleteStruct *K3 = reinterpret_cast<IncompleteStruct *>(&Keys[2]);
|
||||
Map.insert({K1, 1});
|
||||
Map.insert({K2, 2});
|
||||
Map.insert({K3, 3});
|
||||
EXPECT_EQ(Map.count(K1), 1u);
|
||||
EXPECT_EQ(Map[K1], 1);
|
||||
EXPECT_EQ(Map[K2], 2);
|
||||
EXPECT_EQ(Map[K3], 3);
|
||||
Map.clear();
|
||||
EXPECT_EQ(Map.find(K1), Map.end());
|
||||
EXPECT_EQ(Map.find(K2), Map.end());
|
||||
EXPECT_EQ(Map.find(K3), Map.end());
|
||||
}
|
||||
}
|
||||
211
wpiutil/src/test/native/cpp/llvm/EndianTest.cpp
Normal file
211
wpiutil/src/test/native/cpp/llvm/EndianTest.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
//===- unittests/Support/EndianTest.cpp - Endian.h tests ------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/Endian.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
using namespace wpi;
|
||||
using namespace support;
|
||||
|
||||
#undef max
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(Endian, Read) {
|
||||
// These are 5 bytes so we can be sure at least one of the reads is unaligned.
|
||||
unsigned char bigval[] = {0x00, 0x01, 0x02, 0x03, 0x04};
|
||||
unsigned char littleval[] = {0x00, 0x04, 0x03, 0x02, 0x01};
|
||||
int32_t BigAsHost = 0x00010203;
|
||||
EXPECT_EQ(BigAsHost, (endian::read<int32_t, big, unaligned>(bigval)));
|
||||
int32_t LittleAsHost = 0x02030400;
|
||||
EXPECT_EQ(LittleAsHost,(endian::read<int32_t, little, unaligned>(littleval)));
|
||||
|
||||
EXPECT_EQ((endian::read<int32_t, big, unaligned>(bigval + 1)),
|
||||
(endian::read<int32_t, little, unaligned>(littleval + 1)));
|
||||
}
|
||||
|
||||
TEST(Endian, ReadBitAligned) {
|
||||
// Simple test to make sure we properly pull out the 0x0 word.
|
||||
unsigned char littleval[] = {0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff};
|
||||
unsigned char bigval[] = {0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0};
|
||||
EXPECT_EQ(
|
||||
(endian::readAtBitAlignment<int, little, unaligned>(&littleval[0], 6)),
|
||||
0x0);
|
||||
EXPECT_EQ((endian::readAtBitAlignment<int, big, unaligned>(&bigval[0], 6)),
|
||||
0x0);
|
||||
// Test to make sure that signed right shift of 0xf0000000 is masked
|
||||
// properly.
|
||||
unsigned char littleval2[] = {0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00};
|
||||
unsigned char bigval2[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
EXPECT_EQ(
|
||||
(endian::readAtBitAlignment<int, little, unaligned>(&littleval2[0], 4)),
|
||||
0x0f000000);
|
||||
EXPECT_EQ((endian::readAtBitAlignment<int, big, unaligned>(&bigval2[0], 4)),
|
||||
0x0f000000);
|
||||
// Test to make sure left shift of start bit doesn't overflow.
|
||||
EXPECT_EQ(
|
||||
(endian::readAtBitAlignment<int, little, unaligned>(&littleval2[0], 1)),
|
||||
0x78000000);
|
||||
EXPECT_EQ((endian::readAtBitAlignment<int, big, unaligned>(&bigval2[0], 1)),
|
||||
0x78000000);
|
||||
// Test to make sure 64-bit int doesn't overflow.
|
||||
unsigned char littleval3[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
unsigned char bigval3[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
EXPECT_EQ((endian::readAtBitAlignment<int64_t, little, unaligned>(
|
||||
&littleval3[0], 4)),
|
||||
0x0f00000000000000);
|
||||
EXPECT_EQ(
|
||||
(endian::readAtBitAlignment<int64_t, big, unaligned>(&bigval3[0], 4)),
|
||||
0x0f00000000000000);
|
||||
}
|
||||
|
||||
TEST(Endian, WriteBitAligned) {
|
||||
// This test ensures that signed right shift of 0xffffaa is masked
|
||||
// properly.
|
||||
unsigned char bigval[8] = {0x00};
|
||||
endian::writeAtBitAlignment<int32_t, big, unaligned>(bigval, (int)0xffffaaaa,
|
||||
4);
|
||||
EXPECT_EQ(bigval[0], 0xff);
|
||||
EXPECT_EQ(bigval[1], 0xfa);
|
||||
EXPECT_EQ(bigval[2], 0xaa);
|
||||
EXPECT_EQ(bigval[3], 0xa0);
|
||||
EXPECT_EQ(bigval[4], 0x00);
|
||||
EXPECT_EQ(bigval[5], 0x00);
|
||||
EXPECT_EQ(bigval[6], 0x00);
|
||||
EXPECT_EQ(bigval[7], 0x0f);
|
||||
|
||||
unsigned char littleval[8] = {0x00};
|
||||
endian::writeAtBitAlignment<int32_t, little, unaligned>(littleval,
|
||||
(int)0xffffaaaa, 4);
|
||||
EXPECT_EQ(littleval[0], 0xa0);
|
||||
EXPECT_EQ(littleval[1], 0xaa);
|
||||
EXPECT_EQ(littleval[2], 0xfa);
|
||||
EXPECT_EQ(littleval[3], 0xff);
|
||||
EXPECT_EQ(littleval[4], 0x0f);
|
||||
EXPECT_EQ(littleval[5], 0x00);
|
||||
EXPECT_EQ(littleval[6], 0x00);
|
||||
EXPECT_EQ(littleval[7], 0x00);
|
||||
|
||||
// This test makes sure 1<<31 doesn't overflow.
|
||||
// Test to make sure left shift of start bit doesn't overflow.
|
||||
unsigned char bigval2[8] = {0x00};
|
||||
endian::writeAtBitAlignment<int32_t, big, unaligned>(bigval2, (int)0xffffffff,
|
||||
1);
|
||||
EXPECT_EQ(bigval2[0], 0xff);
|
||||
EXPECT_EQ(bigval2[1], 0xff);
|
||||
EXPECT_EQ(bigval2[2], 0xff);
|
||||
EXPECT_EQ(bigval2[3], 0xfe);
|
||||
EXPECT_EQ(bigval2[4], 0x00);
|
||||
EXPECT_EQ(bigval2[5], 0x00);
|
||||
EXPECT_EQ(bigval2[6], 0x00);
|
||||
EXPECT_EQ(bigval2[7], 0x01);
|
||||
|
||||
unsigned char littleval2[8] = {0x00};
|
||||
endian::writeAtBitAlignment<int32_t, little, unaligned>(littleval2,
|
||||
(int)0xffffffff, 1);
|
||||
EXPECT_EQ(littleval2[0], 0xfe);
|
||||
EXPECT_EQ(littleval2[1], 0xff);
|
||||
EXPECT_EQ(littleval2[2], 0xff);
|
||||
EXPECT_EQ(littleval2[3], 0xff);
|
||||
EXPECT_EQ(littleval2[4], 0x01);
|
||||
EXPECT_EQ(littleval2[5], 0x00);
|
||||
EXPECT_EQ(littleval2[6], 0x00);
|
||||
EXPECT_EQ(littleval2[7], 0x00);
|
||||
|
||||
// Test to make sure 64-bit int doesn't overflow.
|
||||
unsigned char bigval64[16] = {0x00};
|
||||
endian::writeAtBitAlignment<int64_t, big, unaligned>(
|
||||
bigval64, (int64_t)0xffffffffffffffff, 1);
|
||||
EXPECT_EQ(bigval64[0], 0xff);
|
||||
EXPECT_EQ(bigval64[1], 0xff);
|
||||
EXPECT_EQ(bigval64[2], 0xff);
|
||||
EXPECT_EQ(bigval64[3], 0xff);
|
||||
EXPECT_EQ(bigval64[4], 0xff);
|
||||
EXPECT_EQ(bigval64[5], 0xff);
|
||||
EXPECT_EQ(bigval64[6], 0xff);
|
||||
EXPECT_EQ(bigval64[7], 0xfe);
|
||||
EXPECT_EQ(bigval64[8], 0x00);
|
||||
EXPECT_EQ(bigval64[9], 0x00);
|
||||
EXPECT_EQ(bigval64[10], 0x00);
|
||||
EXPECT_EQ(bigval64[11], 0x00);
|
||||
EXPECT_EQ(bigval64[12], 0x00);
|
||||
EXPECT_EQ(bigval64[13], 0x00);
|
||||
EXPECT_EQ(bigval64[14], 0x00);
|
||||
EXPECT_EQ(bigval64[15], 0x01);
|
||||
|
||||
unsigned char littleval64[16] = {0x00};
|
||||
endian::writeAtBitAlignment<int64_t, little, unaligned>(
|
||||
littleval64, (int64_t)0xffffffffffffffff, 1);
|
||||
EXPECT_EQ(littleval64[0], 0xfe);
|
||||
EXPECT_EQ(littleval64[1], 0xff);
|
||||
EXPECT_EQ(littleval64[2], 0xff);
|
||||
EXPECT_EQ(littleval64[3], 0xff);
|
||||
EXPECT_EQ(littleval64[4], 0xff);
|
||||
EXPECT_EQ(littleval64[5], 0xff);
|
||||
EXPECT_EQ(littleval64[6], 0xff);
|
||||
EXPECT_EQ(littleval64[7], 0xff);
|
||||
EXPECT_EQ(littleval64[8], 0x01);
|
||||
EXPECT_EQ(littleval64[9], 0x00);
|
||||
EXPECT_EQ(littleval64[10], 0x00);
|
||||
EXPECT_EQ(littleval64[11], 0x00);
|
||||
EXPECT_EQ(littleval64[12], 0x00);
|
||||
EXPECT_EQ(littleval64[13], 0x00);
|
||||
EXPECT_EQ(littleval64[14], 0x00);
|
||||
EXPECT_EQ(littleval64[15], 0x00);
|
||||
}
|
||||
|
||||
TEST(Endian, Write) {
|
||||
unsigned char data[5];
|
||||
endian::write<int32_t, big, unaligned>(data, -1362446643);
|
||||
EXPECT_EQ(data[0], 0xAE);
|
||||
EXPECT_EQ(data[1], 0xCA);
|
||||
EXPECT_EQ(data[2], 0xB6);
|
||||
EXPECT_EQ(data[3], 0xCD);
|
||||
endian::write<int32_t, big, unaligned>(data + 1, -1362446643);
|
||||
EXPECT_EQ(data[1], 0xAE);
|
||||
EXPECT_EQ(data[2], 0xCA);
|
||||
EXPECT_EQ(data[3], 0xB6);
|
||||
EXPECT_EQ(data[4], 0xCD);
|
||||
|
||||
endian::write<int32_t, little, unaligned>(data, -1362446643);
|
||||
EXPECT_EQ(data[0], 0xCD);
|
||||
EXPECT_EQ(data[1], 0xB6);
|
||||
EXPECT_EQ(data[2], 0xCA);
|
||||
EXPECT_EQ(data[3], 0xAE);
|
||||
endian::write<int32_t, little, unaligned>(data + 1, -1362446643);
|
||||
EXPECT_EQ(data[1], 0xCD);
|
||||
EXPECT_EQ(data[2], 0xB6);
|
||||
EXPECT_EQ(data[3], 0xCA);
|
||||
EXPECT_EQ(data[4], 0xAE);
|
||||
}
|
||||
|
||||
TEST(Endian, PackedEndianSpecificIntegral) {
|
||||
// These are 5 bytes so we can be sure at least one of the reads is unaligned.
|
||||
unsigned char big[] = {0x00, 0x01, 0x02, 0x03, 0x04};
|
||||
unsigned char little[] = {0x00, 0x04, 0x03, 0x02, 0x01};
|
||||
big32_t *big_val =
|
||||
reinterpret_cast<big32_t *>(big + 1);
|
||||
little32_t *little_val =
|
||||
reinterpret_cast<little32_t *>(little + 1);
|
||||
|
||||
EXPECT_EQ(*big_val, *little_val);
|
||||
}
|
||||
|
||||
TEST(Endian, PacketEndianSpecificIntegralAsEnum) {
|
||||
enum class Test : uint16_t { ONETWO = 0x0102, TWOONE = 0x0201 };
|
||||
unsigned char bytes[] = {0x01, 0x02};
|
||||
using LittleTest = little_t<Test>;
|
||||
using BigTest = big_t<Test>;
|
||||
EXPECT_EQ(Test::TWOONE, *reinterpret_cast<LittleTest *>(bytes));
|
||||
EXPECT_EQ(Test::ONETWO, *reinterpret_cast<BigTest *>(bytes));
|
||||
}
|
||||
|
||||
} // end anon namespace
|
||||
38
wpiutil/src/test/native/cpp/llvm/ErrnoTest.cpp
Normal file
38
wpiutil/src/test/native/cpp/llvm/ErrnoTest.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
//===- ErrnoTest.cpp - Error handling unit tests --------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/Errno.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace wpi::sys;
|
||||
|
||||
TEST(ErrnoTest, RetryAfterSignal) {
|
||||
EXPECT_EQ(1, RetryAfterSignal(-1, [] { return 1; }));
|
||||
|
||||
EXPECT_EQ(-1, RetryAfterSignal(-1, [] {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}));
|
||||
EXPECT_EQ(EAGAIN, errno);
|
||||
|
||||
unsigned calls = 0;
|
||||
EXPECT_EQ(1, RetryAfterSignal(-1, [&calls] {
|
||||
errno = EINTR;
|
||||
++calls;
|
||||
return calls == 1 ? -1 : 1;
|
||||
}));
|
||||
EXPECT_EQ(2u, calls);
|
||||
|
||||
EXPECT_EQ(1, RetryAfterSignal(-1, [](int x) { return x; }, 1));
|
||||
|
||||
std::unique_ptr<int> P(RetryAfterSignal(nullptr, [] { return new int(47); }));
|
||||
EXPECT_EQ(47, *P);
|
||||
|
||||
errno = EINTR;
|
||||
EXPECT_EQ(-1, RetryAfterSignal(-1, [] { return -1; }));
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
//===- FunctionExtrasTest.cpp - Unit tests for function type erasure ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -11,6 +10,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
@@ -225,4 +225,70 @@ TEST(UniqueFunctionTest, CountForwardingMoves) {
|
||||
UnmovableF(X);
|
||||
}
|
||||
|
||||
TEST(UniqueFunctionTest, Const) {
|
||||
// Can assign from const lambda.
|
||||
unique_function<int(int) const> Plus2 = [X(std::make_unique<int>(2))](int Y) {
|
||||
return *X + Y;
|
||||
};
|
||||
EXPECT_EQ(5, Plus2(3));
|
||||
|
||||
// Can call through a const ref.
|
||||
const auto &Plus2Ref = Plus2;
|
||||
EXPECT_EQ(5, Plus2Ref(3));
|
||||
|
||||
// Can move-construct and assign.
|
||||
unique_function<int(int) const> Plus2A = std::move(Plus2);
|
||||
EXPECT_EQ(5, Plus2A(3));
|
||||
unique_function<int(int) const> Plus2B;
|
||||
Plus2B = std::move(Plus2A);
|
||||
EXPECT_EQ(5, Plus2B(3));
|
||||
|
||||
// Can convert to non-const function type, but not back.
|
||||
unique_function<int(int)> Plus2C = std::move(Plus2B);
|
||||
EXPECT_EQ(5, Plus2C(3));
|
||||
|
||||
// Overloaded call operator correctly resolved.
|
||||
struct ChooseCorrectOverload {
|
||||
std::string_view operator()() { return "non-const"; }
|
||||
std::string_view operator()() const { return "const"; }
|
||||
};
|
||||
unique_function<std::string_view()> ChooseMutable = ChooseCorrectOverload();
|
||||
ChooseCorrectOverload A;
|
||||
EXPECT_EQ("non-const", ChooseMutable());
|
||||
EXPECT_EQ("non-const", A());
|
||||
unique_function<std::string_view() const> ChooseConst = ChooseCorrectOverload();
|
||||
const ChooseCorrectOverload &X = A;
|
||||
EXPECT_EQ("const", ChooseConst());
|
||||
EXPECT_EQ("const", X());
|
||||
}
|
||||
|
||||
// Test that overloads on unique_functions are resolved as expected.
|
||||
std::string returns(std::string_view) { return "not a function"; }
|
||||
std::string returns(unique_function<double()> F) { return "number"; }
|
||||
std::string returns(unique_function<std::string_view()> F) { return "string"; }
|
||||
|
||||
TEST(UniqueFunctionTest, SFINAE) {
|
||||
EXPECT_EQ("not a function", returns("boo!"));
|
||||
EXPECT_EQ("number", returns([] { return 42; }));
|
||||
EXPECT_EQ("string", returns([] { return "hello"; }));
|
||||
}
|
||||
|
||||
// A forward declared type, and a templated type.
|
||||
class Incomplete;
|
||||
template <typename T> class Templated { T A; };
|
||||
|
||||
// Check that we can define unique_function that have references to
|
||||
// incomplete types, even if those types are templated over an
|
||||
// incomplete type.
|
||||
TEST(UniqueFunctionTest, IncompleteTypes) {
|
||||
unique_function<void(Templated<Incomplete> &&)>
|
||||
IncompleteArgumentRValueReference;
|
||||
unique_function<void(Templated<Incomplete> &)>
|
||||
IncompleteArgumentLValueReference;
|
||||
unique_function<void(Templated<Incomplete> *)> IncompleteArgumentPointer;
|
||||
unique_function<Templated<Incomplete> &()> IncompleteResultLValueReference;
|
||||
unique_function<Templated<Incomplete> && ()> IncompleteResultRValueReference2;
|
||||
unique_function<Templated<Incomplete> *()> IncompleteResultPointer;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
430
wpiutil/src/test/native/cpp/llvm/MapVectorTest.cpp
Normal file
430
wpiutil/src/test/native/cpp/llvm/MapVectorTest.cpp
Normal file
@@ -0,0 +1,430 @@
|
||||
//===- unittest/ADT/MapVectorTest.cpp - MapVector unit tests ----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#if !defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "wpi/MapVector.h"
|
||||
#include "wpi/iterator_range.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <utility>
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
TEST(MapVectorTest, swap) {
|
||||
MapVector<int, int> MV1, MV2;
|
||||
std::pair<MapVector<int, int>::iterator, bool> R;
|
||||
|
||||
R = MV1.insert(std::make_pair(1, 2));
|
||||
ASSERT_EQ(R.first, MV1.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
EXPECT_FALSE(MV1.empty());
|
||||
EXPECT_TRUE(MV2.empty());
|
||||
MV2.swap(MV1);
|
||||
EXPECT_TRUE(MV1.empty());
|
||||
EXPECT_FALSE(MV2.empty());
|
||||
|
||||
auto I = MV1.find(1);
|
||||
ASSERT_EQ(MV1.end(), I);
|
||||
|
||||
I = MV2.find(1);
|
||||
ASSERT_EQ(I, MV2.begin());
|
||||
EXPECT_EQ(I->first, 1);
|
||||
EXPECT_EQ(I->second, 2);
|
||||
}
|
||||
|
||||
TEST(MapVectorTest, insert_pop) {
|
||||
MapVector<int, int> MV;
|
||||
std::pair<MapVector<int, int>::iterator, bool> R;
|
||||
|
||||
R = MV.insert(std::make_pair(1, 2));
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
R = MV.insert(std::make_pair(1, 3));
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_FALSE(R.second);
|
||||
|
||||
R = MV.insert(std::make_pair(4, 5));
|
||||
ASSERT_NE(R.first, MV.end());
|
||||
EXPECT_EQ(R.first->first, 4);
|
||||
EXPECT_EQ(R.first->second, 5);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
EXPECT_EQ(MV.size(), 2u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
EXPECT_EQ(MV[4], 5);
|
||||
|
||||
MV.pop_back();
|
||||
EXPECT_EQ(MV.size(), 1u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
|
||||
R = MV.insert(std::make_pair(4, 7));
|
||||
ASSERT_NE(R.first, MV.end());
|
||||
EXPECT_EQ(R.first->first, 4);
|
||||
EXPECT_EQ(R.first->second, 7);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
EXPECT_EQ(MV.size(), 2u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
EXPECT_EQ(MV[4], 7);
|
||||
}
|
||||
|
||||
TEST(MapVectorTest, erase) {
|
||||
MapVector<int, int> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 2));
|
||||
MV.insert(std::make_pair(3, 4));
|
||||
MV.insert(std::make_pair(5, 6));
|
||||
ASSERT_EQ(MV.size(), 3u);
|
||||
|
||||
MV.erase(MV.find(1));
|
||||
ASSERT_EQ(MV.size(), 2u);
|
||||
ASSERT_EQ(MV.find(1), MV.end());
|
||||
ASSERT_EQ(MV[3], 4);
|
||||
ASSERT_EQ(MV[5], 6);
|
||||
|
||||
ASSERT_EQ(MV.erase(3), 1u);
|
||||
ASSERT_EQ(MV.size(), 1u);
|
||||
ASSERT_EQ(MV.find(3), MV.end());
|
||||
ASSERT_EQ(MV[5], 6);
|
||||
|
||||
ASSERT_EQ(MV.erase(79), 0u);
|
||||
ASSERT_EQ(MV.size(), 1u);
|
||||
}
|
||||
|
||||
TEST(MapVectorTest, remove_if) {
|
||||
MapVector<int, int> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 11));
|
||||
MV.insert(std::make_pair(2, 12));
|
||||
MV.insert(std::make_pair(3, 13));
|
||||
MV.insert(std::make_pair(4, 14));
|
||||
MV.insert(std::make_pair(5, 15));
|
||||
MV.insert(std::make_pair(6, 16));
|
||||
ASSERT_EQ(MV.size(), 6u);
|
||||
|
||||
MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; });
|
||||
ASSERT_EQ(MV.size(), 3u);
|
||||
ASSERT_EQ(MV.find(1), MV.end());
|
||||
ASSERT_EQ(MV.find(3), MV.end());
|
||||
ASSERT_EQ(MV.find(5), MV.end());
|
||||
ASSERT_EQ(MV[2], 12);
|
||||
ASSERT_EQ(MV[4], 14);
|
||||
ASSERT_EQ(MV[6], 16);
|
||||
}
|
||||
|
||||
TEST(MapVectorTest, iteration_test) {
|
||||
MapVector<int, int> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 11));
|
||||
MV.insert(std::make_pair(2, 12));
|
||||
MV.insert(std::make_pair(3, 13));
|
||||
MV.insert(std::make_pair(4, 14));
|
||||
MV.insert(std::make_pair(5, 15));
|
||||
MV.insert(std::make_pair(6, 16));
|
||||
ASSERT_EQ(MV.size(), 6u);
|
||||
|
||||
int count = 1;
|
||||
for (auto P : make_range(MV.begin(), MV.end())) {
|
||||
ASSERT_EQ(P.first, count);
|
||||
count++;
|
||||
}
|
||||
|
||||
count = 6;
|
||||
for (auto P : make_range(MV.rbegin(), MV.rend())) {
|
||||
ASSERT_EQ(P.first, count);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MapVectorTest, NonCopyable) {
|
||||
MapVector<int, std::unique_ptr<int>> MV;
|
||||
MV.insert(std::make_pair(1, std::make_unique<int>(1)));
|
||||
MV.insert(std::make_pair(2, std::make_unique<int>(2)));
|
||||
|
||||
ASSERT_EQ(MV.count(1), 1u);
|
||||
ASSERT_EQ(*MV.find(2)->second, 2);
|
||||
}
|
||||
|
||||
template <class IntType> struct MapVectorMappedTypeTest : ::testing::Test {
|
||||
using int_type = IntType;
|
||||
};
|
||||
|
||||
using MapIntTypes = ::testing::Types<int, long, long long, unsigned,
|
||||
unsigned long, unsigned long long>;
|
||||
TYPED_TEST_SUITE(MapVectorMappedTypeTest, MapIntTypes, );
|
||||
|
||||
TYPED_TEST(MapVectorMappedTypeTest, DifferentDenseMap) {
|
||||
// Test that using a map with a mapped type other than 'unsigned' compiles
|
||||
// and works.
|
||||
using IntType = typename TestFixture::int_type;
|
||||
using MapVectorType = MapVector<int, int, DenseMap<int, IntType>>;
|
||||
|
||||
MapVectorType MV;
|
||||
std::pair<typename MapVectorType::iterator, bool> R;
|
||||
|
||||
R = MV.insert(std::make_pair(1, 2));
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
const std::pair<int, int> Elem(1, 3);
|
||||
R = MV.insert(Elem);
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_FALSE(R.second);
|
||||
|
||||
int& value = MV[4];
|
||||
EXPECT_EQ(value, 0);
|
||||
value = 5;
|
||||
|
||||
EXPECT_EQ(MV.size(), 2u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
EXPECT_EQ(MV[4], 5);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorSmallTest, insert_pop) {
|
||||
SmallMapVector<int, int, 32> MV;
|
||||
std::pair<SmallMapVector<int, int, 32>::iterator, bool> R;
|
||||
|
||||
R = MV.insert(std::make_pair(1, 2));
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
R = MV.insert(std::make_pair(1, 3));
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_FALSE(R.second);
|
||||
|
||||
R = MV.insert(std::make_pair(4, 5));
|
||||
ASSERT_NE(R.first, MV.end());
|
||||
EXPECT_EQ(R.first->first, 4);
|
||||
EXPECT_EQ(R.first->second, 5);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
EXPECT_EQ(MV.size(), 2u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
EXPECT_EQ(MV[4], 5);
|
||||
|
||||
MV.pop_back();
|
||||
EXPECT_EQ(MV.size(), 1u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
|
||||
R = MV.insert(std::make_pair(4, 7));
|
||||
ASSERT_NE(R.first, MV.end());
|
||||
EXPECT_EQ(R.first->first, 4);
|
||||
EXPECT_EQ(R.first->second, 7);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
EXPECT_EQ(MV.size(), 2u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
EXPECT_EQ(MV[4], 7);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorSmallTest, erase) {
|
||||
SmallMapVector<int, int, 32> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 2));
|
||||
MV.insert(std::make_pair(3, 4));
|
||||
MV.insert(std::make_pair(5, 6));
|
||||
ASSERT_EQ(MV.size(), 3u);
|
||||
|
||||
MV.erase(MV.find(1));
|
||||
ASSERT_EQ(MV.size(), 2u);
|
||||
ASSERT_EQ(MV.find(1), MV.end());
|
||||
ASSERT_EQ(MV[3], 4);
|
||||
ASSERT_EQ(MV[5], 6);
|
||||
|
||||
ASSERT_EQ(MV.erase(3), 1u);
|
||||
ASSERT_EQ(MV.size(), 1u);
|
||||
ASSERT_EQ(MV.find(3), MV.end());
|
||||
ASSERT_EQ(MV[5], 6);
|
||||
|
||||
ASSERT_EQ(MV.erase(79), 0u);
|
||||
ASSERT_EQ(MV.size(), 1u);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorSmallTest, remove_if) {
|
||||
SmallMapVector<int, int, 32> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 11));
|
||||
MV.insert(std::make_pair(2, 12));
|
||||
MV.insert(std::make_pair(3, 13));
|
||||
MV.insert(std::make_pair(4, 14));
|
||||
MV.insert(std::make_pair(5, 15));
|
||||
MV.insert(std::make_pair(6, 16));
|
||||
ASSERT_EQ(MV.size(), 6u);
|
||||
|
||||
MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; });
|
||||
ASSERT_EQ(MV.size(), 3u);
|
||||
ASSERT_EQ(MV.find(1), MV.end());
|
||||
ASSERT_EQ(MV.find(3), MV.end());
|
||||
ASSERT_EQ(MV.find(5), MV.end());
|
||||
ASSERT_EQ(MV[2], 12);
|
||||
ASSERT_EQ(MV[4], 14);
|
||||
ASSERT_EQ(MV[6], 16);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorSmallTest, iteration_test) {
|
||||
SmallMapVector<int, int, 32> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 11));
|
||||
MV.insert(std::make_pair(2, 12));
|
||||
MV.insert(std::make_pair(3, 13));
|
||||
MV.insert(std::make_pair(4, 14));
|
||||
MV.insert(std::make_pair(5, 15));
|
||||
MV.insert(std::make_pair(6, 16));
|
||||
ASSERT_EQ(MV.size(), 6u);
|
||||
|
||||
int count = 1;
|
||||
for (auto P : make_range(MV.begin(), MV.end())) {
|
||||
ASSERT_EQ(P.first, count);
|
||||
count++;
|
||||
}
|
||||
|
||||
count = 6;
|
||||
for (auto P : make_range(MV.rbegin(), MV.rend())) {
|
||||
ASSERT_EQ(P.first, count);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorSmallTest, NonCopyable) {
|
||||
SmallMapVector<int, std::unique_ptr<int>, 8> MV;
|
||||
MV.insert(std::make_pair(1, std::make_unique<int>(1)));
|
||||
MV.insert(std::make_pair(2, std::make_unique<int>(2)));
|
||||
|
||||
ASSERT_EQ(MV.count(1), 1u);
|
||||
ASSERT_EQ(*MV.find(2)->second, 2);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorLargeTest, insert_pop) {
|
||||
SmallMapVector<int, int, 1> MV;
|
||||
std::pair<SmallMapVector<int, int, 1>::iterator, bool> R;
|
||||
|
||||
R = MV.insert(std::make_pair(1, 2));
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
R = MV.insert(std::make_pair(1, 3));
|
||||
ASSERT_EQ(R.first, MV.begin());
|
||||
EXPECT_EQ(R.first->first, 1);
|
||||
EXPECT_EQ(R.first->second, 2);
|
||||
EXPECT_FALSE(R.second);
|
||||
|
||||
R = MV.insert(std::make_pair(4, 5));
|
||||
ASSERT_NE(R.first, MV.end());
|
||||
EXPECT_EQ(R.first->first, 4);
|
||||
EXPECT_EQ(R.first->second, 5);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
EXPECT_EQ(MV.size(), 2u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
EXPECT_EQ(MV[4], 5);
|
||||
|
||||
MV.pop_back();
|
||||
EXPECT_EQ(MV.size(), 1u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
|
||||
R = MV.insert(std::make_pair(4, 7));
|
||||
ASSERT_NE(R.first, MV.end());
|
||||
EXPECT_EQ(R.first->first, 4);
|
||||
EXPECT_EQ(R.first->second, 7);
|
||||
EXPECT_TRUE(R.second);
|
||||
|
||||
EXPECT_EQ(MV.size(), 2u);
|
||||
EXPECT_EQ(MV[1], 2);
|
||||
EXPECT_EQ(MV[4], 7);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorLargeTest, erase) {
|
||||
SmallMapVector<int, int, 1> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 2));
|
||||
MV.insert(std::make_pair(3, 4));
|
||||
MV.insert(std::make_pair(5, 6));
|
||||
ASSERT_EQ(MV.size(), 3u);
|
||||
|
||||
MV.erase(MV.find(1));
|
||||
ASSERT_EQ(MV.size(), 2u);
|
||||
ASSERT_EQ(MV.find(1), MV.end());
|
||||
ASSERT_EQ(MV[3], 4);
|
||||
ASSERT_EQ(MV[5], 6);
|
||||
|
||||
ASSERT_EQ(MV.erase(3), 1u);
|
||||
ASSERT_EQ(MV.size(), 1u);
|
||||
ASSERT_EQ(MV.find(3), MV.end());
|
||||
ASSERT_EQ(MV[5], 6);
|
||||
|
||||
ASSERT_EQ(MV.erase(79), 0u);
|
||||
ASSERT_EQ(MV.size(), 1u);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorLargeTest, remove_if) {
|
||||
SmallMapVector<int, int, 1> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 11));
|
||||
MV.insert(std::make_pair(2, 12));
|
||||
MV.insert(std::make_pair(3, 13));
|
||||
MV.insert(std::make_pair(4, 14));
|
||||
MV.insert(std::make_pair(5, 15));
|
||||
MV.insert(std::make_pair(6, 16));
|
||||
ASSERT_EQ(MV.size(), 6u);
|
||||
|
||||
MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; });
|
||||
ASSERT_EQ(MV.size(), 3u);
|
||||
ASSERT_EQ(MV.find(1), MV.end());
|
||||
ASSERT_EQ(MV.find(3), MV.end());
|
||||
ASSERT_EQ(MV.find(5), MV.end());
|
||||
ASSERT_EQ(MV[2], 12);
|
||||
ASSERT_EQ(MV[4], 14);
|
||||
ASSERT_EQ(MV[6], 16);
|
||||
}
|
||||
|
||||
TEST(SmallMapVectorLargeTest, iteration_test) {
|
||||
SmallMapVector<int, int, 1> MV;
|
||||
|
||||
MV.insert(std::make_pair(1, 11));
|
||||
MV.insert(std::make_pair(2, 12));
|
||||
MV.insert(std::make_pair(3, 13));
|
||||
MV.insert(std::make_pair(4, 14));
|
||||
MV.insert(std::make_pair(5, 15));
|
||||
MV.insert(std::make_pair(6, 16));
|
||||
ASSERT_EQ(MV.size(), 6u);
|
||||
|
||||
int count = 1;
|
||||
for (auto P : make_range(MV.begin(), MV.end())) {
|
||||
ASSERT_EQ(P.first, count);
|
||||
count++;
|
||||
}
|
||||
|
||||
count = 6;
|
||||
for (auto P : make_range(MV.rbegin(), MV.rend())) {
|
||||
ASSERT_EQ(P.first, count);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
607
wpiutil/src/test/native/cpp/llvm/MathExtrasTest.cpp
Normal file
607
wpiutil/src/test/native/cpp/llvm/MathExtrasTest.cpp
Normal file
@@ -0,0 +1,607 @@
|
||||
//===- unittests/Support/MathExtrasTest.cpp - math utils tests ------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/MathExtras.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(MathExtras, countTrailingZeros) {
|
||||
uint8_t Z8 = 0;
|
||||
uint16_t Z16 = 0;
|
||||
uint32_t Z32 = 0;
|
||||
uint64_t Z64 = 0;
|
||||
EXPECT_EQ(8u, countTrailingZeros(Z8));
|
||||
EXPECT_EQ(16u, countTrailingZeros(Z16));
|
||||
EXPECT_EQ(32u, countTrailingZeros(Z32));
|
||||
EXPECT_EQ(64u, countTrailingZeros(Z64));
|
||||
|
||||
uint8_t NZ8 = 42;
|
||||
uint16_t NZ16 = 42;
|
||||
uint32_t NZ32 = 42;
|
||||
uint64_t NZ64 = 42;
|
||||
EXPECT_EQ(1u, countTrailingZeros(NZ8));
|
||||
EXPECT_EQ(1u, countTrailingZeros(NZ16));
|
||||
EXPECT_EQ(1u, countTrailingZeros(NZ32));
|
||||
EXPECT_EQ(1u, countTrailingZeros(NZ64));
|
||||
}
|
||||
|
||||
TEST(MathExtras, countLeadingZeros) {
|
||||
uint8_t Z8 = 0;
|
||||
uint16_t Z16 = 0;
|
||||
uint32_t Z32 = 0;
|
||||
uint64_t Z64 = 0;
|
||||
EXPECT_EQ(8u, countLeadingZeros(Z8));
|
||||
EXPECT_EQ(16u, countLeadingZeros(Z16));
|
||||
EXPECT_EQ(32u, countLeadingZeros(Z32));
|
||||
EXPECT_EQ(64u, countLeadingZeros(Z64));
|
||||
|
||||
uint8_t NZ8 = 42;
|
||||
uint16_t NZ16 = 42;
|
||||
uint32_t NZ32 = 42;
|
||||
uint64_t NZ64 = 42;
|
||||
EXPECT_EQ(2u, countLeadingZeros(NZ8));
|
||||
EXPECT_EQ(10u, countLeadingZeros(NZ16));
|
||||
EXPECT_EQ(26u, countLeadingZeros(NZ32));
|
||||
EXPECT_EQ(58u, countLeadingZeros(NZ64));
|
||||
|
||||
EXPECT_EQ(8u, countLeadingZeros(0x00F000FFu));
|
||||
EXPECT_EQ(8u, countLeadingZeros(0x00F12345u));
|
||||
for (unsigned i = 0; i <= 30; ++i) {
|
||||
EXPECT_EQ(31 - i, countLeadingZeros(1u << i));
|
||||
}
|
||||
|
||||
EXPECT_EQ(8u, countLeadingZeros(0x00F1234500F12345ULL));
|
||||
EXPECT_EQ(1u, countLeadingZeros(1ULL << 62));
|
||||
for (unsigned i = 0; i <= 62; ++i) {
|
||||
EXPECT_EQ(63 - i, countLeadingZeros(1ULL << i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathExtras, onesMask) {
|
||||
EXPECT_EQ(0U, maskLeadingOnes<uint8_t>(0));
|
||||
EXPECT_EQ(0U, maskTrailingOnes<uint8_t>(0));
|
||||
EXPECT_EQ(0U, maskLeadingOnes<uint16_t>(0));
|
||||
EXPECT_EQ(0U, maskTrailingOnes<uint16_t>(0));
|
||||
EXPECT_EQ(0U, maskLeadingOnes<uint32_t>(0));
|
||||
EXPECT_EQ(0U, maskTrailingOnes<uint32_t>(0));
|
||||
EXPECT_EQ(0U, maskLeadingOnes<uint64_t>(0));
|
||||
EXPECT_EQ(0U, maskTrailingOnes<uint64_t>(0));
|
||||
|
||||
EXPECT_EQ(0x00000003U, maskTrailingOnes<uint32_t>(2U));
|
||||
EXPECT_EQ(0xC0000000U, maskLeadingOnes<uint32_t>(2U));
|
||||
|
||||
EXPECT_EQ(0x000007FFU, maskTrailingOnes<uint32_t>(11U));
|
||||
EXPECT_EQ(0xFFE00000U, maskLeadingOnes<uint32_t>(11U));
|
||||
|
||||
EXPECT_EQ(0xFFFFFFFFU, maskTrailingOnes<uint32_t>(32U));
|
||||
EXPECT_EQ(0xFFFFFFFFU, maskLeadingOnes<uint32_t>(32U));
|
||||
EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, maskTrailingOnes<uint64_t>(64U));
|
||||
EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, maskLeadingOnes<uint64_t>(64U));
|
||||
|
||||
EXPECT_EQ(0x0000FFFFFFFFFFFFULL, maskTrailingOnes<uint64_t>(48U));
|
||||
EXPECT_EQ(0xFFFFFFFFFFFF0000ULL, maskLeadingOnes<uint64_t>(48U));
|
||||
}
|
||||
|
||||
TEST(MathExtras, findFirstSet) {
|
||||
uint8_t Z8 = 0;
|
||||
uint16_t Z16 = 0;
|
||||
uint32_t Z32 = 0;
|
||||
uint64_t Z64 = 0;
|
||||
EXPECT_EQ(0xFFULL, findFirstSet(Z8));
|
||||
EXPECT_EQ(0xFFFFULL, findFirstSet(Z16));
|
||||
EXPECT_EQ(0xFFFFFFFFULL, findFirstSet(Z32));
|
||||
EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, findFirstSet(Z64));
|
||||
|
||||
uint8_t NZ8 = 42;
|
||||
uint16_t NZ16 = 42;
|
||||
uint32_t NZ32 = 42;
|
||||
uint64_t NZ64 = 42;
|
||||
EXPECT_EQ(1u, findFirstSet(NZ8));
|
||||
EXPECT_EQ(1u, findFirstSet(NZ16));
|
||||
EXPECT_EQ(1u, findFirstSet(NZ32));
|
||||
EXPECT_EQ(1u, findFirstSet(NZ64));
|
||||
}
|
||||
|
||||
TEST(MathExtras, findLastSet) {
|
||||
uint8_t Z8 = 0;
|
||||
uint16_t Z16 = 0;
|
||||
uint32_t Z32 = 0;
|
||||
uint64_t Z64 = 0;
|
||||
EXPECT_EQ(0xFFULL, findLastSet(Z8));
|
||||
EXPECT_EQ(0xFFFFULL, findLastSet(Z16));
|
||||
EXPECT_EQ(0xFFFFFFFFULL, findLastSet(Z32));
|
||||
EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, findLastSet(Z64));
|
||||
|
||||
uint8_t NZ8 = 42;
|
||||
uint16_t NZ16 = 42;
|
||||
uint32_t NZ32 = 42;
|
||||
uint64_t NZ64 = 42;
|
||||
EXPECT_EQ(5u, findLastSet(NZ8));
|
||||
EXPECT_EQ(5u, findLastSet(NZ16));
|
||||
EXPECT_EQ(5u, findLastSet(NZ32));
|
||||
EXPECT_EQ(5u, findLastSet(NZ64));
|
||||
}
|
||||
|
||||
TEST(MathExtras, isIntN) {
|
||||
EXPECT_TRUE(isIntN(16, 32767));
|
||||
EXPECT_FALSE(isIntN(16, 32768));
|
||||
}
|
||||
|
||||
TEST(MathExtras, isUIntN) {
|
||||
EXPECT_TRUE(isUIntN(16, 65535));
|
||||
EXPECT_FALSE(isUIntN(16, 65536));
|
||||
EXPECT_TRUE(isUIntN(1, 0));
|
||||
EXPECT_TRUE(isUIntN(6, 63));
|
||||
}
|
||||
|
||||
TEST(MathExtras, maxIntN) {
|
||||
EXPECT_EQ(32767, maxIntN(16));
|
||||
EXPECT_EQ(2147483647, maxIntN(32));
|
||||
EXPECT_EQ(std::numeric_limits<int32_t>::max(), maxIntN(32));
|
||||
EXPECT_EQ(std::numeric_limits<int64_t>::max(), maxIntN(64));
|
||||
}
|
||||
|
||||
TEST(MathExtras, minIntN) {
|
||||
EXPECT_EQ(-32768LL, minIntN(16));
|
||||
EXPECT_EQ(-64LL, minIntN(7));
|
||||
EXPECT_EQ(std::numeric_limits<int32_t>::min(), minIntN(32));
|
||||
EXPECT_EQ(std::numeric_limits<int64_t>::min(), minIntN(64));
|
||||
}
|
||||
|
||||
TEST(MathExtras, maxUIntN) {
|
||||
EXPECT_EQ(0xffffULL, maxUIntN(16));
|
||||
EXPECT_EQ(0xffffffffULL, maxUIntN(32));
|
||||
EXPECT_EQ(0xffffffffffffffffULL, maxUIntN(64));
|
||||
EXPECT_EQ(1ULL, maxUIntN(1));
|
||||
EXPECT_EQ(0x0fULL, maxUIntN(4));
|
||||
}
|
||||
|
||||
TEST(MathExtras, reverseBits) {
|
||||
uint8_t NZ8 = 42;
|
||||
uint16_t NZ16 = 42;
|
||||
uint32_t NZ32 = 42;
|
||||
uint64_t NZ64 = 42;
|
||||
EXPECT_EQ(0x54ULL, reverseBits(NZ8));
|
||||
EXPECT_EQ(0x5400ULL, reverseBits(NZ16));
|
||||
EXPECT_EQ(0x54000000ULL, reverseBits(NZ32));
|
||||
EXPECT_EQ(0x5400000000000000ULL, reverseBits(NZ64));
|
||||
}
|
||||
|
||||
TEST(MathExtras, isPowerOf2_32) {
|
||||
EXPECT_FALSE(isPowerOf2_32(0));
|
||||
EXPECT_TRUE(isPowerOf2_32(1 << 6));
|
||||
EXPECT_TRUE(isPowerOf2_32(1 << 12));
|
||||
EXPECT_FALSE(isPowerOf2_32((1 << 19) + 3));
|
||||
EXPECT_FALSE(isPowerOf2_32(0xABCDEF0));
|
||||
}
|
||||
|
||||
TEST(MathExtras, isPowerOf2_64) {
|
||||
EXPECT_FALSE(isPowerOf2_64(0));
|
||||
EXPECT_TRUE(isPowerOf2_64(1LL << 46));
|
||||
EXPECT_TRUE(isPowerOf2_64(1LL << 12));
|
||||
EXPECT_FALSE(isPowerOf2_64((1LL << 53) + 3));
|
||||
EXPECT_FALSE(isPowerOf2_64(0xABCDEF0ABCDEF0LL));
|
||||
}
|
||||
|
||||
TEST(MathExtras, PowerOf2Ceil) {
|
||||
EXPECT_EQ(0U, PowerOf2Ceil(0U));
|
||||
EXPECT_EQ(8U, PowerOf2Ceil(8U));
|
||||
EXPECT_EQ(8U, PowerOf2Ceil(7U));
|
||||
}
|
||||
|
||||
TEST(MathExtras, PowerOf2Floor) {
|
||||
EXPECT_EQ(0U, PowerOf2Floor(0U));
|
||||
EXPECT_EQ(8U, PowerOf2Floor(8U));
|
||||
EXPECT_EQ(4U, PowerOf2Floor(7U));
|
||||
}
|
||||
|
||||
TEST(MathExtras, CTLog2) {
|
||||
EXPECT_EQ(CTLog2<1ULL << 0>(), 0U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 1>(), 1U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 2>(), 2U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 3>(), 3U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 4>(), 4U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 5>(), 5U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 6>(), 6U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 7>(), 7U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 8>(), 8U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 9>(), 9U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 10>(), 10U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 11>(), 11U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 12>(), 12U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 13>(), 13U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 14>(), 14U);
|
||||
EXPECT_EQ(CTLog2<1ULL << 15>(), 15U);
|
||||
}
|
||||
|
||||
TEST(MathExtras, countLeadingOnes) {
|
||||
for (int i = 30; i >= 0; --i) {
|
||||
// Start with all ones and unset some bit.
|
||||
EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i)));
|
||||
}
|
||||
for (int i = 62; i >= 0; --i) {
|
||||
// Start with all ones and unset some bit.
|
||||
EXPECT_EQ(63u - i, countLeadingOnes(0xFFFFFFFFFFFFFFFFULL ^ (1LL << i)));
|
||||
}
|
||||
for (int i = 30; i >= 0; --i) {
|
||||
// Start with all ones and unset some bit.
|
||||
EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i)));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathExtras, FloatBits) {
|
||||
static const float kValue = 5632.34f;
|
||||
EXPECT_FLOAT_EQ(kValue, BitsToFloat(FloatToBits(kValue)));
|
||||
}
|
||||
|
||||
TEST(MathExtras, DoubleBits) {
|
||||
static const double kValue = 87987234.983498;
|
||||
EXPECT_DOUBLE_EQ(kValue, BitsToDouble(DoubleToBits(kValue)));
|
||||
}
|
||||
|
||||
TEST(MathExtras, MinAlign) {
|
||||
EXPECT_EQ(1u, MinAlign(2, 3));
|
||||
EXPECT_EQ(2u, MinAlign(2, 4));
|
||||
EXPECT_EQ(1u, MinAlign(17, 64));
|
||||
EXPECT_EQ(256u, MinAlign(256, 512));
|
||||
}
|
||||
|
||||
TEST(MathExtras, NextPowerOf2) {
|
||||
EXPECT_EQ(4u, NextPowerOf2(3));
|
||||
EXPECT_EQ(16u, NextPowerOf2(15));
|
||||
EXPECT_EQ(256u, NextPowerOf2(128));
|
||||
}
|
||||
|
||||
TEST(MathExtras, alignTo) {
|
||||
EXPECT_EQ(8u, alignTo(5, 8));
|
||||
EXPECT_EQ(24u, alignTo(17, 8));
|
||||
EXPECT_EQ(0u, alignTo(~0LL, 8));
|
||||
|
||||
EXPECT_EQ(7u, alignTo(5, 8, 7));
|
||||
EXPECT_EQ(17u, alignTo(17, 8, 1));
|
||||
EXPECT_EQ(3u, alignTo(~0LL, 8, 3));
|
||||
EXPECT_EQ(552u, alignTo(321, 255, 42));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SaturatingAddTestHelper()
|
||||
{
|
||||
const T Max = std::numeric_limits<T>::max();
|
||||
bool ResultOverflowed;
|
||||
|
||||
EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2)));
|
||||
EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingAdd(Max, T(1)));
|
||||
EXPECT_EQ(Max, SaturatingAdd(Max, T(1), &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1)));
|
||||
EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingAdd(T(1), Max));
|
||||
EXPECT_EQ(Max, SaturatingAdd(T(1), Max, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingAdd(Max, Max));
|
||||
EXPECT_EQ(Max, SaturatingAdd(Max, Max, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
}
|
||||
|
||||
TEST(MathExtras, SaturatingAdd) {
|
||||
SaturatingAddTestHelper<uint8_t>();
|
||||
SaturatingAddTestHelper<uint16_t>();
|
||||
SaturatingAddTestHelper<uint32_t>();
|
||||
SaturatingAddTestHelper<uint64_t>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SaturatingMultiplyTestHelper()
|
||||
{
|
||||
const T Max = std::numeric_limits<T>::max();
|
||||
bool ResultOverflowed;
|
||||
|
||||
// Test basic multiplication.
|
||||
EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3)));
|
||||
EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2)));
|
||||
EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
// Test multiplication by zero.
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0)));
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0)));
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1)));
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0)));
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max));
|
||||
EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max, &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
// Test multiplication by maximum value.
|
||||
EXPECT_EQ(Max, SaturatingMultiply(Max, T(2)));
|
||||
EXPECT_EQ(Max, SaturatingMultiply(Max, T(2), &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingMultiply(T(2), Max));
|
||||
EXPECT_EQ(Max, SaturatingMultiply(T(2), Max, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingMultiply(Max, Max));
|
||||
EXPECT_EQ(Max, SaturatingMultiply(Max, Max, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
// Test interesting boundary conditions for algorithm -
|
||||
// ((1 << A) - 1) * ((1 << B) + K) for K in [-1, 0, 1]
|
||||
// and A + B == std::numeric_limits<T>::digits.
|
||||
// We expect overflow iff A > B and K = 1.
|
||||
const int Digits = std::numeric_limits<T>::digits;
|
||||
for (int A = 1, B = Digits - 1; B >= 1; ++A, --B) {
|
||||
for (int K = -1; K <= 1; ++K) {
|
||||
T X = (T(1) << A) - T(1);
|
||||
T Y = (T(1) << B) + K;
|
||||
bool OverflowExpected = A > B && K == 1;
|
||||
|
||||
if(OverflowExpected) {
|
||||
EXPECT_EQ(Max, SaturatingMultiply(X, Y));
|
||||
EXPECT_EQ(Max, SaturatingMultiply(X, Y, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
} else {
|
||||
EXPECT_EQ(X * Y, SaturatingMultiply(X, Y));
|
||||
EXPECT_EQ(X * Y, SaturatingMultiply(X, Y, &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MathExtras, SaturatingMultiply) {
|
||||
SaturatingMultiplyTestHelper<uint8_t>();
|
||||
SaturatingMultiplyTestHelper<uint16_t>();
|
||||
SaturatingMultiplyTestHelper<uint32_t>();
|
||||
SaturatingMultiplyTestHelper<uint64_t>();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SaturatingMultiplyAddTestHelper()
|
||||
{
|
||||
const T Max = std::numeric_limits<T>::max();
|
||||
bool ResultOverflowed;
|
||||
|
||||
// Test basic multiply-add.
|
||||
EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10)));
|
||||
EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
// Test multiply overflows, add doesn't overflow
|
||||
EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(0), &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
// Test multiply doesn't overflow, add overflows
|
||||
EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
// Test multiply-add with Max as operand
|
||||
EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), Max, T(1), &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(1), &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, Max, &ResultOverflowed));
|
||||
EXPECT_TRUE(ResultOverflowed);
|
||||
|
||||
// Test multiply-add with 0 as operand
|
||||
EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(1), T(0), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(0), T(1), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(0), T(0), T(1), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
EXPECT_EQ(T(0), SaturatingMultiplyAdd(T(0), T(0), T(0), &ResultOverflowed));
|
||||
EXPECT_FALSE(ResultOverflowed);
|
||||
|
||||
}
|
||||
|
||||
TEST(MathExtras, SaturatingMultiplyAdd) {
|
||||
SaturatingMultiplyAddTestHelper<uint8_t>();
|
||||
SaturatingMultiplyAddTestHelper<uint16_t>();
|
||||
SaturatingMultiplyAddTestHelper<uint32_t>();
|
||||
SaturatingMultiplyAddTestHelper<uint64_t>();
|
||||
}
|
||||
|
||||
TEST(MathExtras, IsShiftedUInt) {
|
||||
EXPECT_TRUE((isShiftedUInt<1, 0>(0)));
|
||||
EXPECT_TRUE((isShiftedUInt<1, 0>(1)));
|
||||
EXPECT_FALSE((isShiftedUInt<1, 0>(2)));
|
||||
EXPECT_FALSE((isShiftedUInt<1, 0>(3)));
|
||||
EXPECT_FALSE((isShiftedUInt<1, 0>(0x8000000000000000)));
|
||||
EXPECT_TRUE((isShiftedUInt<1, 63>(0x8000000000000000)));
|
||||
EXPECT_TRUE((isShiftedUInt<2, 62>(0xC000000000000000)));
|
||||
EXPECT_FALSE((isShiftedUInt<2, 62>(0xE000000000000000)));
|
||||
|
||||
// 0x201 is ten bits long and has a 1 in the MSB and LSB.
|
||||
EXPECT_TRUE((isShiftedUInt<10, 5>(uint64_t(0x201) << 5)));
|
||||
EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 4)));
|
||||
EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 6)));
|
||||
}
|
||||
|
||||
TEST(MathExtras, IsShiftedInt) {
|
||||
EXPECT_TRUE((isShiftedInt<1, 0>(0)));
|
||||
EXPECT_TRUE((isShiftedInt<1, 0>(-1)));
|
||||
EXPECT_FALSE((isShiftedInt<1, 0>(2)));
|
||||
EXPECT_FALSE((isShiftedInt<1, 0>(3)));
|
||||
EXPECT_FALSE((isShiftedInt<1, 0>(0x8000000000000000)));
|
||||
EXPECT_TRUE((isShiftedInt<1, 63>(0x8000000000000000)));
|
||||
EXPECT_TRUE((isShiftedInt<2, 62>(0xC000000000000000)));
|
||||
EXPECT_FALSE((isShiftedInt<2, 62>(0xE000000000000000)));
|
||||
|
||||
// 0x201 is ten bits long and has a 1 in the MSB and LSB.
|
||||
EXPECT_TRUE((isShiftedInt<11, 5>(int64_t(0x201) << 5)));
|
||||
EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 3)));
|
||||
EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 6)));
|
||||
EXPECT_TRUE((isShiftedInt<11, 5>(-(int64_t(0x201) << 5))));
|
||||
EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 3))));
|
||||
EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 6))));
|
||||
|
||||
EXPECT_TRUE((isShiftedInt<6, 10>(-(int64_t(1) << 15))));
|
||||
EXPECT_FALSE((isShiftedInt<6, 10>(int64_t(1) << 15)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class OverflowTest : public ::testing::Test { };
|
||||
|
||||
using OverflowTestTypes = ::testing::Types<signed char, short, int, long,
|
||||
long long>;
|
||||
|
||||
TYPED_TEST_SUITE(OverflowTest, OverflowTestTypes, );
|
||||
|
||||
TYPED_TEST(OverflowTest, AddNoOverflow) {
|
||||
TypeParam Result;
|
||||
EXPECT_FALSE(AddOverflow<TypeParam>(1, 2, Result));
|
||||
EXPECT_EQ(Result, TypeParam(3));
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, AddOverflowToNegative) {
|
||||
TypeParam Result;
|
||||
auto MaxValue = std::numeric_limits<TypeParam>::max();
|
||||
EXPECT_TRUE(AddOverflow<TypeParam>(MaxValue, MaxValue, Result));
|
||||
EXPECT_EQ(Result, TypeParam(-2));
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, AddOverflowToMin) {
|
||||
TypeParam Result;
|
||||
auto MaxValue = std::numeric_limits<TypeParam>::max();
|
||||
EXPECT_TRUE(AddOverflow<TypeParam>(MaxValue, TypeParam(1), Result));
|
||||
EXPECT_EQ(Result, std::numeric_limits<TypeParam>::min());
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, AddOverflowToZero) {
|
||||
TypeParam Result;
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_TRUE(AddOverflow<TypeParam>(MinValue, MinValue, Result));
|
||||
EXPECT_EQ(Result, TypeParam(0));
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, AddOverflowToMax) {
|
||||
TypeParam Result;
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_TRUE(AddOverflow<TypeParam>(MinValue, TypeParam(-1), Result));
|
||||
EXPECT_EQ(Result, std::numeric_limits<TypeParam>::max());
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, SubNoOverflow) {
|
||||
TypeParam Result;
|
||||
EXPECT_FALSE(SubOverflow<TypeParam>(1, 2, Result));
|
||||
EXPECT_EQ(Result, TypeParam(-1));
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, SubOverflowToMax) {
|
||||
TypeParam Result;
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_TRUE(SubOverflow<TypeParam>(0, MinValue, Result));
|
||||
EXPECT_EQ(Result, MinValue);
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, SubOverflowToMin) {
|
||||
TypeParam Result;
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_TRUE(SubOverflow<TypeParam>(0, MinValue, Result));
|
||||
EXPECT_EQ(Result, MinValue);
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, SubOverflowToNegative) {
|
||||
TypeParam Result;
|
||||
auto MaxValue = std::numeric_limits<TypeParam>::max();
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_TRUE(SubOverflow<TypeParam>(MaxValue, MinValue, Result));
|
||||
EXPECT_EQ(Result, TypeParam(-1));
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, SubOverflowToPositive) {
|
||||
TypeParam Result;
|
||||
auto MaxValue = std::numeric_limits<TypeParam>::max();
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_TRUE(SubOverflow<TypeParam>(MinValue, MaxValue, Result));
|
||||
EXPECT_EQ(Result, TypeParam(1));
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, MulNoOverflow) {
|
||||
TypeParam Result;
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(1, 2, Result));
|
||||
EXPECT_EQ(Result, 2);
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(-1, 3, Result));
|
||||
EXPECT_EQ(Result, -3);
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(4, -2, Result));
|
||||
EXPECT_EQ(Result, -8);
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(-6, -5, Result));
|
||||
EXPECT_EQ(Result, 30);
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, MulNoOverflowToMax) {
|
||||
TypeParam Result;
|
||||
auto MaxValue = std::numeric_limits<TypeParam>::max();
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(MinValue + 1, -1, Result));
|
||||
EXPECT_EQ(Result, MaxValue);
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, MulOverflowToMin) {
|
||||
TypeParam Result;
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
EXPECT_TRUE(MulOverflow<TypeParam>(MinValue, -1, Result));
|
||||
EXPECT_EQ(Result, MinValue);
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, MulOverflowMax) {
|
||||
TypeParam Result;
|
||||
auto MinValue = std::numeric_limits<TypeParam>::min();
|
||||
auto MaxValue = std::numeric_limits<TypeParam>::max();
|
||||
EXPECT_TRUE(MulOverflow<TypeParam>(MinValue, MinValue, Result));
|
||||
EXPECT_EQ(Result, 0);
|
||||
EXPECT_TRUE(MulOverflow<TypeParam>(MaxValue, MaxValue, Result));
|
||||
EXPECT_EQ(Result, 1);
|
||||
}
|
||||
|
||||
TYPED_TEST(OverflowTest, MulResultZero) {
|
||||
TypeParam Result;
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(4, 0, Result));
|
||||
EXPECT_EQ(Result, TypeParam(0));
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(-5, 0, Result));
|
||||
EXPECT_EQ(Result, TypeParam(0));
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(0, 5, Result));
|
||||
EXPECT_EQ(Result, TypeParam(0));
|
||||
EXPECT_FALSE(MulOverflow<TypeParam>(0, -5, Result));
|
||||
EXPECT_EQ(Result, TypeParam(0));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
109
wpiutil/src/test/native/cpp/llvm/PointerIntPairTest.cpp
Normal file
109
wpiutil/src/test/native/cpp/llvm/PointerIntPairTest.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
//===- llvm/unittest/ADT/PointerIntPairTest.cpp - Unit tests --------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/PointerIntPair.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <limits>
|
||||
using namespace wpi;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(PointerIntPairTest, GetSet) {
|
||||
struct S {
|
||||
int i;
|
||||
};
|
||||
S s;
|
||||
|
||||
PointerIntPair<S *, 2> Pair(&s, 1U);
|
||||
EXPECT_EQ(&s, Pair.getPointer());
|
||||
EXPECT_EQ(1U, Pair.getInt());
|
||||
|
||||
Pair.setInt(2);
|
||||
EXPECT_EQ(&s, Pair.getPointer());
|
||||
EXPECT_EQ(2U, Pair.getInt());
|
||||
|
||||
Pair.setPointer(nullptr);
|
||||
EXPECT_EQ(nullptr, Pair.getPointer());
|
||||
EXPECT_EQ(2U, Pair.getInt());
|
||||
|
||||
Pair.setPointerAndInt(&s, 3U);
|
||||
EXPECT_EQ(&s, Pair.getPointer());
|
||||
EXPECT_EQ(3U, Pair.getInt());
|
||||
|
||||
// Make sure that we can perform all of our operations on enum classes.
|
||||
//
|
||||
// The concern is that enum classes are only explicitly convertible to
|
||||
// integers. This means that if we assume in PointerIntPair this, a
|
||||
// compilation error will result. This group of tests exercises the enum class
|
||||
// code to make sure that we do not run into such issues in the future.
|
||||
enum class E : unsigned {
|
||||
Case1,
|
||||
Case2,
|
||||
Case3,
|
||||
};
|
||||
PointerIntPair<S *, 2, E> Pair2(&s, E::Case1);
|
||||
EXPECT_EQ(&s, Pair2.getPointer());
|
||||
EXPECT_EQ(E::Case1, Pair2.getInt());
|
||||
|
||||
Pair2.setInt(E::Case2);
|
||||
EXPECT_EQ(&s, Pair2.getPointer());
|
||||
EXPECT_EQ(E::Case2, Pair2.getInt());
|
||||
|
||||
Pair2.setPointer(nullptr);
|
||||
EXPECT_EQ(nullptr, Pair2.getPointer());
|
||||
EXPECT_EQ(E::Case2, Pair2.getInt());
|
||||
|
||||
Pair2.setPointerAndInt(&s, E::Case3);
|
||||
EXPECT_EQ(&s, Pair2.getPointer());
|
||||
EXPECT_EQ(E::Case3, Pair2.getInt());
|
||||
|
||||
static_assert(std::is_trivially_copyable<PointerIntPair<S *, 2, E>>::value,
|
||||
"trivially copyable");
|
||||
}
|
||||
|
||||
TEST(PointerIntPairTest, DefaultInitialize) {
|
||||
PointerIntPair<float *, 2> Pair;
|
||||
EXPECT_EQ(nullptr, Pair.getPointer());
|
||||
EXPECT_EQ(0U, Pair.getInt());
|
||||
}
|
||||
|
||||
// In real code this would be a word-sized integer limited to 31 bits.
|
||||
struct Fixnum31 {
|
||||
uintptr_t Value;
|
||||
};
|
||||
struct FixnumPointerTraits {
|
||||
static inline void *getAsVoidPointer(Fixnum31 Num) {
|
||||
return reinterpret_cast<void *>(Num.Value << NumLowBitsAvailable);
|
||||
}
|
||||
static inline Fixnum31 getFromVoidPointer(void *P) {
|
||||
// In real code this would assert that the value is in range.
|
||||
return {reinterpret_cast<uintptr_t>(P) >> NumLowBitsAvailable};
|
||||
}
|
||||
static constexpr int NumLowBitsAvailable =
|
||||
std::numeric_limits<uintptr_t>::digits - 31;
|
||||
};
|
||||
TEST(PointerIntPairTest, ManyUnusedBits) {
|
||||
|
||||
PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits> pair;
|
||||
EXPECT_EQ((uintptr_t)0, pair.getPointer().Value);
|
||||
EXPECT_FALSE(pair.getInt());
|
||||
|
||||
pair.setPointerAndInt({ 0x7FFFFFFF }, true );
|
||||
EXPECT_EQ((uintptr_t)0x7FFFFFFF, pair.getPointer().Value);
|
||||
EXPECT_TRUE(pair.getInt());
|
||||
|
||||
EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1,
|
||||
(int)PointerLikeTypeTraits<decltype(pair)>::NumLowBitsAvailable);
|
||||
|
||||
static_assert(
|
||||
std::is_trivially_copyable<
|
||||
PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits>>::value,
|
||||
"trivially copyable");
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
159
wpiutil/src/test/native/cpp/llvm/PointerUnionTest.cpp
Normal file
159
wpiutil/src/test/native/cpp/llvm/PointerUnionTest.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
//===- llvm/unittest/ADT/PointerUnionTest.cpp - Optional unit tests -------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/PointerUnion.h"
|
||||
#include "gtest/gtest.h"
|
||||
using namespace wpi;
|
||||
|
||||
namespace {
|
||||
|
||||
typedef PointerUnion<int *, float *> PU;
|
||||
typedef PointerUnion<int *, float *, long long *> PU3;
|
||||
typedef PointerUnion<int *, float *, long long *, double *> PU4;
|
||||
|
||||
struct PointerUnionTest : public testing::Test {
|
||||
float f;
|
||||
int i;
|
||||
double d;
|
||||
long long l;
|
||||
|
||||
PU a, b, c, n;
|
||||
PU3 i3, f3, l3;
|
||||
PU4 i4, f4, l4, d4;
|
||||
PU4 i4null, f4null, l4null, d4null;
|
||||
|
||||
PointerUnionTest()
|
||||
: f(3.14f), i(42), d(3.14), l(42), a(&f), b(&i), c(&i), n(), i3(&i),
|
||||
f3(&f), l3(&l), i4(&i), f4(&f), l4(&l), d4(&d), i4null((int *)nullptr),
|
||||
f4null((float *)nullptr), l4null((long long *)nullptr),
|
||||
d4null((double *)nullptr) {}
|
||||
};
|
||||
|
||||
TEST_F(PointerUnionTest, Comparison) {
|
||||
EXPECT_TRUE(a == a);
|
||||
EXPECT_FALSE(a != a);
|
||||
EXPECT_TRUE(a != b);
|
||||
EXPECT_FALSE(a == b);
|
||||
EXPECT_TRUE(b == c);
|
||||
EXPECT_FALSE(b != c);
|
||||
EXPECT_TRUE(b != n);
|
||||
EXPECT_FALSE(b == n);
|
||||
EXPECT_TRUE(i3 == i3);
|
||||
EXPECT_FALSE(i3 != i3);
|
||||
EXPECT_TRUE(i3 != f3);
|
||||
EXPECT_TRUE(f3 != l3);
|
||||
EXPECT_TRUE(i4 == i4);
|
||||
EXPECT_FALSE(i4 != i4);
|
||||
EXPECT_TRUE(i4 != f4);
|
||||
EXPECT_TRUE(i4 != l4);
|
||||
EXPECT_TRUE(f4 != l4);
|
||||
EXPECT_TRUE(l4 != d4);
|
||||
EXPECT_TRUE(i4null != f4null);
|
||||
EXPECT_TRUE(i4null != l4null);
|
||||
EXPECT_TRUE(i4null != d4null);
|
||||
}
|
||||
|
||||
TEST_F(PointerUnionTest, Null) {
|
||||
EXPECT_FALSE(a.isNull());
|
||||
EXPECT_FALSE(b.isNull());
|
||||
EXPECT_TRUE(n.isNull());
|
||||
EXPECT_FALSE(!a);
|
||||
EXPECT_FALSE(!b);
|
||||
EXPECT_TRUE(!n);
|
||||
// workaround an issue with EXPECT macros and explicit bool
|
||||
EXPECT_TRUE((bool)a);
|
||||
EXPECT_TRUE((bool)b);
|
||||
EXPECT_FALSE(n);
|
||||
|
||||
EXPECT_NE(n, b);
|
||||
EXPECT_EQ(b, c);
|
||||
b = nullptr;
|
||||
EXPECT_EQ(n, b);
|
||||
EXPECT_NE(b, c);
|
||||
EXPECT_FALSE(i3.isNull());
|
||||
EXPECT_FALSE(f3.isNull());
|
||||
EXPECT_FALSE(l3.isNull());
|
||||
EXPECT_FALSE(i4.isNull());
|
||||
EXPECT_FALSE(f4.isNull());
|
||||
EXPECT_FALSE(l4.isNull());
|
||||
EXPECT_FALSE(d4.isNull());
|
||||
EXPECT_TRUE(i4null.isNull());
|
||||
EXPECT_TRUE(f4null.isNull());
|
||||
EXPECT_TRUE(l4null.isNull());
|
||||
EXPECT_TRUE(d4null.isNull());
|
||||
}
|
||||
|
||||
TEST_F(PointerUnionTest, Is) {
|
||||
EXPECT_FALSE(a.is<int *>());
|
||||
EXPECT_TRUE(a.is<float *>());
|
||||
EXPECT_TRUE(b.is<int *>());
|
||||
EXPECT_FALSE(b.is<float *>());
|
||||
EXPECT_TRUE(n.is<int *>());
|
||||
EXPECT_FALSE(n.is<float *>());
|
||||
EXPECT_TRUE(i3.is<int *>());
|
||||
EXPECT_TRUE(f3.is<float *>());
|
||||
EXPECT_TRUE(l3.is<long long *>());
|
||||
EXPECT_TRUE(i4.is<int *>());
|
||||
EXPECT_TRUE(f4.is<float *>());
|
||||
EXPECT_TRUE(l4.is<long long *>());
|
||||
EXPECT_TRUE(d4.is<double *>());
|
||||
EXPECT_TRUE(i4null.is<int *>());
|
||||
EXPECT_TRUE(f4null.is<float *>());
|
||||
EXPECT_TRUE(l4null.is<long long *>());
|
||||
EXPECT_TRUE(d4null.is<double *>());
|
||||
}
|
||||
|
||||
TEST_F(PointerUnionTest, Get) {
|
||||
EXPECT_EQ(a.get<float *>(), &f);
|
||||
EXPECT_EQ(b.get<int *>(), &i);
|
||||
EXPECT_EQ(n.get<int *>(), (int *)nullptr);
|
||||
}
|
||||
|
||||
template<int I> struct alignas(8) Aligned {};
|
||||
|
||||
typedef PointerUnion<Aligned<0> *, Aligned<1> *, Aligned<2> *, Aligned<3> *,
|
||||
Aligned<4> *, Aligned<5> *, Aligned<6> *, Aligned<7> *>
|
||||
PU8;
|
||||
|
||||
TEST_F(PointerUnionTest, ManyElements) {
|
||||
Aligned<0> a0;
|
||||
Aligned<7> a7;
|
||||
|
||||
PU8 a = &a0;
|
||||
EXPECT_TRUE(a.is<Aligned<0>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<1>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<2>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<3>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<4>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<5>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<6>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<7>*>());
|
||||
EXPECT_EQ(a.dyn_cast<Aligned<0>*>(), &a0);
|
||||
EXPECT_EQ(*a.getAddrOfPtr1(), &a0);
|
||||
|
||||
a = &a7;
|
||||
EXPECT_FALSE(a.is<Aligned<0>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<1>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<2>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<3>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<4>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<5>*>());
|
||||
EXPECT_FALSE(a.is<Aligned<6>*>());
|
||||
EXPECT_TRUE(a.is<Aligned<7>*>());
|
||||
EXPECT_EQ(a.dyn_cast<Aligned<7>*>(), &a7);
|
||||
|
||||
EXPECT_TRUE(a == PU8(&a7));
|
||||
EXPECT_TRUE(a != PU8(&a0));
|
||||
}
|
||||
|
||||
TEST_F(PointerUnionTest, GetAddrOfPtr1) {
|
||||
EXPECT_TRUE((void *)b.getAddrOfPtr1() == (void *)&b);
|
||||
EXPECT_TRUE((void *)n.getAddrOfPtr1() == (void *)&n);
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
78
wpiutil/src/test/native/cpp/llvm/STLForwardCompatTest.cpp
Normal file
78
wpiutil/src/test/native/cpp/llvm/STLForwardCompatTest.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
//===- STLForwardCompatTest.cpp - Unit tests for STLForwardCompat ---------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/STLForwardCompat.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(STLForwardCompatTest, NegationTest) {
|
||||
EXPECT_TRUE((wpi::negation<std::false_type>::value));
|
||||
EXPECT_FALSE((wpi::negation<std::true_type>::value));
|
||||
}
|
||||
|
||||
struct incomplete_type;
|
||||
|
||||
TEST(STLForwardCompatTest, ConjunctionTest) {
|
||||
EXPECT_TRUE((wpi::conjunction<>::value));
|
||||
EXPECT_FALSE((wpi::conjunction<std::false_type>::value));
|
||||
EXPECT_TRUE((wpi::conjunction<std::true_type>::value));
|
||||
EXPECT_FALSE((wpi::conjunction<std::false_type, incomplete_type>::value));
|
||||
EXPECT_FALSE((wpi::conjunction<std::false_type, std::true_type>::value));
|
||||
EXPECT_FALSE((wpi::conjunction<std::true_type, std::false_type>::value));
|
||||
EXPECT_TRUE((wpi::conjunction<std::true_type, std::true_type>::value));
|
||||
EXPECT_TRUE((wpi::conjunction<std::true_type, std::true_type,
|
||||
std::true_type>::value));
|
||||
}
|
||||
|
||||
TEST(STLForwardCompatTest, DisjunctionTest) {
|
||||
EXPECT_FALSE((wpi::disjunction<>::value));
|
||||
EXPECT_FALSE((wpi::disjunction<std::false_type>::value));
|
||||
EXPECT_TRUE((wpi::disjunction<std::true_type>::value));
|
||||
EXPECT_TRUE((wpi::disjunction<std::true_type, incomplete_type>::value));
|
||||
EXPECT_TRUE((wpi::disjunction<std::false_type, std::true_type>::value));
|
||||
EXPECT_TRUE((wpi::disjunction<std::true_type, std::false_type>::value));
|
||||
EXPECT_TRUE((wpi::disjunction<std::true_type, std::true_type>::value));
|
||||
EXPECT_TRUE((wpi::disjunction<std::true_type, std::true_type,
|
||||
std::true_type>::value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class STLForwardCompatRemoveCVRefTest : public ::testing::Test {};
|
||||
|
||||
using STLForwardCompatRemoveCVRefTestTypes = ::testing::Types<
|
||||
// clang-format off
|
||||
std::pair<int, int>,
|
||||
std::pair<int &, int>,
|
||||
std::pair<const int, int>,
|
||||
std::pair<volatile int, int>,
|
||||
std::pair<const volatile int &, int>,
|
||||
std::pair<int *, int *>,
|
||||
std::pair<int *const, int *>,
|
||||
std::pair<const int *, const int *>,
|
||||
std::pair<int *&, int *>
|
||||
// clang-format on
|
||||
>;
|
||||
|
||||
TYPED_TEST_SUITE(STLForwardCompatRemoveCVRefTest,
|
||||
STLForwardCompatRemoveCVRefTestTypes, );
|
||||
|
||||
TYPED_TEST(STLForwardCompatRemoveCVRefTest, RemoveCVRef) {
|
||||
using From = typename TypeParam::first_type;
|
||||
using To = typename TypeParam::second_type;
|
||||
EXPECT_TRUE(
|
||||
(std::is_same<typename wpi::remove_cvref<From>::type, To>::value));
|
||||
}
|
||||
|
||||
TYPED_TEST(STLForwardCompatRemoveCVRefTest, RemoveCVRefT) {
|
||||
using From = typename TypeParam::first_type;
|
||||
EXPECT_TRUE((std::is_same<typename wpi::remove_cvref<From>::type,
|
||||
wpi::remove_cvref_t<From>>::value));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
412
wpiutil/src/test/native/cpp/llvm/SmallPtrSetTest.cpp
Normal file
412
wpiutil/src/test/native/cpp/llvm/SmallPtrSetTest.cpp
Normal file
@@ -0,0 +1,412 @@
|
||||
//===- llvm/unittest/ADT/SmallPtrSetTest.cpp ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// SmallPtrSet unit tests.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/SmallPtrSet.h"
|
||||
#include "wpi/PointerIntPair.h"
|
||||
#include "wpi/PointerLikeTypeTraits.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
TEST(SmallPtrSetTest, Assignment) {
|
||||
int buf[8];
|
||||
for (int i = 0; i < 8; ++i)
|
||||
buf[i] = 0;
|
||||
|
||||
SmallPtrSet<int *, 4> s1 = {&buf[0], &buf[1]};
|
||||
SmallPtrSet<int *, 4> s2;
|
||||
(s2 = s1).insert(&buf[2]);
|
||||
|
||||
// Self assign as well.
|
||||
(s2 = static_cast<SmallPtrSet<int *, 4> &>(s2)).insert(&buf[3]);
|
||||
|
||||
s1 = s2;
|
||||
EXPECT_EQ(4U, s1.size());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
if (i < 4)
|
||||
EXPECT_TRUE(s1.count(&buf[i]));
|
||||
else
|
||||
EXPECT_FALSE(s1.count(&buf[i]));
|
||||
|
||||
// Assign and insert with initializer lists, and ones that contain both
|
||||
// duplicates and out-of-order elements.
|
||||
(s2 = {&buf[6], &buf[7], &buf[6]}).insert({&buf[5], &buf[4]});
|
||||
for (int i = 0; i < 8; ++i)
|
||||
if (i < 4)
|
||||
EXPECT_FALSE(s2.count(&buf[i]));
|
||||
else
|
||||
EXPECT_TRUE(s2.count(&buf[i]));
|
||||
}
|
||||
|
||||
TEST(SmallPtrSetTest, GrowthTest) {
|
||||
int i;
|
||||
int buf[8];
|
||||
for(i=0; i<8; ++i) buf[i]=0;
|
||||
|
||||
|
||||
SmallPtrSet<int *, 4> s;
|
||||
typedef SmallPtrSet<int *, 4>::iterator iter;
|
||||
|
||||
s.insert(&buf[0]);
|
||||
s.insert(&buf[1]);
|
||||
s.insert(&buf[2]);
|
||||
s.insert(&buf[3]);
|
||||
EXPECT_EQ(4U, s.size());
|
||||
|
||||
i = 0;
|
||||
for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
|
||||
(**I)++;
|
||||
EXPECT_EQ(4, i);
|
||||
for(i=0; i<8; ++i)
|
||||
EXPECT_EQ(i<4?1:0,buf[i]);
|
||||
|
||||
s.insert(&buf[4]);
|
||||
s.insert(&buf[5]);
|
||||
s.insert(&buf[6]);
|
||||
s.insert(&buf[7]);
|
||||
|
||||
i = 0;
|
||||
for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
|
||||
(**I)++;
|
||||
EXPECT_EQ(8, i);
|
||||
s.erase(&buf[4]);
|
||||
s.erase(&buf[5]);
|
||||
s.erase(&buf[6]);
|
||||
s.erase(&buf[7]);
|
||||
EXPECT_EQ(4U, s.size());
|
||||
|
||||
i = 0;
|
||||
for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
|
||||
(**I)++;
|
||||
EXPECT_EQ(4, i);
|
||||
for(i=0; i<8; ++i)
|
||||
EXPECT_EQ(i<4?3:1,buf[i]);
|
||||
|
||||
s.clear();
|
||||
for(i=0; i<8; ++i) buf[i]=0;
|
||||
for(i=0; i<128; ++i) s.insert(&buf[i%8]); // test repeated entires
|
||||
EXPECT_EQ(8U, s.size());
|
||||
for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
|
||||
(**I)++;
|
||||
for(i=0; i<8; ++i)
|
||||
EXPECT_EQ(1,buf[i]);
|
||||
}
|
||||
|
||||
TEST(SmallPtrSetTest, CopyAndMoveTest) {
|
||||
int buf[8];
|
||||
for (int i = 0; i < 8; ++i)
|
||||
buf[i] = 0;
|
||||
|
||||
SmallPtrSet<int *, 4> s1;
|
||||
s1.insert(&buf[0]);
|
||||
s1.insert(&buf[1]);
|
||||
s1.insert(&buf[2]);
|
||||
s1.insert(&buf[3]);
|
||||
EXPECT_EQ(4U, s1.size());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
if (i < 4)
|
||||
EXPECT_TRUE(s1.count(&buf[i]));
|
||||
else
|
||||
EXPECT_FALSE(s1.count(&buf[i]));
|
||||
|
||||
SmallPtrSet<int *, 4> s2(s1);
|
||||
EXPECT_EQ(4U, s2.size());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
if (i < 4)
|
||||
EXPECT_TRUE(s2.count(&buf[i]));
|
||||
else
|
||||
EXPECT_FALSE(s2.count(&buf[i]));
|
||||
|
||||
s1 = s2;
|
||||
EXPECT_EQ(4U, s1.size());
|
||||
EXPECT_EQ(4U, s2.size());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
if (i < 4)
|
||||
EXPECT_TRUE(s1.count(&buf[i]));
|
||||
else
|
||||
EXPECT_FALSE(s1.count(&buf[i]));
|
||||
|
||||
SmallPtrSet<int *, 4> s3(std::move(s1));
|
||||
EXPECT_EQ(4U, s3.size());
|
||||
EXPECT_TRUE(s1.empty());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
if (i < 4)
|
||||
EXPECT_TRUE(s3.count(&buf[i]));
|
||||
else
|
||||
EXPECT_FALSE(s3.count(&buf[i]));
|
||||
|
||||
// Move assign into the moved-from object. Also test move of a non-small
|
||||
// container.
|
||||
s3.insert(&buf[4]);
|
||||
s3.insert(&buf[5]);
|
||||
s3.insert(&buf[6]);
|
||||
s3.insert(&buf[7]);
|
||||
s1 = std::move(s3);
|
||||
EXPECT_EQ(8U, s1.size());
|
||||
EXPECT_TRUE(s3.empty());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
EXPECT_TRUE(s1.count(&buf[i]));
|
||||
|
||||
// Copy assign into a moved-from object.
|
||||
s3 = s1;
|
||||
EXPECT_EQ(8U, s3.size());
|
||||
EXPECT_EQ(8U, s1.size());
|
||||
for (int i = 0; i < 8; ++i)
|
||||
EXPECT_TRUE(s3.count(&buf[i]));
|
||||
}
|
||||
|
||||
TEST(SmallPtrSetTest, SwapTest) {
|
||||
int buf[10];
|
||||
|
||||
SmallPtrSet<int *, 2> a;
|
||||
SmallPtrSet<int *, 2> b;
|
||||
|
||||
a.insert(&buf[0]);
|
||||
a.insert(&buf[1]);
|
||||
b.insert(&buf[2]);
|
||||
|
||||
EXPECT_EQ(2U, a.size());
|
||||
EXPECT_EQ(1U, b.size());
|
||||
EXPECT_TRUE(a.count(&buf[0]));
|
||||
EXPECT_TRUE(a.count(&buf[1]));
|
||||
EXPECT_FALSE(a.count(&buf[2]));
|
||||
EXPECT_FALSE(a.count(&buf[3]));
|
||||
EXPECT_FALSE(b.count(&buf[0]));
|
||||
EXPECT_FALSE(b.count(&buf[1]));
|
||||
EXPECT_TRUE(b.count(&buf[2]));
|
||||
EXPECT_FALSE(b.count(&buf[3]));
|
||||
|
||||
std::swap(a, b);
|
||||
|
||||
EXPECT_EQ(1U, a.size());
|
||||
EXPECT_EQ(2U, b.size());
|
||||
EXPECT_FALSE(a.count(&buf[0]));
|
||||
EXPECT_FALSE(a.count(&buf[1]));
|
||||
EXPECT_TRUE(a.count(&buf[2]));
|
||||
EXPECT_FALSE(a.count(&buf[3]));
|
||||
EXPECT_TRUE(b.count(&buf[0]));
|
||||
EXPECT_TRUE(b.count(&buf[1]));
|
||||
EXPECT_FALSE(b.count(&buf[2]));
|
||||
EXPECT_FALSE(b.count(&buf[3]));
|
||||
|
||||
b.insert(&buf[3]);
|
||||
std::swap(a, b);
|
||||
|
||||
EXPECT_EQ(3U, a.size());
|
||||
EXPECT_EQ(1U, b.size());
|
||||
EXPECT_TRUE(a.count(&buf[0]));
|
||||
EXPECT_TRUE(a.count(&buf[1]));
|
||||
EXPECT_FALSE(a.count(&buf[2]));
|
||||
EXPECT_TRUE(a.count(&buf[3]));
|
||||
EXPECT_FALSE(b.count(&buf[0]));
|
||||
EXPECT_FALSE(b.count(&buf[1]));
|
||||
EXPECT_TRUE(b.count(&buf[2]));
|
||||
EXPECT_FALSE(b.count(&buf[3]));
|
||||
|
||||
std::swap(a, b);
|
||||
|
||||
EXPECT_EQ(1U, a.size());
|
||||
EXPECT_EQ(3U, b.size());
|
||||
EXPECT_FALSE(a.count(&buf[0]));
|
||||
EXPECT_FALSE(a.count(&buf[1]));
|
||||
EXPECT_TRUE(a.count(&buf[2]));
|
||||
EXPECT_FALSE(a.count(&buf[3]));
|
||||
EXPECT_TRUE(b.count(&buf[0]));
|
||||
EXPECT_TRUE(b.count(&buf[1]));
|
||||
EXPECT_FALSE(b.count(&buf[2]));
|
||||
EXPECT_TRUE(b.count(&buf[3]));
|
||||
|
||||
a.insert(&buf[4]);
|
||||
a.insert(&buf[5]);
|
||||
a.insert(&buf[6]);
|
||||
|
||||
std::swap(b, a);
|
||||
|
||||
EXPECT_EQ(3U, a.size());
|
||||
EXPECT_EQ(4U, b.size());
|
||||
EXPECT_TRUE(b.count(&buf[2]));
|
||||
EXPECT_TRUE(b.count(&buf[4]));
|
||||
EXPECT_TRUE(b.count(&buf[5]));
|
||||
EXPECT_TRUE(b.count(&buf[6]));
|
||||
EXPECT_TRUE(a.count(&buf[0]));
|
||||
EXPECT_TRUE(a.count(&buf[1]));
|
||||
EXPECT_TRUE(a.count(&buf[3]));
|
||||
}
|
||||
|
||||
void checkEraseAndIterators(SmallPtrSetImpl<int*> &S) {
|
||||
int buf[3];
|
||||
|
||||
S.insert(&buf[0]);
|
||||
S.insert(&buf[1]);
|
||||
S.insert(&buf[2]);
|
||||
|
||||
// Iterators must still be valid after erase() calls;
|
||||
auto B = S.begin();
|
||||
auto M = std::next(B);
|
||||
auto E = S.end();
|
||||
EXPECT_TRUE(*B == &buf[0] || *B == &buf[1] || *B == &buf[2]);
|
||||
EXPECT_TRUE(*M == &buf[0] || *M == &buf[1] || *M == &buf[2]);
|
||||
EXPECT_TRUE(*B != *M);
|
||||
int *Removable = *std::next(M);
|
||||
// No iterator points to Removable now.
|
||||
EXPECT_TRUE(Removable == &buf[0] || Removable == &buf[1] ||
|
||||
Removable == &buf[2]);
|
||||
EXPECT_TRUE(Removable != *B && Removable != *M);
|
||||
|
||||
S.erase(Removable);
|
||||
|
||||
// B,M,E iterators should still be valid
|
||||
EXPECT_EQ(B, S.begin());
|
||||
EXPECT_EQ(M, std::next(B));
|
||||
EXPECT_EQ(E, S.end());
|
||||
EXPECT_EQ(std::next(M), E);
|
||||
}
|
||||
|
||||
TEST(SmallPtrSetTest, EraseTest) {
|
||||
// Test when set stays small.
|
||||
SmallPtrSet<int *, 8> B;
|
||||
checkEraseAndIterators(B);
|
||||
|
||||
// Test when set grows big.
|
||||
SmallPtrSet<int *, 2> A;
|
||||
checkEraseAndIterators(A);
|
||||
}
|
||||
|
||||
// Verify that dereferencing and iteration work.
|
||||
TEST(SmallPtrSetTest, dereferenceAndIterate) {
|
||||
int Ints[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
SmallPtrSet<const int *, 4> S;
|
||||
for (int &I : Ints) {
|
||||
EXPECT_EQ(&I, *S.insert(&I).first);
|
||||
EXPECT_EQ(&I, *S.find(&I));
|
||||
}
|
||||
|
||||
// Iterate from each and count how many times each element is found.
|
||||
int Found[sizeof(Ints)/sizeof(int)] = {0};
|
||||
for (int &I : Ints)
|
||||
for (auto F = S.find(&I), E = S.end(); F != E; ++F)
|
||||
++Found[*F - Ints];
|
||||
|
||||
// Sort. We should hit the first element just once and the final element N
|
||||
// times.
|
||||
std::sort(std::begin(Found), std::end(Found));
|
||||
for (auto F = std::begin(Found), E = std::end(Found); F != E; ++F)
|
||||
EXPECT_EQ(F - Found + 1, *F);
|
||||
}
|
||||
|
||||
// Verify that const pointers work for count and find even when the underlying
|
||||
// SmallPtrSet is not for a const pointer type.
|
||||
TEST(SmallPtrSetTest, ConstTest) {
|
||||
SmallPtrSet<int *, 8> IntSet;
|
||||
int A;
|
||||
int *B = &A;
|
||||
const int *C = &A;
|
||||
IntSet.insert(B);
|
||||
EXPECT_EQ(IntSet.count(B), 1u);
|
||||
EXPECT_EQ(IntSet.count(C), 1u);
|
||||
EXPECT_TRUE(IntSet.contains(B));
|
||||
EXPECT_TRUE(IntSet.contains(C));
|
||||
}
|
||||
|
||||
// Verify that we automatically get the const version of PointerLikeTypeTraits
|
||||
// filled in for us, even for a non-pointer type
|
||||
using TestPair = PointerIntPair<int *, 1>;
|
||||
|
||||
TEST(SmallPtrSetTest, ConstNonPtrTest) {
|
||||
SmallPtrSet<TestPair, 8> IntSet;
|
||||
int A[1];
|
||||
TestPair Pair(&A[0], 1);
|
||||
IntSet.insert(Pair);
|
||||
EXPECT_EQ(IntSet.count(Pair), 1u);
|
||||
EXPECT_TRUE(IntSet.contains(Pair));
|
||||
}
|
||||
|
||||
// Test equality comparison.
|
||||
TEST(SmallPtrSetTest, EqualityComparison) {
|
||||
int buf[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
buf[i] = 0;
|
||||
|
||||
SmallPtrSet<int *, 1> a;
|
||||
a.insert(&buf[0]);
|
||||
a.insert(&buf[1]);
|
||||
|
||||
SmallPtrSet<int *, 2> b;
|
||||
b.insert(&buf[1]);
|
||||
b.insert(&buf[0]);
|
||||
|
||||
SmallPtrSet<int *, 3> c;
|
||||
c.insert(&buf[1]);
|
||||
c.insert(&buf[2]);
|
||||
|
||||
SmallPtrSet<int *, 4> d;
|
||||
d.insert(&buf[0]);
|
||||
|
||||
SmallPtrSet<int *, 5> e;
|
||||
e.insert(&buf[0]);
|
||||
e.insert(&buf[1]);
|
||||
e.insert(&buf[2]);
|
||||
|
||||
EXPECT_EQ(a, b);
|
||||
EXPECT_EQ(b, a);
|
||||
EXPECT_NE(b, c);
|
||||
EXPECT_NE(c, a);
|
||||
EXPECT_NE(d, a);
|
||||
EXPECT_NE(a, d);
|
||||
EXPECT_NE(a, e);
|
||||
EXPECT_NE(e, a);
|
||||
EXPECT_NE(c, e);
|
||||
EXPECT_NE(e, d);
|
||||
}
|
||||
|
||||
TEST(SmallPtrSetTest, Contains) {
|
||||
SmallPtrSet<int *, 2> Set;
|
||||
int buf[4] = {0, 11, 22, 11};
|
||||
EXPECT_FALSE(Set.contains(&buf[0]));
|
||||
EXPECT_FALSE(Set.contains(&buf[1]));
|
||||
|
||||
Set.insert(&buf[0]);
|
||||
Set.insert(&buf[1]);
|
||||
EXPECT_TRUE(Set.contains(&buf[0]));
|
||||
EXPECT_TRUE(Set.contains(&buf[1]));
|
||||
EXPECT_FALSE(Set.contains(&buf[3]));
|
||||
|
||||
Set.insert(&buf[1]);
|
||||
EXPECT_TRUE(Set.contains(&buf[0]));
|
||||
EXPECT_TRUE(Set.contains(&buf[1]));
|
||||
EXPECT_FALSE(Set.contains(&buf[3]));
|
||||
|
||||
Set.erase(&buf[1]);
|
||||
EXPECT_TRUE(Set.contains(&buf[0]));
|
||||
EXPECT_FALSE(Set.contains(&buf[1]));
|
||||
|
||||
Set.insert(&buf[1]);
|
||||
Set.insert(&buf[2]);
|
||||
EXPECT_TRUE(Set.contains(&buf[0]));
|
||||
EXPECT_TRUE(Set.contains(&buf[1]));
|
||||
EXPECT_TRUE(Set.contains(&buf[2]));
|
||||
}
|
||||
|
||||
TEST(SmallPtrSetTest, InsertIterator) {
|
||||
SmallPtrSet<int *, 5> Set;
|
||||
int Vals[5] = {11, 22, 33, 44, 55};
|
||||
int *Buf[5] = {&Vals[0], &Vals[1], &Vals[2], &Vals[3], &Vals[4]};
|
||||
|
||||
for (int *Ptr : Buf)
|
||||
Set.insert(Set.begin(), Ptr);
|
||||
|
||||
// Ensure that all of the values were copied into the set.
|
||||
for (const auto *Ptr : Buf)
|
||||
EXPECT_TRUE(Set.contains(Ptr));
|
||||
}
|
||||
194
wpiutil/src/test/native/cpp/llvm/SmallSetTest.cpp
Normal file
194
wpiutil/src/test/native/cpp/llvm/SmallSetTest.cpp
Normal file
@@ -0,0 +1,194 @@
|
||||
//===- llvm/unittest/ADT/SmallSetTest.cpp ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// SmallSet unit tests.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/SmallSet.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <string>
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
TEST(SmallSetTest, Insert) {
|
||||
|
||||
SmallSet<int, 4> s1;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
s1.insert(i);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
s1.insert(i);
|
||||
|
||||
EXPECT_EQ(4u, s1.size());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
EXPECT_EQ(1u, s1.count(i));
|
||||
|
||||
EXPECT_EQ(0u, s1.count(4));
|
||||
}
|
||||
|
||||
TEST(SmallSetTest, Grow) {
|
||||
SmallSet<int, 4> s1;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
s1.insert(i);
|
||||
|
||||
EXPECT_EQ(8u, s1.size());
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
EXPECT_EQ(1u, s1.count(i));
|
||||
|
||||
EXPECT_EQ(0u, s1.count(8));
|
||||
}
|
||||
|
||||
TEST(SmallSetTest, Erase) {
|
||||
SmallSet<int, 4> s1;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
s1.insert(i);
|
||||
|
||||
EXPECT_EQ(8u, s1.size());
|
||||
|
||||
// Remove elements one by one and check if all other elements are still there.
|
||||
for (int i = 0; i < 8; i++) {
|
||||
EXPECT_EQ(1u, s1.count(i));
|
||||
EXPECT_TRUE(s1.erase(i));
|
||||
EXPECT_EQ(0u, s1.count(i));
|
||||
EXPECT_EQ(8u - i - 1, s1.size());
|
||||
for (int j = i + 1; j < 8; j++)
|
||||
EXPECT_EQ(1u, s1.count(j));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0u, s1.count(8));
|
||||
}
|
||||
|
||||
TEST(SmallSetTest, IteratorInt) {
|
||||
SmallSet<int, 4> s1;
|
||||
|
||||
// Test the 'small' case.
|
||||
for (int i = 0; i < 3; i++)
|
||||
s1.insert(i);
|
||||
|
||||
std::vector<int> V(s1.begin(), s1.end());
|
||||
// Make sure the elements are in the expected order.
|
||||
std::sort(V.begin(), V.end());
|
||||
for (int i = 0; i < 3; i++)
|
||||
EXPECT_EQ(i, V[i]);
|
||||
|
||||
// Test the 'big' case by adding a few more elements to switch to std::set
|
||||
// internally.
|
||||
for (int i = 3; i < 6; i++)
|
||||
s1.insert(i);
|
||||
|
||||
V.assign(s1.begin(), s1.end());
|
||||
// Make sure the elements are in the expected order.
|
||||
std::sort(V.begin(), V.end());
|
||||
for (int i = 0; i < 6; i++)
|
||||
EXPECT_EQ(i, V[i]);
|
||||
}
|
||||
|
||||
TEST(SmallSetTest, IteratorString) {
|
||||
// Test SmallSetIterator for SmallSet with a type with non-trivial
|
||||
// ctors/dtors.
|
||||
SmallSet<std::string, 2> s1;
|
||||
|
||||
s1.insert("str 1");
|
||||
s1.insert("str 2");
|
||||
s1.insert("str 1");
|
||||
|
||||
std::vector<std::string> V(s1.begin(), s1.end());
|
||||
std::sort(V.begin(), V.end());
|
||||
EXPECT_EQ(2u, s1.size());
|
||||
EXPECT_EQ("str 1", V[0]);
|
||||
EXPECT_EQ("str 2", V[1]);
|
||||
|
||||
s1.insert("str 4");
|
||||
s1.insert("str 0");
|
||||
s1.insert("str 4");
|
||||
|
||||
V.assign(s1.begin(), s1.end());
|
||||
// Make sure the elements are in the expected order.
|
||||
std::sort(V.begin(), V.end());
|
||||
EXPECT_EQ(4u, s1.size());
|
||||
EXPECT_EQ("str 0", V[0]);
|
||||
EXPECT_EQ("str 1", V[1]);
|
||||
EXPECT_EQ("str 2", V[2]);
|
||||
EXPECT_EQ("str 4", V[3]);
|
||||
}
|
||||
|
||||
TEST(SmallSetTest, IteratorIncMoveCopy) {
|
||||
// Test SmallSetIterator for SmallSet with a type with non-trivial
|
||||
// ctors/dtors.
|
||||
SmallSet<std::string, 2> s1;
|
||||
|
||||
s1.insert("str 1");
|
||||
s1.insert("str 2");
|
||||
|
||||
auto Iter = s1.begin();
|
||||
EXPECT_EQ("str 1", *Iter);
|
||||
++Iter;
|
||||
EXPECT_EQ("str 2", *Iter);
|
||||
|
||||
s1.insert("str 4");
|
||||
s1.insert("str 0");
|
||||
auto Iter2 = s1.begin();
|
||||
Iter = std::move(Iter2);
|
||||
EXPECT_EQ("str 0", *Iter);
|
||||
}
|
||||
|
||||
TEST(SmallSetTest, EqualityComparisonTest) {
|
||||
SmallSet<int, 8> s1small;
|
||||
SmallSet<int, 10> s2small;
|
||||
SmallSet<int, 3> s3large;
|
||||
SmallSet<int, 8> s4large;
|
||||
|
||||
for (int i = 1; i < 5; i++) {
|
||||
s1small.insert(i);
|
||||
s2small.insert(5 - i);
|
||||
s3large.insert(i);
|
||||
}
|
||||
for (int i = 1; i < 11; i++)
|
||||
s4large.insert(i);
|
||||
|
||||
EXPECT_EQ(s1small, s1small);
|
||||
EXPECT_EQ(s3large, s3large);
|
||||
|
||||
EXPECT_EQ(s1small, s2small);
|
||||
EXPECT_EQ(s1small, s3large);
|
||||
EXPECT_EQ(s2small, s3large);
|
||||
|
||||
EXPECT_NE(s1small, s4large);
|
||||
EXPECT_NE(s4large, s3large);
|
||||
}
|
||||
|
||||
TEST(SmallSetTest, Contains) {
|
||||
SmallSet<int, 2> Set;
|
||||
EXPECT_FALSE(Set.contains(0));
|
||||
EXPECT_FALSE(Set.contains(1));
|
||||
|
||||
Set.insert(0);
|
||||
Set.insert(1);
|
||||
EXPECT_TRUE(Set.contains(0));
|
||||
EXPECT_TRUE(Set.contains(1));
|
||||
|
||||
Set.insert(1);
|
||||
EXPECT_TRUE(Set.contains(0));
|
||||
EXPECT_TRUE(Set.contains(1));
|
||||
|
||||
Set.erase(1);
|
||||
EXPECT_TRUE(Set.contains(0));
|
||||
EXPECT_FALSE(Set.contains(1));
|
||||
|
||||
Set.insert(1);
|
||||
Set.insert(2);
|
||||
EXPECT_TRUE(Set.contains(0));
|
||||
EXPECT_TRUE(Set.contains(1));
|
||||
EXPECT_TRUE(Set.contains(2));
|
||||
}
|
||||
166
wpiutil/src/test/native/cpp/llvm/SmallStringTest.cpp
Normal file
166
wpiutil/src/test/native/cpp/llvm/SmallStringTest.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//===- llvm/unittest/ADT/SmallStringTest.cpp ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// SmallString unit tests.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/SmallString.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
namespace {
|
||||
|
||||
// Test fixture class
|
||||
class SmallStringTest : public testing::Test {
|
||||
protected:
|
||||
typedef SmallString<40> StringType;
|
||||
|
||||
StringType theString;
|
||||
|
||||
void assertEmpty(StringType & v) {
|
||||
// Size tests
|
||||
EXPECT_EQ(0u, v.size());
|
||||
EXPECT_TRUE(v.empty());
|
||||
// Iterator tests
|
||||
EXPECT_TRUE(v.begin() == v.end());
|
||||
}
|
||||
};
|
||||
|
||||
// New string test.
|
||||
TEST_F(SmallStringTest, EmptyStringTest) {
|
||||
SCOPED_TRACE("EmptyStringTest");
|
||||
assertEmpty(theString);
|
||||
EXPECT_TRUE(theString.rbegin() == theString.rend());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AssignRepeated) {
|
||||
theString.assign(3, 'a');
|
||||
EXPECT_EQ(3u, theString.size());
|
||||
EXPECT_STREQ("aaa", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AssignIterPair) {
|
||||
std::string_view abc = "abc";
|
||||
theString.assign(abc.begin(), abc.end());
|
||||
EXPECT_EQ(3u, theString.size());
|
||||
EXPECT_STREQ("abc", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AssignStringView) {
|
||||
std::string_view abc = "abc";
|
||||
theString.assign(abc);
|
||||
EXPECT_EQ(3u, theString.size());
|
||||
EXPECT_STREQ("abc", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AssignSmallVector) {
|
||||
std::string_view abc = "abc";
|
||||
SmallVector<char, 10> abcVec(abc.begin(), abc.end());
|
||||
theString.assign(abcVec);
|
||||
EXPECT_EQ(3u, theString.size());
|
||||
EXPECT_STREQ("abc", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AssignStringViews) {
|
||||
theString.assign({"abc", "def", "ghi"});
|
||||
EXPECT_EQ(9u, theString.size());
|
||||
EXPECT_STREQ("abcdefghi", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AppendIterPair) {
|
||||
std::string_view abc = "abc";
|
||||
theString.append(abc.begin(), abc.end());
|
||||
theString.append(abc.begin(), abc.end());
|
||||
EXPECT_EQ(6u, theString.size());
|
||||
EXPECT_STREQ("abcabc", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AppendStringView) {
|
||||
std::string_view abc = "abc";
|
||||
theString.append(abc);
|
||||
theString.append(abc);
|
||||
EXPECT_EQ(6u, theString.size());
|
||||
EXPECT_STREQ("abcabc", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AppendSmallVector) {
|
||||
std::string_view abc = "abc";
|
||||
SmallVector<char, 10> abcVec(abc.begin(), abc.end());
|
||||
theString.append(abcVec);
|
||||
theString.append(abcVec);
|
||||
EXPECT_EQ(6u, theString.size());
|
||||
EXPECT_STREQ("abcabc", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, AppendStringViews) {
|
||||
theString.append({"abc", "def", "ghi"});
|
||||
EXPECT_EQ(9u, theString.size());
|
||||
EXPECT_STREQ("abcdefghi", theString.c_str());
|
||||
std::string_view Jkl = "jkl";
|
||||
std::string Mno = "mno";
|
||||
SmallString<4> Pqr("pqr");
|
||||
const char *Stu = "stu";
|
||||
theString.append({Jkl, Mno, Pqr, Stu});
|
||||
EXPECT_EQ(21u, theString.size());
|
||||
EXPECT_STREQ("abcdefghijklmnopqrstu", theString.c_str());
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, StringViewConversion) {
|
||||
std::string_view abc = "abc";
|
||||
theString.assign(abc.begin(), abc.end());
|
||||
std::string_view theStringView = theString;
|
||||
EXPECT_EQ("abc", theStringView);
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, StdStringConversion) {
|
||||
std::string_view abc = "abc";
|
||||
theString.assign(abc.begin(), abc.end());
|
||||
std::string theStdString = std::string(theString);
|
||||
EXPECT_EQ("abc", theStdString);
|
||||
}
|
||||
|
||||
TEST_F(SmallStringTest, Find) {
|
||||
theString = "hello";
|
||||
EXPECT_EQ(2U, theString.find('l'));
|
||||
EXPECT_EQ(std::string_view::npos, theString.find('z'));
|
||||
EXPECT_EQ(std::string_view::npos, theString.find("helloworld"));
|
||||
EXPECT_EQ(0U, theString.find("hello"));
|
||||
EXPECT_EQ(1U, theString.find("ello"));
|
||||
EXPECT_EQ(std::string_view::npos, theString.find("zz"));
|
||||
EXPECT_EQ(2U, theString.find("ll", 2));
|
||||
EXPECT_EQ(std::string_view::npos, theString.find("ll", 3));
|
||||
EXPECT_EQ(0U, theString.find(""));
|
||||
|
||||
EXPECT_EQ(3U, theString.rfind('l'));
|
||||
EXPECT_EQ(std::string_view::npos, theString.rfind('z'));
|
||||
EXPECT_EQ(std::string_view::npos, theString.rfind("helloworld"));
|
||||
EXPECT_EQ(0U, theString.rfind("hello"));
|
||||
EXPECT_EQ(1U, theString.rfind("ello"));
|
||||
EXPECT_EQ(std::string_view::npos, theString.rfind("zz"));
|
||||
|
||||
EXPECT_EQ(2U, theString.find_first_of('l'));
|
||||
EXPECT_EQ(1U, theString.find_first_of("el"));
|
||||
EXPECT_EQ(std::string_view::npos, theString.find_first_of("xyz"));
|
||||
|
||||
EXPECT_EQ(1U, theString.find_first_not_of('h'));
|
||||
EXPECT_EQ(4U, theString.find_first_not_of("hel"));
|
||||
EXPECT_EQ(std::string_view::npos, theString.find_first_not_of("hello"));
|
||||
|
||||
theString = "hellx xello hell ello world foo bar hello";
|
||||
EXPECT_EQ(36U, theString.find("hello"));
|
||||
EXPECT_EQ(28U, theString.find("foo"));
|
||||
EXPECT_EQ(12U, theString.find("hell", 2));
|
||||
EXPECT_EQ(0U, theString.find(""));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
1399
wpiutil/src/test/native/cpp/llvm/SmallVectorTest.cpp
Normal file
1399
wpiutil/src/test/native/cpp/llvm/SmallVectorTest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
613
wpiutil/src/test/native/cpp/llvm/StringMapTest.cpp
Normal file
613
wpiutil/src/test/native/cpp/llvm/StringMapTest.cpp
Normal file
@@ -0,0 +1,613 @@
|
||||
//===- llvm/unittest/ADT/StringMapMap.cpp - StringMap unit tests ----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/StringMap.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
using namespace wpi;
|
||||
|
||||
namespace {
|
||||
|
||||
// Test fixture
|
||||
class StringMapTest : public testing::Test {
|
||||
protected:
|
||||
StringMap<uint32_t> testMap;
|
||||
|
||||
static const char testKey[];
|
||||
static const uint32_t testValue;
|
||||
static const char* testKeyFirst;
|
||||
static size_t testKeyLength;
|
||||
static const std::string testKeyStr;
|
||||
|
||||
void assertEmptyMap() {
|
||||
// Size tests
|
||||
EXPECT_EQ(0u, testMap.size());
|
||||
EXPECT_TRUE(testMap.empty());
|
||||
|
||||
// Iterator tests
|
||||
EXPECT_TRUE(testMap.begin() == testMap.end());
|
||||
|
||||
// Lookup tests
|
||||
EXPECT_EQ(0u, testMap.count(testKey));
|
||||
EXPECT_EQ(0u, testMap.count(std::string_view(testKeyFirst, testKeyLength)));
|
||||
EXPECT_EQ(0u, testMap.count(testKeyStr));
|
||||
EXPECT_TRUE(testMap.find(testKey) == testMap.end());
|
||||
EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) ==
|
||||
testMap.end());
|
||||
EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
|
||||
}
|
||||
|
||||
void assertSingleItemMap() {
|
||||
// Size tests
|
||||
EXPECT_EQ(1u, testMap.size());
|
||||
EXPECT_FALSE(testMap.begin() == testMap.end());
|
||||
EXPECT_FALSE(testMap.empty());
|
||||
|
||||
// Iterator tests
|
||||
StringMap<uint32_t>::iterator it = testMap.begin();
|
||||
EXPECT_STREQ(testKey, it->first().data());
|
||||
EXPECT_EQ(testValue, it->second);
|
||||
++it;
|
||||
EXPECT_TRUE(it == testMap.end());
|
||||
|
||||
// Lookup tests
|
||||
EXPECT_EQ(1u, testMap.count(testKey));
|
||||
EXPECT_EQ(1u, testMap.count(std::string_view(testKeyFirst, testKeyLength)));
|
||||
EXPECT_EQ(1u, testMap.count(testKeyStr));
|
||||
EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
|
||||
EXPECT_TRUE(testMap.find(std::string_view(testKeyFirst, testKeyLength)) ==
|
||||
testMap.begin());
|
||||
EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
|
||||
}
|
||||
};
|
||||
|
||||
const char StringMapTest::testKey[] = "key";
|
||||
const uint32_t StringMapTest::testValue = 1u;
|
||||
const char* StringMapTest::testKeyFirst = testKey;
|
||||
size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
|
||||
const std::string StringMapTest::testKeyStr(testKey);
|
||||
|
||||
struct CountCopyAndMove {
|
||||
CountCopyAndMove() = default;
|
||||
CountCopyAndMove(const CountCopyAndMove &) { copy = 1; }
|
||||
CountCopyAndMove(CountCopyAndMove &&) { move = 1; }
|
||||
void operator=(const CountCopyAndMove &) { ++copy; }
|
||||
void operator=(CountCopyAndMove &&) { ++move; }
|
||||
int copy = 0;
|
||||
int move = 0;
|
||||
};
|
||||
|
||||
// Empty map tests.
|
||||
TEST_F(StringMapTest, EmptyMapTest) {
|
||||
assertEmptyMap();
|
||||
}
|
||||
|
||||
// Constant map tests.
|
||||
TEST_F(StringMapTest, ConstEmptyMapTest) {
|
||||
const StringMap<uint32_t>& constTestMap = testMap;
|
||||
|
||||
// Size tests
|
||||
EXPECT_EQ(0u, constTestMap.size());
|
||||
EXPECT_TRUE(constTestMap.empty());
|
||||
|
||||
// Iterator tests
|
||||
EXPECT_TRUE(constTestMap.begin() == constTestMap.end());
|
||||
|
||||
// Lookup tests
|
||||
EXPECT_EQ(0u, constTestMap.count(testKey));
|
||||
EXPECT_EQ(0u, constTestMap.count(std::string_view(testKeyFirst, testKeyLength)));
|
||||
EXPECT_EQ(0u, constTestMap.count(testKeyStr));
|
||||
EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end());
|
||||
EXPECT_TRUE(constTestMap.find(std::string_view(testKeyFirst, testKeyLength)) ==
|
||||
constTestMap.end());
|
||||
EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end());
|
||||
}
|
||||
|
||||
// A map with a single entry.
|
||||
TEST_F(StringMapTest, SingleEntryMapTest) {
|
||||
testMap[testKey] = testValue;
|
||||
assertSingleItemMap();
|
||||
}
|
||||
|
||||
// Test clear() method.
|
||||
TEST_F(StringMapTest, ClearTest) {
|
||||
testMap[testKey] = testValue;
|
||||
testMap.clear();
|
||||
assertEmptyMap();
|
||||
}
|
||||
|
||||
// Test erase(iterator) method.
|
||||
TEST_F(StringMapTest, EraseIteratorTest) {
|
||||
testMap[testKey] = testValue;
|
||||
testMap.erase(testMap.begin());
|
||||
assertEmptyMap();
|
||||
}
|
||||
|
||||
// Test erase(value) method.
|
||||
TEST_F(StringMapTest, EraseValueTest) {
|
||||
testMap[testKey] = testValue;
|
||||
testMap.erase(testKey);
|
||||
assertEmptyMap();
|
||||
}
|
||||
|
||||
// Test inserting two values and erasing one.
|
||||
TEST_F(StringMapTest, InsertAndEraseTest) {
|
||||
testMap[testKey] = testValue;
|
||||
testMap["otherKey"] = 2;
|
||||
testMap.erase("otherKey");
|
||||
assertSingleItemMap();
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, SmallFullMapTest) {
|
||||
// StringMap has a tricky corner case when the map is small (<8 buckets) and
|
||||
// it fills up through a balanced pattern of inserts and erases. This can
|
||||
// lead to inf-loops in some cases (PR13148) so we test it explicitly here.
|
||||
wpi::StringMap<int> Map(2);
|
||||
|
||||
Map["eins"] = 1;
|
||||
Map["zwei"] = 2;
|
||||
Map["drei"] = 3;
|
||||
Map.erase("drei");
|
||||
Map.erase("eins");
|
||||
Map["veir"] = 4;
|
||||
Map["funf"] = 5;
|
||||
|
||||
EXPECT_EQ(3u, Map.size());
|
||||
EXPECT_EQ(0, Map.lookup("eins"));
|
||||
EXPECT_EQ(2, Map.lookup("zwei"));
|
||||
EXPECT_EQ(0, Map.lookup("drei"));
|
||||
EXPECT_EQ(4, Map.lookup("veir"));
|
||||
EXPECT_EQ(5, Map.lookup("funf"));
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, CopyCtorTest) {
|
||||
wpi::StringMap<int> Map;
|
||||
|
||||
Map["eins"] = 1;
|
||||
Map["zwei"] = 2;
|
||||
Map["drei"] = 3;
|
||||
Map.erase("drei");
|
||||
Map.erase("eins");
|
||||
Map["veir"] = 4;
|
||||
Map["funf"] = 5;
|
||||
|
||||
EXPECT_EQ(3u, Map.size());
|
||||
EXPECT_EQ(0, Map.lookup("eins"));
|
||||
EXPECT_EQ(2, Map.lookup("zwei"));
|
||||
EXPECT_EQ(0, Map.lookup("drei"));
|
||||
EXPECT_EQ(4, Map.lookup("veir"));
|
||||
EXPECT_EQ(5, Map.lookup("funf"));
|
||||
|
||||
wpi::StringMap<int> Map2(Map);
|
||||
EXPECT_EQ(3u, Map2.size());
|
||||
EXPECT_EQ(0, Map2.lookup("eins"));
|
||||
EXPECT_EQ(2, Map2.lookup("zwei"));
|
||||
EXPECT_EQ(0, Map2.lookup("drei"));
|
||||
EXPECT_EQ(4, Map2.lookup("veir"));
|
||||
EXPECT_EQ(5, Map2.lookup("funf"));
|
||||
}
|
||||
|
||||
// A more complex iteration test.
|
||||
TEST_F(StringMapTest, IterationTest) {
|
||||
bool visited[100];
|
||||
|
||||
// Insert 100 numbers into the map
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
std::stringstream ss;
|
||||
ss << "key_" << i;
|
||||
testMap[ss.str()] = i;
|
||||
visited[i] = false;
|
||||
}
|
||||
|
||||
// Iterate over all numbers and mark each one found.
|
||||
for (StringMap<uint32_t>::iterator it = testMap.begin();
|
||||
it != testMap.end(); ++it) {
|
||||
std::stringstream ss;
|
||||
ss << "key_" << it->second;
|
||||
ASSERT_STREQ(ss.str().c_str(), it->first().data());
|
||||
visited[it->second] = true;
|
||||
}
|
||||
|
||||
// Ensure every number was visited.
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
|
||||
}
|
||||
}
|
||||
|
||||
// Test StringMapEntry::Create() method.
|
||||
TEST_F(StringMapTest, StringMapEntryTest) {
|
||||
StringMap<uint32_t>::value_type *entry =
|
||||
StringMap<uint32_t>::value_type::Create(
|
||||
std::string_view(testKeyFirst, testKeyLength), 1u);
|
||||
EXPECT_STREQ(testKey, entry->first().data());
|
||||
EXPECT_EQ(1u, entry->second);
|
||||
entry->Destroy();
|
||||
}
|
||||
|
||||
// Test insert() method.
|
||||
TEST_F(StringMapTest, InsertTest) {
|
||||
SCOPED_TRACE("InsertTest");
|
||||
testMap.insert(
|
||||
StringMap<uint32_t>::value_type::Create(
|
||||
std::string_view(testKeyFirst, testKeyLength),
|
||||
1u));
|
||||
assertSingleItemMap();
|
||||
}
|
||||
|
||||
// Test insert(pair<K, V>) method
|
||||
TEST_F(StringMapTest, InsertPairTest) {
|
||||
bool Inserted;
|
||||
StringMap<uint32_t>::iterator NewIt;
|
||||
std::tie(NewIt, Inserted) =
|
||||
testMap.insert(std::make_pair(testKeyFirst, testValue));
|
||||
EXPECT_EQ(1u, testMap.size());
|
||||
EXPECT_EQ(testValue, testMap[testKeyFirst]);
|
||||
EXPECT_EQ(testKeyFirst, NewIt->first());
|
||||
EXPECT_EQ(testValue, NewIt->second);
|
||||
EXPECT_TRUE(Inserted);
|
||||
|
||||
StringMap<uint32_t>::iterator ExistingIt;
|
||||
std::tie(ExistingIt, Inserted) =
|
||||
testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
|
||||
EXPECT_EQ(1u, testMap.size());
|
||||
EXPECT_EQ(testValue, testMap[testKeyFirst]);
|
||||
EXPECT_FALSE(Inserted);
|
||||
EXPECT_EQ(NewIt, ExistingIt);
|
||||
}
|
||||
|
||||
// Test insert(pair<K, V>) method when rehashing occurs
|
||||
TEST_F(StringMapTest, InsertRehashingPairTest) {
|
||||
// Check that the correct iterator is returned when the inserted element is
|
||||
// moved to a different bucket during internal rehashing. This depends on
|
||||
// the particular key, and the implementation of StringMap and HashString.
|
||||
// Changes to those might result in this test not actually checking that.
|
||||
StringMap<uint32_t> t(0);
|
||||
EXPECT_EQ(0u, t.getNumBuckets());
|
||||
|
||||
StringMap<uint32_t>::iterator It =
|
||||
t.insert(std::make_pair("abcdef", 42)).first;
|
||||
EXPECT_EQ(16u, t.getNumBuckets());
|
||||
EXPECT_EQ("abcdef", It->first());
|
||||
EXPECT_EQ(42u, It->second);
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, InsertOrAssignTest) {
|
||||
struct A : CountCopyAndMove {
|
||||
A(int v) : v(v) {}
|
||||
int v;
|
||||
};
|
||||
StringMap<A> t(0);
|
||||
|
||||
auto try1 = t.insert_or_assign("A", A(1));
|
||||
EXPECT_TRUE(try1.second);
|
||||
EXPECT_EQ(1, try1.first->second.v);
|
||||
EXPECT_EQ(1, try1.first->second.move);
|
||||
|
||||
auto try2 = t.insert_or_assign("A", A(2));
|
||||
EXPECT_FALSE(try2.second);
|
||||
EXPECT_EQ(2, try2.first->second.v);
|
||||
EXPECT_EQ(2, try1.first->second.move);
|
||||
|
||||
EXPECT_EQ(try1.first, try2.first);
|
||||
EXPECT_EQ(0, try1.first->second.copy);
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, IterMapKeys) {
|
||||
StringMap<int> Map;
|
||||
Map["A"] = 1;
|
||||
Map["B"] = 2;
|
||||
Map["C"] = 3;
|
||||
Map["D"] = 3;
|
||||
|
||||
auto Keys = to_vector<4>(Map.keys());
|
||||
std::sort(Keys.begin(), Keys.end());
|
||||
|
||||
SmallVector<std::string_view, 4> Expected = {"A", "B", "C", "D"};
|
||||
EXPECT_EQ(Expected, Keys);
|
||||
}
|
||||
|
||||
// Create a non-default constructable value
|
||||
struct StringMapTestStruct {
|
||||
StringMapTestStruct(int i) : i(i) {}
|
||||
StringMapTestStruct() = delete;
|
||||
int i;
|
||||
};
|
||||
|
||||
TEST_F(StringMapTest, NonDefaultConstructable) {
|
||||
StringMap<StringMapTestStruct> t;
|
||||
t.insert(std::make_pair("Test", StringMapTestStruct(123)));
|
||||
StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
|
||||
ASSERT_NE(iter, t.end());
|
||||
ASSERT_EQ(iter->second.i, 123);
|
||||
}
|
||||
|
||||
struct Immovable {
|
||||
Immovable() {}
|
||||
Immovable(Immovable&&) = delete; // will disable the other special members
|
||||
};
|
||||
|
||||
struct MoveOnly {
|
||||
int i;
|
||||
MoveOnly(int i) : i(i) {}
|
||||
MoveOnly(const Immovable&) : i(0) {}
|
||||
MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
|
||||
MoveOnly &operator=(MoveOnly &&RHS) {
|
||||
i = RHS.i;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
MoveOnly(const MoveOnly &) = delete;
|
||||
MoveOnly &operator=(const MoveOnly &) = delete;
|
||||
};
|
||||
|
||||
TEST_F(StringMapTest, MoveOnly) {
|
||||
StringMap<MoveOnly> t;
|
||||
t.insert(std::make_pair("Test", MoveOnly(42)));
|
||||
std::string_view Key = "Test";
|
||||
StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42))
|
||||
->Destroy();
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, CtorArg) {
|
||||
std::string_view Key = "Test";
|
||||
StringMapEntry<MoveOnly>::Create(Key, Immovable())
|
||||
->Destroy();
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, MoveConstruct) {
|
||||
StringMap<int> A;
|
||||
A["x"] = 42;
|
||||
StringMap<int> B = std::move(A);
|
||||
ASSERT_EQ(A.size(), 0u);
|
||||
ASSERT_EQ(B.size(), 1u);
|
||||
ASSERT_EQ(B["x"], 42);
|
||||
ASSERT_EQ(B.count("y"), 0u);
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, MoveAssignment) {
|
||||
StringMap<int> A;
|
||||
A["x"] = 42;
|
||||
StringMap<int> B;
|
||||
B["y"] = 117;
|
||||
A = std::move(B);
|
||||
ASSERT_EQ(A.size(), 1u);
|
||||
ASSERT_EQ(B.size(), 0u);
|
||||
ASSERT_EQ(A["y"], 117);
|
||||
ASSERT_EQ(B.count("x"), 0u);
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, EqualEmpty) {
|
||||
StringMap<int> A;
|
||||
StringMap<int> B;
|
||||
ASSERT_TRUE(A == B);
|
||||
ASSERT_FALSE(A != B);
|
||||
ASSERT_TRUE(A == A); // self check
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, EqualWithValues) {
|
||||
StringMap<int> A;
|
||||
A["A"] = 1;
|
||||
A["B"] = 2;
|
||||
A["C"] = 3;
|
||||
A["D"] = 3;
|
||||
|
||||
StringMap<int> B;
|
||||
B["A"] = 1;
|
||||
B["B"] = 2;
|
||||
B["C"] = 3;
|
||||
B["D"] = 3;
|
||||
|
||||
ASSERT_TRUE(A == B);
|
||||
ASSERT_TRUE(B == A);
|
||||
ASSERT_FALSE(A != B);
|
||||
ASSERT_FALSE(B != A);
|
||||
ASSERT_TRUE(A == A); // self check
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, NotEqualMissingKeys) {
|
||||
StringMap<int> A;
|
||||
A["A"] = 1;
|
||||
A["B"] = 2;
|
||||
|
||||
StringMap<int> B;
|
||||
B["A"] = 1;
|
||||
B["B"] = 2;
|
||||
B["C"] = 3;
|
||||
B["D"] = 3;
|
||||
|
||||
ASSERT_FALSE(A == B);
|
||||
ASSERT_FALSE(B == A);
|
||||
ASSERT_TRUE(A != B);
|
||||
ASSERT_TRUE(B != A);
|
||||
}
|
||||
|
||||
TEST_F(StringMapTest, NotEqualWithDifferentValues) {
|
||||
StringMap<int> A;
|
||||
A["A"] = 1;
|
||||
A["B"] = 2;
|
||||
A["C"] = 100;
|
||||
A["D"] = 3;
|
||||
|
||||
StringMap<int> B;
|
||||
B["A"] = 1;
|
||||
B["B"] = 2;
|
||||
B["C"] = 3;
|
||||
B["D"] = 3;
|
||||
|
||||
ASSERT_FALSE(A == B);
|
||||
ASSERT_FALSE(B == A);
|
||||
ASSERT_TRUE(A != B);
|
||||
ASSERT_TRUE(B != A);
|
||||
}
|
||||
|
||||
struct Countable {
|
||||
int &InstanceCount;
|
||||
int Number;
|
||||
Countable(int Number, int &InstanceCount)
|
||||
: InstanceCount(InstanceCount), Number(Number) {
|
||||
++InstanceCount;
|
||||
}
|
||||
Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
|
||||
++InstanceCount;
|
||||
C.Number = -1;
|
||||
}
|
||||
Countable(const Countable &C)
|
||||
: InstanceCount(C.InstanceCount), Number(C.Number) {
|
||||
++InstanceCount;
|
||||
}
|
||||
Countable &operator=(Countable C) {
|
||||
Number = C.Number;
|
||||
return *this;
|
||||
}
|
||||
~Countable() { --InstanceCount; }
|
||||
};
|
||||
|
||||
TEST_F(StringMapTest, MoveDtor) {
|
||||
int InstanceCount = 0;
|
||||
StringMap<Countable> A;
|
||||
A.insert(std::make_pair("x", Countable(42, InstanceCount)));
|
||||
ASSERT_EQ(InstanceCount, 1);
|
||||
auto I = A.find("x");
|
||||
ASSERT_NE(I, A.end());
|
||||
ASSERT_EQ(I->second.Number, 42);
|
||||
|
||||
StringMap<Countable> B;
|
||||
B = std::move(A);
|
||||
ASSERT_EQ(InstanceCount, 1);
|
||||
ASSERT_TRUE(A.empty());
|
||||
I = B.find("x");
|
||||
ASSERT_NE(I, B.end());
|
||||
ASSERT_EQ(I->second.Number, 42);
|
||||
|
||||
B = StringMap<Countable>();
|
||||
ASSERT_EQ(InstanceCount, 0);
|
||||
ASSERT_TRUE(B.empty());
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Simple class that counts how many moves and copy happens when growing a map
|
||||
struct CountCtorCopyAndMove {
|
||||
static unsigned Ctor;
|
||||
static unsigned Move;
|
||||
static unsigned Copy;
|
||||
int Data = 0;
|
||||
CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; }
|
||||
CountCtorCopyAndMove() { Ctor++; }
|
||||
|
||||
CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; }
|
||||
CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) {
|
||||
Copy++;
|
||||
return *this;
|
||||
}
|
||||
CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; }
|
||||
CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) {
|
||||
Move++;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
unsigned CountCtorCopyAndMove::Copy = 0;
|
||||
unsigned CountCtorCopyAndMove::Move = 0;
|
||||
unsigned CountCtorCopyAndMove::Ctor = 0;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// Make sure creating the map with an initial size of N actually gives us enough
|
||||
// buckets to insert N items without increasing allocation size.
|
||||
TEST(StringMapCustomTest, InitialSizeTest) {
|
||||
// 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an
|
||||
// arbitrary prime, picked without any good reason.
|
||||
for (auto Size : {1, 32, 67}) {
|
||||
StringMap<CountCtorCopyAndMove> Map(Size);
|
||||
auto NumBuckets = Map.getNumBuckets();
|
||||
CountCtorCopyAndMove::Move = 0;
|
||||
CountCtorCopyAndMove::Copy = 0;
|
||||
for (int i = 0; i < Size; ++i)
|
||||
Map.insert(std::pair<std::string, CountCtorCopyAndMove>(
|
||||
std::piecewise_construct, std::forward_as_tuple(std::to_string(i)),
|
||||
std::forward_as_tuple(i)));
|
||||
// After the initial move, the map will move the Elts in the Entry.
|
||||
EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move);
|
||||
// We copy once the pair from the Elts vector
|
||||
EXPECT_EQ(0u, CountCtorCopyAndMove::Copy);
|
||||
// Check that the map didn't grow
|
||||
EXPECT_EQ(Map.getNumBuckets(), NumBuckets);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(StringMapCustomTest, BracketOperatorCtor) {
|
||||
StringMap<CountCtorCopyAndMove> Map;
|
||||
CountCtorCopyAndMove::Ctor = 0;
|
||||
Map["abcd"];
|
||||
EXPECT_EQ(1u, CountCtorCopyAndMove::Ctor);
|
||||
// Test that operator[] does not create a value when it is already in the map
|
||||
CountCtorCopyAndMove::Ctor = 0;
|
||||
Map["abcd"];
|
||||
EXPECT_EQ(0u, CountCtorCopyAndMove::Ctor);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct NonMoveableNonCopyableType {
|
||||
int Data = 0;
|
||||
NonMoveableNonCopyableType() = default;
|
||||
NonMoveableNonCopyableType(int Data) : Data(Data) {}
|
||||
NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
|
||||
NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
// Test that we can "emplace" an element in the map without involving map/move
|
||||
TEST(StringMapCustomTest, EmplaceTest) {
|
||||
StringMap<NonMoveableNonCopyableType> Map;
|
||||
Map.try_emplace("abcd", 42);
|
||||
EXPECT_EQ(1u, Map.count("abcd"));
|
||||
EXPECT_EQ(42, Map["abcd"].Data);
|
||||
}
|
||||
|
||||
// Test that StringMapEntryBase can handle size_t wide sizes.
|
||||
TEST(StringMapCustomTest, StringMapEntryBaseSize) {
|
||||
size_t LargeValue;
|
||||
|
||||
// Test that the entry can represent max-unsigned.
|
||||
if (sizeof(size_t) <= sizeof(unsigned))
|
||||
LargeValue = std::numeric_limits<unsigned>::max();
|
||||
else
|
||||
LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
|
||||
StringMapEntryBase LargeBase(LargeValue);
|
||||
EXPECT_EQ(LargeValue, LargeBase.getKeyLength());
|
||||
|
||||
// Test that the entry can hold at least max size_t.
|
||||
LargeValue = std::numeric_limits<size_t>::max();
|
||||
StringMapEntryBase LargerBase(LargeValue);
|
||||
LargeValue = std::numeric_limits<size_t>::max();
|
||||
EXPECT_EQ(LargeValue, LargerBase.getKeyLength());
|
||||
}
|
||||
|
||||
// Test that StringMapEntry can handle size_t wide sizes.
|
||||
TEST(StringMapCustomTest, StringMapEntrySize) {
|
||||
size_t LargeValue;
|
||||
|
||||
// Test that the entry can represent max-unsigned.
|
||||
if (sizeof(size_t) <= sizeof(unsigned))
|
||||
LargeValue = std::numeric_limits<unsigned>::max();
|
||||
else
|
||||
LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
|
||||
StringMapEntry<int> LargeEntry(LargeValue);
|
||||
std::string_view Key = LargeEntry.getKey();
|
||||
EXPECT_EQ(LargeValue, Key.size());
|
||||
|
||||
// Test that the entry can hold at least max size_t.
|
||||
LargeValue = std::numeric_limits<size_t>::max();
|
||||
StringMapEntry<int> LargerEntry(LargeValue);
|
||||
Key = LargerEntry.getKey();
|
||||
EXPECT_EQ(LargeValue, Key.size());
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
210
wpiutil/src/test/native/cpp/llvm/SwapByteOrderTest.cpp
Normal file
210
wpiutil/src/test/native/cpp/llvm/SwapByteOrderTest.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
//===- unittests/Support/SwapByteOrderTest.cpp - swap byte order test -----===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "wpi/SwapByteOrder.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
using namespace wpi;
|
||||
|
||||
#undef max
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(ByteSwap, Swap_32) {
|
||||
EXPECT_EQ(0x44332211u, ByteSwap_32(0x11223344));
|
||||
EXPECT_EQ(0xDDCCBBAAu, ByteSwap_32(0xAABBCCDD));
|
||||
}
|
||||
|
||||
TEST(ByteSwap, Swap_64) {
|
||||
EXPECT_EQ(0x8877665544332211ULL, ByteSwap_64(0x1122334455667788LL));
|
||||
EXPECT_EQ(0x1100FFEEDDCCBBAAULL, ByteSwap_64(0xAABBCCDDEEFF0011LL));
|
||||
}
|
||||
|
||||
// In these first two tests all of the original_uintx values are truncated
|
||||
// except for 64. We could avoid this, but there's really no point.
|
||||
|
||||
TEST(getSwappedBytes, UnsignedRoundTrip) {
|
||||
// The point of the bit twiddling of magic is to test with and without bits
|
||||
// in every byte.
|
||||
uint64_t value = 1;
|
||||
for (std::size_t i = 0; i <= sizeof(value); ++i) {
|
||||
uint8_t original_uint8 = static_cast<uint8_t>(value);
|
||||
EXPECT_EQ(original_uint8,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_uint8)));
|
||||
|
||||
uint16_t original_uint16 = static_cast<uint16_t>(value);
|
||||
EXPECT_EQ(original_uint16,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_uint16)));
|
||||
|
||||
uint32_t original_uint32 = static_cast<uint32_t>(value);
|
||||
EXPECT_EQ(original_uint32,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_uint32)));
|
||||
|
||||
uint64_t original_uint64 = static_cast<uint64_t>(value);
|
||||
EXPECT_EQ(original_uint64,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_uint64)));
|
||||
|
||||
value = (value << 8) | 0x55; // binary 0101 0101.
|
||||
}
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, SignedRoundTrip) {
|
||||
// The point of the bit twiddling of magic is to test with and without bits
|
||||
// in every byte.
|
||||
uint64_t value = 1;
|
||||
for (std::size_t i = 0; i <= sizeof(value); ++i) {
|
||||
int8_t original_int8 = static_cast<int8_t>(value);
|
||||
EXPECT_EQ(original_int8,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int8)));
|
||||
|
||||
int16_t original_int16 = static_cast<int16_t>(value);
|
||||
EXPECT_EQ(original_int16,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int16)));
|
||||
|
||||
int32_t original_int32 = static_cast<int32_t>(value);
|
||||
EXPECT_EQ(original_int32,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int32)));
|
||||
|
||||
int64_t original_int64 = static_cast<int64_t>(value);
|
||||
EXPECT_EQ(original_int64,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int64)));
|
||||
|
||||
// Test other sign.
|
||||
value *= -1;
|
||||
|
||||
original_int8 = static_cast<int8_t>(value);
|
||||
EXPECT_EQ(original_int8,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int8)));
|
||||
|
||||
original_int16 = static_cast<int16_t>(value);
|
||||
EXPECT_EQ(original_int16,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int16)));
|
||||
|
||||
original_int32 = static_cast<int32_t>(value);
|
||||
EXPECT_EQ(original_int32,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int32)));
|
||||
|
||||
original_int64 = static_cast<int64_t>(value);
|
||||
EXPECT_EQ(original_int64,
|
||||
sys::getSwappedBytes(sys::getSwappedBytes(original_int64)));
|
||||
|
||||
// Return to normal sign and twiddle.
|
||||
value *= -1;
|
||||
value = (value << 8) | 0x55; // binary 0101 0101.
|
||||
}
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, uint8_t) {
|
||||
EXPECT_EQ(uint8_t(0x11), sys::getSwappedBytes(uint8_t(0x11)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, uint16_t) {
|
||||
EXPECT_EQ(uint16_t(0x1122), sys::getSwappedBytes(uint16_t(0x2211)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, uint32_t) {
|
||||
EXPECT_EQ(uint32_t(0x11223344), sys::getSwappedBytes(uint32_t(0x44332211)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, uint64_t) {
|
||||
EXPECT_EQ(uint64_t(0x1122334455667788ULL),
|
||||
sys::getSwappedBytes(uint64_t(0x8877665544332211ULL)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, int8_t) {
|
||||
EXPECT_EQ(int8_t(0x11), sys::getSwappedBytes(int8_t(0x11)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, int16_t) {
|
||||
EXPECT_EQ(int16_t(0x1122), sys::getSwappedBytes(int16_t(0x2211)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, int32_t) {
|
||||
EXPECT_EQ(int32_t(0x11223344), sys::getSwappedBytes(int32_t(0x44332211)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, int64_t) {
|
||||
EXPECT_EQ(int64_t(0x1122334455667788LL),
|
||||
sys::getSwappedBytes(int64_t(0x8877665544332211LL)));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, float) {
|
||||
EXPECT_EQ(1.79366203433576585078237386661e-43f, sys::getSwappedBytes(-0.0f));
|
||||
// 0x11223344
|
||||
EXPECT_EQ(7.1653228759765625e2f, sys::getSwappedBytes(1.2795344e-28f));
|
||||
}
|
||||
|
||||
TEST(getSwappedBytes, double) {
|
||||
EXPECT_EQ(6.32404026676795576546008054871e-322, sys::getSwappedBytes(-0.0));
|
||||
// 0x1122334455667788
|
||||
EXPECT_EQ(-7.08687663657301358331704585496e-268,
|
||||
sys::getSwappedBytes(3.84141202447173065923064450234e-226));
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, uint8_t) {
|
||||
uint8_t value = 0x11;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(uint8_t(0x11), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, uint16_t) {
|
||||
uint16_t value = 0x2211;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(uint16_t(0x1122), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, uint32_t) {
|
||||
uint32_t value = 0x44332211;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(uint32_t(0x11223344), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, uint64_t) {
|
||||
uint64_t value = 0x8877665544332211ULL;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(uint64_t(0x1122334455667788ULL), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, int8_t) {
|
||||
int8_t value = 0x11;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(int8_t(0x11), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, int16_t) {
|
||||
int16_t value = 0x2211;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(int16_t(0x1122), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, int32_t) {
|
||||
int32_t value = 0x44332211;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(int32_t(0x11223344), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, int64_t) {
|
||||
int64_t value = 0x8877665544332211LL;
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(int64_t(0x1122334455667788LL), value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, float) {
|
||||
float value = 7.1653228759765625e2f; // 0x44332211
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(1.2795344e-28f, value);
|
||||
}
|
||||
|
||||
TEST(swapByteOrder, double) {
|
||||
double value = -7.08687663657301358331704585496e-268; // 0x8877665544332211
|
||||
sys::swapByteOrder(value);
|
||||
EXPECT_EQ(3.84141202447173065923064450234e-226, value);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user