diff options
Diffstat (limited to 'unittests/ADT')
-rw-r--r-- | unittests/ADT/APFloatTest.cpp | 24 | ||||
-rw-r--r-- | unittests/ADT/APIntTest.cpp | 42 | ||||
-rw-r--r-- | unittests/ADT/BitVectorTest.cpp | 46 | ||||
-rw-r--r-- | unittests/ADT/DenseMapTest.cpp | 41 | ||||
-rw-r--r-- | unittests/ADT/HashingTest.cpp | 424 | ||||
-rw-r--r-- | unittests/ADT/IntrusiveRefCntPtrTest.cpp | 64 | ||||
-rw-r--r-- | unittests/ADT/SmallPtrSetTest.cpp | 72 | ||||
-rw-r--r-- | unittests/ADT/SmallStringTest.cpp | 148 | ||||
-rw-r--r-- | unittests/ADT/SparseSetTest.cpp | 186 | ||||
-rw-r--r-- | unittests/ADT/StringRefTest.cpp | 143 | ||||
-rw-r--r-- | unittests/ADT/TripleTest.cpp | 143 | ||||
-rw-r--r-- | unittests/ADT/VariadicFunctionTest.cpp | 110 |
12 files changed, 1430 insertions, 13 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index b6e02e3a9a3e..cc207f764da2 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -653,4 +653,28 @@ TEST(APFloatTest, getLargest) { EXPECT_EQ(1.7976931348623158e+308, APFloat::getLargest(APFloat::IEEEdouble).convertToDouble()); } +TEST(APFloatTest, convert) { + bool losesInfo; + APFloat test(APFloat::IEEEdouble, "1.0"); + test.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_EQ(1.0f, test.convertToFloat()); + EXPECT_FALSE(losesInfo); + + test = APFloat(APFloat::x87DoubleExtended, "0x1p-53"); + test.add(APFloat(APFloat::x87DoubleExtended, "1.0"), APFloat::rmNearestTiesToEven); + test.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_EQ(1.0, test.convertToDouble()); + EXPECT_TRUE(losesInfo); + + test = APFloat(APFloat::IEEEquad, "0x1p-53"); + test.add(APFloat(APFloat::IEEEquad, "1.0"), APFloat::rmNearestTiesToEven); + test.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_EQ(1.0, test.convertToDouble()); + EXPECT_TRUE(losesInfo); + + test = APFloat(APFloat::x87DoubleExtended, "0xf.fffffffp+28"); + test.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_EQ(4294967295.0, test.convertToDouble()); + EXPECT_FALSE(losesInfo); +} } diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 490811deb8f9..89b8aa94e464 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -144,6 +144,12 @@ TEST(APIntTest, i1) { EXPECT_EQ(zero, one.lshr(1)); EXPECT_EQ(zero, one.ashr(1)); + // Rotates. + EXPECT_EQ(one, one.rotl(0)); + EXPECT_EQ(one, one.rotl(1)); + EXPECT_EQ(one, one.rotr(0)); + EXPECT_EQ(one, one.rotr(1)); + // Multiplies. EXPECT_EQ(neg_one, neg_one * one); EXPECT_EQ(neg_one, one * neg_one); @@ -354,7 +360,7 @@ TEST(APIntTest, toString) { APInt(8, 0).toString(S, 16, true, true); EXPECT_EQ(S.str().str(), "0x0"); S.clear(); - APInt(8, 0).toString(S, 36, true, true); + APInt(8, 0).toString(S, 36, true, false); EXPECT_EQ(S.str().str(), "0"); S.clear(); @@ -371,7 +377,7 @@ TEST(APIntTest, toString) { APInt(8, 255, isSigned).toString(S, 16, isSigned, true); EXPECT_EQ(S.str().str(), "0xFF"); S.clear(); - APInt(8, 255, isSigned).toString(S, 36, isSigned, true); + APInt(8, 255, isSigned).toString(S, 36, isSigned, false); EXPECT_EQ(S.str().str(), "73"); S.clear(); @@ -388,7 +394,7 @@ TEST(APIntTest, toString) { APInt(8, 255, isSigned).toString(S, 16, isSigned, true); EXPECT_EQ(S.str().str(), "-0x1"); S.clear(); - APInt(8, 255, isSigned).toString(S, 36, isSigned, true); + APInt(8, 255, isSigned).toString(S, 36, isSigned, false); EXPECT_EQ(S.str().str(), "-1"); S.clear(); } @@ -450,4 +456,34 @@ TEST(APIntTest, mul_clear) { EXPECT_EQ(ValA.toString(10, false), ValC.toString(10, false)); } +TEST(APIntTest, Rotate) { + EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotl(0)); + EXPECT_EQ(APInt(8, 2), APInt(8, 1).rotl(1)); + EXPECT_EQ(APInt(8, 4), APInt(8, 1).rotl(2)); + EXPECT_EQ(APInt(8, 16), APInt(8, 1).rotl(4)); + EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotl(8)); + + EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotl(0)); + EXPECT_EQ(APInt(8, 32), APInt(8, 16).rotl(1)); + EXPECT_EQ(APInt(8, 64), APInt(8, 16).rotl(2)); + EXPECT_EQ(APInt(8, 1), APInt(8, 16).rotl(4)); + EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotl(8)); + + EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotr(0)); + EXPECT_EQ(APInt(8, 8), APInt(8, 16).rotr(1)); + EXPECT_EQ(APInt(8, 4), APInt(8, 16).rotr(2)); + EXPECT_EQ(APInt(8, 1), APInt(8, 16).rotr(4)); + EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotr(8)); + + EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotr(0)); + EXPECT_EQ(APInt(8, 128), APInt(8, 1).rotr(1)); + EXPECT_EQ(APInt(8, 64), APInt(8, 1).rotr(2)); + EXPECT_EQ(APInt(8, 16), APInt(8, 1).rotr(4)); + EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotr(8)); + + APInt Big(256, "00004000800000000000000000003fff8000000000000000", 16); + APInt Rot(256, "3fff80000000000000000000000000000000000040008000", 16); + EXPECT_EQ(Rot, Big.rotr(144)); +} + } diff --git a/unittests/ADT/BitVectorTest.cpp b/unittests/ADT/BitVectorTest.cpp index fa663121a8a6..f733e13fdfc3 100644 --- a/unittests/ADT/BitVectorTest.cpp +++ b/unittests/ADT/BitVectorTest.cpp @@ -196,6 +196,52 @@ TEST(BitVectorTest, ProxyIndex) { EXPECT_TRUE(Vec.none()); } +TEST(BitVectorTest, PortableBitMask) { + BitVector A; + const uint32_t Mask1[] = { 0x80000000, 6, 5 }; + + A.resize(10); + A.setBitsInMask(Mask1, 3); + EXPECT_EQ(10u, A.size()); + EXPECT_FALSE(A.test(0)); + + A.resize(32); + A.setBitsInMask(Mask1, 3); + EXPECT_FALSE(A.test(0)); + EXPECT_TRUE(A.test(31)); + EXPECT_EQ(1u, A.count()); + + A.resize(33); + A.setBitsInMask(Mask1, 1); + EXPECT_EQ(1u, A.count()); + A.setBitsInMask(Mask1, 2); + EXPECT_EQ(1u, A.count()); + + A.resize(34); + A.setBitsInMask(Mask1, 2); + EXPECT_EQ(2u, A.count()); + + A.resize(65); + A.setBitsInMask(Mask1, 3); + EXPECT_EQ(4u, A.count()); + + A.setBitsNotInMask(Mask1, 1); + EXPECT_EQ(32u+3u, A.count()); + + A.setBitsNotInMask(Mask1, 3); + EXPECT_EQ(65u, A.count()); + + A.resize(96); + EXPECT_EQ(65u, A.count()); + + A.clear(); + A.resize(128); + A.setBitsNotInMask(Mask1, 3); + EXPECT_EQ(96u-5u, A.count()); + + A.clearBitsNotInMask(Mask1, 1); + EXPECT_EQ(64-4u, A.count()); +} } #endif diff --git a/unittests/ADT/DenseMapTest.cpp b/unittests/ADT/DenseMapTest.cpp index afac651a6b2b..e0ee7782ccbb 100644 --- a/unittests/ADT/DenseMapTest.cpp +++ b/unittests/ADT/DenseMapTest.cpp @@ -176,4 +176,45 @@ TEST_F(DenseMapTest, ConstIteratorTest) { EXPECT_TRUE(cit == cit2); } +// 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_F(DenseMapTest, 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(1, 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()); +} + } diff --git a/unittests/ADT/HashingTest.cpp b/unittests/ADT/HashingTest.cpp new file mode 100644 index 000000000000..b148f144513c --- /dev/null +++ b/unittests/ADT/HashingTest.cpp @@ -0,0 +1,424 @@ +//===- llvm/unittest/ADT/HashingTest.cpp ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Hashing.h unit tests. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/Support/DataTypes.h" +#include <deque> +#include <list> +#include <map> +#include <vector> + +namespace llvm { + +// Helper for test code to print hash codes. +void PrintTo(const hash_code &code, std::ostream *os) { + *os << static_cast<size_t>(code); +} + +// Fake an object that is recognized as hashable data to test super large +// objects. +struct LargeTestInteger { uint64_t arr[8]; }; + +struct NonPOD { + uint64_t x, y; + NonPOD(uint64_t x, uint64_t y) : x(x), y(y) {} + ~NonPOD() {} + friend hash_code hash_value(const NonPOD &obj) { + return hash_combine(obj.x, obj.y); + } +}; + +namespace hashing { +namespace detail { +template <> struct is_hashable_data<LargeTestInteger> : true_type {}; +} // namespace detail +} // namespace hashing + +} // namespace llvm + +using namespace llvm; + +namespace { + +enum TestEnumeration { + TE_Foo = 42, + TE_Bar = 43 +}; + +TEST(HashingTest, HashValueBasicTest) { + int x = 42, y = 43, c = 'x'; + void *p = 0; + uint64_t i = 71; + const unsigned ci = 71; + volatile int vi = 71; + const volatile int cvi = 71; + uintptr_t addr = reinterpret_cast<uintptr_t>(&y); + EXPECT_EQ(hash_value(42), hash_value(x)); + EXPECT_EQ(hash_value(42), hash_value(TE_Foo)); + EXPECT_NE(hash_value(42), hash_value(y)); + EXPECT_NE(hash_value(42), hash_value(TE_Bar)); + EXPECT_NE(hash_value(42), hash_value(p)); + EXPECT_EQ(hash_value(71), hash_value(i)); + EXPECT_EQ(hash_value(71), hash_value(ci)); + EXPECT_EQ(hash_value(71), hash_value(vi)); + EXPECT_EQ(hash_value(71), hash_value(cvi)); + EXPECT_EQ(hash_value(c), hash_value('x')); + EXPECT_EQ(hash_value('4'), hash_value('0' + 4)); + EXPECT_EQ(hash_value(addr), hash_value(&y)); +} + +TEST(HashingTest, HashValueStdPair) { + EXPECT_EQ(hash_combine(42, 43), hash_value(std::make_pair(42, 43))); + EXPECT_NE(hash_combine(43, 42), hash_value(std::make_pair(42, 43))); + EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43ull))); + EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42, 43ull))); + EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43))); + + // Note that pairs are implicitly flattened to a direct sequence of data and + // hashed efficiently as a consequence. + EXPECT_EQ(hash_combine(42, 43, 44), + hash_value(std::make_pair(42, std::make_pair(43, 44)))); + EXPECT_EQ(hash_value(std::make_pair(42, std::make_pair(43, 44))), + hash_value(std::make_pair(std::make_pair(42, 43), 44))); + + // Ensure that pairs which have padding bytes *inside* them don't get treated + // this way. + EXPECT_EQ(hash_combine('0', hash_combine(1ull, '2')), + hash_value(std::make_pair('0', std::make_pair(1ull, '2')))); + + // Ensure that non-POD pairs don't explode the traits used. + NonPOD obj1(1, 2), obj2(3, 4), obj3(5, 6); + EXPECT_EQ(hash_combine(obj1, hash_combine(obj2, obj3)), + hash_value(std::make_pair(obj1, std::make_pair(obj2, obj3)))); +} + +TEST(HashingTest, HashValueStdString) { + std::string s = "Hello World!"; + EXPECT_EQ(hash_combine_range(s.c_str(), s.c_str() + s.size()), hash_value(s)); + EXPECT_EQ(hash_combine_range(s.c_str(), s.c_str() + s.size() - 1), + hash_value(s.substr(0, s.size() - 1))); + EXPECT_EQ(hash_combine_range(s.c_str() + 1, s.c_str() + s.size() - 1), + hash_value(s.substr(1, s.size() - 2))); + + std::wstring ws = L"Hello Wide World!"; + EXPECT_EQ(hash_combine_range(ws.c_str(), ws.c_str() + ws.size()), + hash_value(ws)); + EXPECT_EQ(hash_combine_range(ws.c_str(), ws.c_str() + ws.size() - 1), + hash_value(ws.substr(0, ws.size() - 1))); + EXPECT_EQ(hash_combine_range(ws.c_str() + 1, ws.c_str() + ws.size() - 1), + hash_value(ws.substr(1, ws.size() - 2))); +} + +template <typename T, size_t N> T *begin(T (&arr)[N]) { return arr; } +template <typename T, size_t N> T *end(T (&arr)[N]) { return arr + N; } + +// Provide a dummy, hashable type designed for easy verification: its hash is +// the same as its value. +struct HashableDummy { size_t value; }; +hash_code hash_value(HashableDummy dummy) { return dummy.value; } + +TEST(HashingTest, HashCombineRangeBasicTest) { + // Leave this uninitialized in the hope that valgrind will catch bad reads. + int dummy; + hash_code dummy_hash = hash_combine_range(&dummy, &dummy); + EXPECT_NE(hash_code(0), dummy_hash); + + const int arr1[] = { 1, 2, 3 }; + hash_code arr1_hash = hash_combine_range(begin(arr1), end(arr1)); + EXPECT_NE(dummy_hash, arr1_hash); + EXPECT_EQ(arr1_hash, hash_combine_range(begin(arr1), end(arr1))); + + const std::vector<int> vec(begin(arr1), end(arr1)); + EXPECT_EQ(arr1_hash, hash_combine_range(vec.begin(), vec.end())); + + const std::list<int> list(begin(arr1), end(arr1)); + EXPECT_EQ(arr1_hash, hash_combine_range(list.begin(), list.end())); + + const std::deque<int> deque(begin(arr1), end(arr1)); + EXPECT_EQ(arr1_hash, hash_combine_range(deque.begin(), deque.end())); + + const int arr2[] = { 3, 2, 1 }; + hash_code arr2_hash = hash_combine_range(begin(arr2), end(arr2)); + EXPECT_NE(dummy_hash, arr2_hash); + EXPECT_NE(arr1_hash, arr2_hash); + + const int arr3[] = { 1, 1, 2, 3 }; + hash_code arr3_hash = hash_combine_range(begin(arr3), end(arr3)); + EXPECT_NE(dummy_hash, arr3_hash); + EXPECT_NE(arr1_hash, arr3_hash); + + const int arr4[] = { 1, 2, 3, 3 }; + hash_code arr4_hash = hash_combine_range(begin(arr4), end(arr4)); + EXPECT_NE(dummy_hash, arr4_hash); + EXPECT_NE(arr1_hash, arr4_hash); + + const size_t arr5[] = { 1, 2, 3 }; + const HashableDummy d_arr5[] = { {1}, {2}, {3} }; + hash_code arr5_hash = hash_combine_range(begin(arr5), end(arr5)); + hash_code d_arr5_hash = hash_combine_range(begin(d_arr5), end(d_arr5)); + EXPECT_EQ(arr5_hash, d_arr5_hash); +} + +TEST(HashingTest, HashCombineRangeLengthDiff) { + // Test that as only the length varies, we compute different hash codes for + // sequences. + std::map<size_t, size_t> code_to_size; + std::vector<char> all_one_c(256, '\xff'); + for (unsigned Idx = 1, Size = all_one_c.size(); Idx < Size; ++Idx) { + hash_code code = hash_combine_range(&all_one_c[0], &all_one_c[0] + Idx); + std::map<size_t, size_t>::iterator + I = code_to_size.insert(std::make_pair(code, Idx)).first; + EXPECT_EQ(Idx, I->second); + } + code_to_size.clear(); + std::vector<char> all_zero_c(256, '\0'); + for (unsigned Idx = 1, Size = all_zero_c.size(); Idx < Size; ++Idx) { + hash_code code = hash_combine_range(&all_zero_c[0], &all_zero_c[0] + Idx); + std::map<size_t, size_t>::iterator + I = code_to_size.insert(std::make_pair(code, Idx)).first; + EXPECT_EQ(Idx, I->second); + } + code_to_size.clear(); + std::vector<unsigned> all_one_int(512, -1); + for (unsigned Idx = 1, Size = all_one_int.size(); Idx < Size; ++Idx) { + hash_code code = hash_combine_range(&all_one_int[0], &all_one_int[0] + Idx); + std::map<size_t, size_t>::iterator + I = code_to_size.insert(std::make_pair(code, Idx)).first; + EXPECT_EQ(Idx, I->second); + } + code_to_size.clear(); + std::vector<unsigned> all_zero_int(512, 0); + for (unsigned Idx = 1, Size = all_zero_int.size(); Idx < Size; ++Idx) { + hash_code code = hash_combine_range(&all_zero_int[0], &all_zero_int[0] + Idx); + std::map<size_t, size_t>::iterator + I = code_to_size.insert(std::make_pair(code, Idx)).first; + EXPECT_EQ(Idx, I->second); + } +} + +TEST(HashingTest, HashCombineRangeGoldenTest) { + struct { const char *s; uint64_t hash; } golden_data[] = { +#if SIZE_MAX == UINT64_MAX + { "a", 0xaeb6f9d5517c61f8ULL }, + { "ab", 0x7ab1edb96be496b4ULL }, + { "abc", 0xe38e60bf19c71a3fULL }, + { "abcde", 0xd24461a66de97f6eULL }, + { "abcdefgh", 0x4ef872ec411dec9dULL }, + { "abcdefghijklm", 0xe8a865539f4eadfeULL }, + { "abcdefghijklmnopqrstu", 0x261cdf85faaf4e79ULL }, + { "abcdefghijklmnopqrstuvwxyzabcdef", 0x43ba70e4198e3b2aULL }, + { "abcdefghijklmnopqrstuvwxyzabcdef" + "abcdefghijklmnopqrstuvwxyzghijkl" + "abcdefghijklmnopqrstuvwxyzmnopqr" + "abcdefghijklmnopqrstuvwxyzstuvwx" + "abcdefghijklmnopqrstuvwxyzyzabcd", 0xdcd57fb2afdf72beULL }, + { "a", 0xaeb6f9d5517c61f8ULL }, + { "aa", 0xf2b3b69a9736a1ebULL }, + { "aaa", 0xf752eb6f07b1cafeULL }, + { "aaaaa", 0x812bd21e1236954cULL }, + { "aaaaaaaa", 0xff07a2cff08ac587ULL }, + { "aaaaaaaaaaaaa", 0x84ac949d54d704ecULL }, + { "aaaaaaaaaaaaaaaaaaaaa", 0xcb2c8fb6be8f5648ULL }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xcc40ab7f164091b6ULL }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xc58e174c1e78ffe9ULL }, + { "z", 0x1ba160d7e8f8785cULL }, + { "zz", 0x2c5c03172f1285d7ULL }, + { "zzz", 0x9d2c4f4b507a2ac3ULL }, + { "zzzzz", 0x0f03b9031735693aULL }, + { "zzzzzzzz", 0xe674147c8582c08eULL }, + { "zzzzzzzzzzzzz", 0x3162d9fa6938db83ULL }, + { "zzzzzzzzzzzzzzzzzzzzz", 0x37b9a549e013620cULL }, + { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x8921470aff885016ULL }, + { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0xf60fdcd9beb08441ULL }, + { "a", 0xaeb6f9d5517c61f8ULL }, + { "ab", 0x7ab1edb96be496b4ULL }, + { "aba", 0x3edb049950884d0aULL }, + { "ababa", 0x8f2de9e73a97714bULL }, + { "abababab", 0xee14a29ddf0ce54cULL }, + { "ababababababa", 0x38b3ddaada2d52b4ULL }, + { "ababababababababababa", 0xd3665364219f2b85ULL }, + { "abababababababababababababababab", 0xa75cd6afbf1bc972ULL }, + { "abababababababababababababababab" + "abababababababababababababababab" + "abababababababababababababababab" + "abababababababababababababababab" + "abababababababababababababababab", 0x840192d129f7a22bULL } +#elif SIZE_MAX == UINT32_MAX + { "a", 0x000000004605f745ULL }, + { "ab", 0x00000000d5f06301ULL }, + { "abc", 0x00000000559fe1eeULL }, + { "abcde", 0x00000000424028d7ULL }, + { "abcdefgh", 0x000000007bb119f8ULL }, + { "abcdefghijklm", 0x00000000edbca513ULL }, + { "abcdefghijklmnopqrstu", 0x000000007c15712eULL }, + { "abcdefghijklmnopqrstuvwxyzabcdef", 0x000000000b3aad66ULL }, + { "abcdefghijklmnopqrstuvwxyzabcdef" + "abcdefghijklmnopqrstuvwxyzghijkl" + "abcdefghijklmnopqrstuvwxyzmnopqr" + "abcdefghijklmnopqrstuvwxyzstuvwx" + "abcdefghijklmnopqrstuvwxyzyzabcd", 0x000000008c758c8bULL }, + { "a", 0x000000004605f745ULL }, + { "aa", 0x00000000dc0a52daULL }, + { "aaa", 0x00000000b309274fULL }, + { "aaaaa", 0x00000000203b5ef6ULL }, + { "aaaaaaaa", 0x00000000a429e18fULL }, + { "aaaaaaaaaaaaa", 0x000000008662070bULL }, + { "aaaaaaaaaaaaaaaaaaaaa", 0x000000003f11151cULL }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x000000008600fe20ULL }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x000000004e0e0804ULL }, + { "z", 0x00000000c5e405e9ULL }, + { "zz", 0x00000000a8d8a2c6ULL }, + { "zzz", 0x00000000fc2af672ULL }, + { "zzzzz", 0x0000000047d9efe6ULL }, + { "zzzzzzzz", 0x0000000080d77794ULL }, + { "zzzzzzzzzzzzz", 0x00000000405f93adULL }, + { "zzzzzzzzzzzzzzzzzzzzz", 0x00000000fc72838dULL }, + { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x000000007ce160f1ULL }, + { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x00000000aed9ed1bULL }, + { "a", 0x000000004605f745ULL }, + { "ab", 0x00000000d5f06301ULL }, + { "aba", 0x00000000a85cd91bULL }, + { "ababa", 0x000000009e3bb52eULL }, + { "abababab", 0x000000002709b3b9ULL }, + { "ababababababa", 0x000000003a234174ULL }, + { "ababababababababababa", 0x000000005c63e5ceULL }, + { "abababababababababababababababab", 0x0000000013f74334ULL }, + { "abababababababababababababababab" + "abababababababababababababababab" + "abababababababababababababababab" + "abababababababababababababababab" + "abababababababababababababababab", 0x00000000c1a6f135ULL }, +#else +#error This test only supports 64-bit and 32-bit systems. +#endif + }; + for (unsigned i = 0; i < sizeof(golden_data)/sizeof(*golden_data); ++i) { + StringRef str = golden_data[i].s; + hash_code hash = hash_combine_range(str.begin(), str.end()); +#if 0 // Enable this to generate paste-able text for the above structure. + std::string member_str = "\"" + str.str() + "\","; + fprintf(stderr, " { %-35s 0x%016llxULL },\n", + member_str.c_str(), static_cast<uint64_t>(hash)); +#endif + EXPECT_EQ(static_cast<size_t>(golden_data[i].hash), + static_cast<size_t>(hash)); + } +} + +TEST(HashingTest, HashCombineBasicTest) { + // Hashing a sequence of homogenous types matches range hashing. + const int i1 = 42, i2 = 43, i3 = 123, i4 = 999, i5 = 0, i6 = 79; + const int arr1[] = { i1, i2, i3, i4, i5, i6 }; + EXPECT_EQ(hash_combine_range(arr1, arr1 + 1), hash_combine(i1)); + EXPECT_EQ(hash_combine_range(arr1, arr1 + 2), hash_combine(i1, i2)); + EXPECT_EQ(hash_combine_range(arr1, arr1 + 3), hash_combine(i1, i2, i3)); + EXPECT_EQ(hash_combine_range(arr1, arr1 + 4), hash_combine(i1, i2, i3, i4)); + EXPECT_EQ(hash_combine_range(arr1, arr1 + 5), + hash_combine(i1, i2, i3, i4, i5)); + EXPECT_EQ(hash_combine_range(arr1, arr1 + 6), + hash_combine(i1, i2, i3, i4, i5, i6)); + + // Hashing a sequence of heterogenous types which *happen* to all produce the + // same data for hashing produces the same as a range-based hash of the + // fundamental values. + const size_t s1 = 1024, s2 = 8888, s3 = 9000000; + const HashableDummy d1 = { 1024 }, d2 = { 8888 }, d3 = { 9000000 }; + const size_t arr2[] = { s1, s2, s3 }; + EXPECT_EQ(hash_combine_range(begin(arr2), end(arr2)), + hash_combine(s1, s2, s3)); + EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, s2, d3)); + EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, d2, s3)); + EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, s2, s3)); + EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, s3)); + EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, d3)); + + // Permuting values causes hashes to change. + EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i1, i2)); + EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i2, i1)); + EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i1, i1)); + EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i1)); + EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i2)); + EXPECT_NE(hash_combine(i2, i1, i1), hash_combine(i1, i1, i2)); + EXPECT_NE(hash_combine(i1, i1, i2), hash_combine(i1, i2, i1)); + EXPECT_NE(hash_combine(i1, i2, i1), hash_combine(i2, i1, i1)); + + // Changing type w/o changing value causes hashes to change. + EXPECT_NE(hash_combine(i1, i2, i3), hash_combine((char)i1, i2, i3)); + EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, (char)i2, i3)); + EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, i2, (char)i3)); + + // This is array of uint64, but it should have the exact same byte pattern as + // an array of LargeTestIntegers. + const uint64_t bigarr[] = { + 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, + 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL, + 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL, + 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, + 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL, + 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL, + 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, + 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL, + 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL + }; + // Hash a preposterously large integer, both aligned with the buffer and + // misaligned. + const LargeTestInteger li = { { + 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, + 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL, + 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL + } }; + // Rotate the storage from 'li'. + const LargeTestInteger l2 = { { + 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL, + 0xfefefefededededeULL, 0xafafafafededededULL, 0xffffeeeeddddccccULL, + 0xaaaacbcbffffababULL, 0xaaaaaaaaababababULL + } }; + const LargeTestInteger l3 = { { + 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, + 0xafafafafededededULL, 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL, + 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL + } }; + EXPECT_EQ(hash_combine_range(begin(bigarr), end(bigarr)), + hash_combine(li, li, li)); + EXPECT_EQ(hash_combine_range(bigarr, bigarr + 9), + hash_combine(bigarr[0], l2)); + EXPECT_EQ(hash_combine_range(bigarr, bigarr + 10), + hash_combine(bigarr[0], bigarr[1], l3)); + EXPECT_EQ(hash_combine_range(bigarr, bigarr + 17), + hash_combine(li, bigarr[0], l2)); + EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18), + hash_combine(li, bigarr[0], bigarr[1], l3)); + EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18), + hash_combine(bigarr[0], l2, bigarr[9], l3)); + EXPECT_EQ(hash_combine_range(bigarr, bigarr + 20), + hash_combine(bigarr[0], l2, bigarr[9], l3, bigarr[18], bigarr[19])); +} + +} diff --git a/unittests/ADT/IntrusiveRefCntPtrTest.cpp b/unittests/ADT/IntrusiveRefCntPtrTest.cpp new file mode 100644 index 000000000000..0c8c4ca16dd7 --- /dev/null +++ b/unittests/ADT/IntrusiveRefCntPtrTest.cpp @@ -0,0 +1,64 @@ +//===- unittest/ADT/IntrusiveRefCntPtrTest.cpp ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "gtest/gtest.h" + +namespace llvm { + +struct VirtualRefCounted : public RefCountedBaseVPTR { + virtual void f() {} +}; + +// Run this test with valgrind to detect memory leaks. +TEST(IntrusiveRefCntPtr, RefCountedBaseVPTRCopyDoesNotLeak) { + VirtualRefCounted *V1 = new VirtualRefCounted; + IntrusiveRefCntPtr<VirtualRefCounted> R1 = V1; + VirtualRefCounted *V2 = new VirtualRefCounted(*V1); + IntrusiveRefCntPtr<VirtualRefCounted> R2 = V2; +} + +struct SimpleRefCounted : public RefCountedBase<SimpleRefCounted> {}; + +// Run this test with valgrind to detect memory leaks. +TEST(IntrusiveRefCntPtr, RefCountedBaseCopyDoesNotLeak) { + SimpleRefCounted *S1 = new SimpleRefCounted; + IntrusiveRefCntPtr<SimpleRefCounted> R1 = S1; + SimpleRefCounted *S2 = new SimpleRefCounted(*S1); + IntrusiveRefCntPtr<SimpleRefCounted> R2 = S2; +} + +struct InterceptRefCounted : public RefCountedBase<InterceptRefCounted> { + InterceptRefCounted(bool *Released, bool *Retained) + : Released(Released), Retained(Retained) {} + bool * const Released; + bool * const Retained; +}; +template <> struct IntrusiveRefCntPtrInfo<InterceptRefCounted> { + static void retain(InterceptRefCounted *I) { + *I->Retained = true; + I->Retain(); + } + static void release(InterceptRefCounted *I) { + *I->Released = true; + I->Release(); + } +}; +TEST(IntrusiveRefCntPtr, UsesTraitsToRetainAndRelease) { + bool Released = false; + bool Retained = false; + { + InterceptRefCounted *I = new InterceptRefCounted(&Released, &Retained); + IntrusiveRefCntPtr<InterceptRefCounted> R = I; + } + EXPECT_TRUE(Released); + EXPECT_TRUE(Retained); +} + +} // end namespace llvm diff --git a/unittests/ADT/SmallPtrSetTest.cpp b/unittests/ADT/SmallPtrSetTest.cpp new file mode 100644 index 000000000000..9114875e0035 --- /dev/null +++ b/unittests/ADT/SmallPtrSetTest.cpp @@ -0,0 +1,72 @@ +//===- llvm/unittest/ADT/SmallPtrSetTest.cpp ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// SmallPtrSet unit tests. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/SmallPtrSet.h" + +using namespace llvm; + +// SmallPtrSet swapping test. +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]); + + std::swap(a, b); + + EXPECT_EQ(1U, a.size()); + EXPECT_EQ(2U, b.size()); + EXPECT_TRUE(a.count(&buf[2])); + EXPECT_TRUE(b.count(&buf[0])); + EXPECT_TRUE(b.count(&buf[1])); + + 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_TRUE(a.count(&buf[3])); + EXPECT_TRUE(b.count(&buf[2])); + + std::swap(a, b); + + EXPECT_EQ(1U, a.size()); + EXPECT_EQ(3U, b.size()); + EXPECT_TRUE(a.count(&buf[2])); + EXPECT_TRUE(b.count(&buf[0])); + EXPECT_TRUE(b.count(&buf[1])); + 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])); +} diff --git a/unittests/ADT/SmallStringTest.cpp b/unittests/ADT/SmallStringTest.cpp index 099d8159c917..660ac44a8bca 100644 --- a/unittests/ADT/SmallStringTest.cpp +++ b/unittests/ADT/SmallStringTest.cpp @@ -44,5 +44,153 @@ TEST_F(SmallStringTest, EmptyStringTest) { 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) { + StringRef abc = "abc"; + theString.assign(abc.begin(), abc.end()); + EXPECT_EQ(3u, theString.size()); + EXPECT_STREQ("abc", theString.c_str()); +} + +TEST_F(SmallStringTest, AssignStringRef) { + StringRef abc = "abc"; + theString.assign(abc); + EXPECT_EQ(3u, theString.size()); + EXPECT_STREQ("abc", theString.c_str()); +} + +TEST_F(SmallStringTest, AssignSmallVector) { + StringRef 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, AppendIterPair) { + StringRef 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, AppendStringRef) { + StringRef abc = "abc"; + theString.append(abc); + theString.append(abc); + EXPECT_EQ(6u, theString.size()); + EXPECT_STREQ("abcabc", theString.c_str()); +} + +TEST_F(SmallStringTest, AppendSmallVector) { + StringRef 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, Substr) { + theString = "hello"; + EXPECT_EQ("lo", theString.substr(3)); + EXPECT_EQ("", theString.substr(100)); + EXPECT_EQ("hello", theString.substr(0, 100)); + EXPECT_EQ("o", theString.substr(4, 10)); +} + +TEST_F(SmallStringTest, Slice) { + theString = "hello"; + EXPECT_EQ("l", theString.slice(2, 3)); + EXPECT_EQ("ell", theString.slice(1, 4)); + EXPECT_EQ("llo", theString.slice(2, 100)); + EXPECT_EQ("", theString.slice(2, 1)); + EXPECT_EQ("", theString.slice(10, 20)); +} + +TEST_F(SmallStringTest, Find) { + theString = "hello"; + EXPECT_EQ(2U, theString.find('l')); + EXPECT_EQ(StringRef::npos, theString.find('z')); + EXPECT_EQ(StringRef::npos, theString.find("helloworld")); + EXPECT_EQ(0U, theString.find("hello")); + EXPECT_EQ(1U, theString.find("ello")); + EXPECT_EQ(StringRef::npos, theString.find("zz")); + EXPECT_EQ(2U, theString.find("ll", 2)); + EXPECT_EQ(StringRef::npos, theString.find("ll", 3)); + EXPECT_EQ(0U, theString.find("")); + + EXPECT_EQ(3U, theString.rfind('l')); + EXPECT_EQ(StringRef::npos, theString.rfind('z')); + EXPECT_EQ(StringRef::npos, theString.rfind("helloworld")); + EXPECT_EQ(0U, theString.rfind("hello")); + EXPECT_EQ(1U, theString.rfind("ello")); + EXPECT_EQ(StringRef::npos, theString.rfind("zz")); + + EXPECT_EQ(2U, theString.find_first_of('l')); + EXPECT_EQ(1U, theString.find_first_of("el")); + EXPECT_EQ(StringRef::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(StringRef::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("")); +} + +TEST_F(SmallStringTest, Count) { + theString = "hello"; + EXPECT_EQ(2U, theString.count('l')); + EXPECT_EQ(1U, theString.count('o')); + EXPECT_EQ(0U, theString.count('z')); + EXPECT_EQ(0U, theString.count("helloworld")); + EXPECT_EQ(1U, theString.count("hello")); + EXPECT_EQ(1U, theString.count("ello")); + EXPECT_EQ(0U, theString.count("zz")); +} + +TEST(StringRefTest, Comparisons) { + EXPECT_EQ(-1, SmallString<10>("aab").compare("aad")); + EXPECT_EQ( 0, SmallString<10>("aab").compare("aab")); + EXPECT_EQ( 1, SmallString<10>("aab").compare("aaa")); + EXPECT_EQ(-1, SmallString<10>("aab").compare("aabb")); + EXPECT_EQ( 1, SmallString<10>("aab").compare("aa")); + EXPECT_EQ( 1, SmallString<10>("\xFF").compare("\1")); + + EXPECT_EQ(-1, SmallString<10>("AaB").compare_lower("aAd")); + EXPECT_EQ( 0, SmallString<10>("AaB").compare_lower("aab")); + EXPECT_EQ( 1, SmallString<10>("AaB").compare_lower("AAA")); + EXPECT_EQ(-1, SmallString<10>("AaB").compare_lower("aaBb")); + EXPECT_EQ( 1, SmallString<10>("AaB").compare_lower("aA")); + EXPECT_EQ( 1, SmallString<10>("\xFF").compare_lower("\1")); + + EXPECT_EQ(-1, SmallString<10>("aab").compare_numeric("aad")); + EXPECT_EQ( 0, SmallString<10>("aab").compare_numeric("aab")); + EXPECT_EQ( 1, SmallString<10>("aab").compare_numeric("aaa")); + EXPECT_EQ(-1, SmallString<10>("aab").compare_numeric("aabb")); + EXPECT_EQ( 1, SmallString<10>("aab").compare_numeric("aa")); + EXPECT_EQ(-1, SmallString<10>("1").compare_numeric("10")); + EXPECT_EQ( 0, SmallString<10>("10").compare_numeric("10")); + EXPECT_EQ( 0, SmallString<10>("10a").compare_numeric("10a")); + EXPECT_EQ( 1, SmallString<10>("2").compare_numeric("1")); + EXPECT_EQ( 0, SmallString<10>("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty")); + EXPECT_EQ( 1, SmallString<10>("\xFF").compare_numeric("\1")); + EXPECT_EQ( 1, SmallString<10>("V16").compare_numeric("V1_q0")); + EXPECT_EQ(-1, SmallString<10>("V1_q0").compare_numeric("V16")); + EXPECT_EQ(-1, SmallString<10>("V8_q0").compare_numeric("V16")); + EXPECT_EQ( 1, SmallString<10>("V16").compare_numeric("V8_q0")); + EXPECT_EQ(-1, SmallString<10>("V1_q0").compare_numeric("V8_q0")); + EXPECT_EQ( 1, SmallString<10>("V8_q0").compare_numeric("V1_q0")); +} + +} diff --git a/unittests/ADT/SparseSetTest.cpp b/unittests/ADT/SparseSetTest.cpp new file mode 100644 index 000000000000..a6ea7572ce44 --- /dev/null +++ b/unittests/ADT/SparseSetTest.cpp @@ -0,0 +1,186 @@ +//===------ ADT/SparseSetTest.cpp - SparseSet unit tests - -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SparseSet.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +typedef SparseSet<unsigned> USet; + +// Empty set tests. +TEST(SparseSetTest, EmptySet) { + USet Set; + EXPECT_TRUE(Set.empty()); + EXPECT_TRUE(Set.begin() == Set.end()); + EXPECT_EQ(0u, Set.size()); + + Set.setUniverse(10); + + // Lookups on empty set. + EXPECT_TRUE(Set.find(0) == Set.end()); + EXPECT_TRUE(Set.find(9) == Set.end()); + + // Same thing on a const reference. + const USet &CSet = Set; + EXPECT_TRUE(CSet.empty()); + EXPECT_TRUE(CSet.begin() == CSet.end()); + EXPECT_EQ(0u, CSet.size()); + EXPECT_TRUE(CSet.find(0) == CSet.end()); + USet::const_iterator I = CSet.find(5); + EXPECT_TRUE(I == CSet.end()); +} + +// Single entry set tests. +TEST(SparseSetTest, SingleEntrySet) { + USet Set; + Set.setUniverse(10); + std::pair<USet::iterator, bool> IP = Set.insert(5); + EXPECT_TRUE(IP.second); + EXPECT_TRUE(IP.first == Set.begin()); + + EXPECT_FALSE(Set.empty()); + EXPECT_FALSE(Set.begin() == Set.end()); + EXPECT_TRUE(Set.begin() + 1 == Set.end()); + EXPECT_EQ(1u, Set.size()); + + EXPECT_TRUE(Set.find(0) == Set.end()); + EXPECT_TRUE(Set.find(9) == Set.end()); + + EXPECT_FALSE(Set.count(0)); + EXPECT_TRUE(Set.count(5)); + + // Redundant insert. + IP = Set.insert(5); + EXPECT_FALSE(IP.second); + EXPECT_TRUE(IP.first == Set.begin()); + + // Erase non-existent element. + EXPECT_FALSE(Set.erase(1)); + EXPECT_EQ(1u, Set.size()); + EXPECT_EQ(5u, *Set.begin()); + + // Erase iterator. + USet::iterator I = Set.find(5); + EXPECT_TRUE(I == Set.begin()); + I = Set.erase(I); + EXPECT_TRUE(I == Set.end()); + EXPECT_TRUE(Set.empty()); +} + +// Multiple entry set tests. +TEST(SparseSetTest, MultipleEntrySet) { + USet Set; + Set.setUniverse(10); + + Set.insert(5); + Set.insert(3); + Set.insert(2); + Set.insert(1); + Set.insert(4); + EXPECT_EQ(5u, Set.size()); + + // Without deletions, iteration order == insertion order. + USet::const_iterator I = Set.begin(); + EXPECT_EQ(5u, *I); + ++I; + EXPECT_EQ(3u, *I); + ++I; + EXPECT_EQ(2u, *I); + ++I; + EXPECT_EQ(1u, *I); + ++I; + EXPECT_EQ(4u, *I); + ++I; + EXPECT_TRUE(I == Set.end()); + + // Redundant insert. + std::pair<USet::iterator, bool> IP = Set.insert(3); + EXPECT_FALSE(IP.second); + EXPECT_TRUE(IP.first == Set.begin() + 1); + + // Erase last element by key. + EXPECT_TRUE(Set.erase(4)); + EXPECT_EQ(4u, Set.size()); + EXPECT_FALSE(Set.count(4)); + EXPECT_FALSE(Set.erase(4)); + EXPECT_EQ(4u, Set.size()); + EXPECT_FALSE(Set.count(4)); + + // Erase first element by key. + EXPECT_TRUE(Set.count(5)); + EXPECT_TRUE(Set.find(5) == Set.begin()); + EXPECT_TRUE(Set.erase(5)); + EXPECT_EQ(3u, Set.size()); + EXPECT_FALSE(Set.count(5)); + EXPECT_FALSE(Set.erase(5)); + EXPECT_EQ(3u, Set.size()); + EXPECT_FALSE(Set.count(5)); + + Set.insert(6); + Set.insert(7); + EXPECT_EQ(5u, Set.size()); + + // Erase last element by iterator. + I = Set.erase(Set.end() - 1); + EXPECT_TRUE(I == Set.end()); + EXPECT_EQ(4u, Set.size()); + + // Erase second element by iterator. + I = Set.erase(Set.begin() + 1); + EXPECT_TRUE(I == Set.begin() + 1); + + // Clear and resize the universe. + Set.clear(); + EXPECT_FALSE(Set.count(5)); + Set.setUniverse(1000); + + // Add more than 256 elements. + for (unsigned i = 100; i != 800; ++i) + Set.insert(i); + + for (unsigned i = 0; i != 10; ++i) + Set.erase(i); + + for (unsigned i = 100; i != 800; ++i) + EXPECT_TRUE(Set.count(i)); + + EXPECT_FALSE(Set.count(99)); + EXPECT_FALSE(Set.count(800)); + EXPECT_EQ(700u, Set.size()); +} + +struct Alt { + unsigned Value; + explicit Alt(unsigned x) : Value(x) {} + unsigned getSparseSetKey() const { return Value - 1000; } +}; + +TEST(SparseSetTest, AltStructSet) { + typedef SparseSet<Alt> ASet; + ASet Set; + Set.setUniverse(10); + Set.insert(Alt(1005)); + + ASet::iterator I = Set.find(5); + ASSERT_TRUE(I == Set.begin()); + EXPECT_EQ(1005u, I->Value); + + Set.insert(Alt(1006)); + Set.insert(Alt(1006)); + I = Set.erase(Set.begin()); + ASSERT_TRUE(I == Set.begin()); + EXPECT_EQ(1006u, I->Value); + + EXPECT_FALSE(Set.erase(5)); + EXPECT_TRUE(Set.erase(6)); +} +} // namespace diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index 8364eac82748..cc7a7fbe332d 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -245,6 +246,12 @@ TEST(StringRefTest, Find) { EXPECT_EQ(StringRef::npos, Str.find("zz")); EXPECT_EQ(2U, Str.find("ll", 2)); EXPECT_EQ(StringRef::npos, Str.find("ll", 3)); + EXPECT_EQ(0U, Str.find("")); + StringRef LongStr("hellx xello hell ello world foo bar hello"); + EXPECT_EQ(36U, LongStr.find("hello")); + EXPECT_EQ(28U, LongStr.find("foo")); + EXPECT_EQ(12U, LongStr.find("hell", 2)); + EXPECT_EQ(0U, LongStr.find("")); EXPECT_EQ(3U, Str.rfind('l')); EXPECT_EQ(StringRef::npos, Str.rfind('z')); @@ -285,4 +292,140 @@ TEST(StringRefTest, Misc) { EXPECT_EQ("hello", OS.str()); } +TEST(StringRefTest, Hashing) { + EXPECT_EQ(hash_value(std::string()), hash_value(StringRef())); + EXPECT_EQ(hash_value(std::string()), hash_value(StringRef(""))); + std::string S = "hello world"; + hash_code H = hash_value(S); + EXPECT_EQ(H, hash_value(StringRef("hello world"))); + EXPECT_EQ(H, hash_value(StringRef(S))); + EXPECT_NE(H, hash_value(StringRef("hello worl"))); + EXPECT_EQ(hash_value(std::string("hello worl")), + hash_value(StringRef("hello worl"))); + EXPECT_NE(H, hash_value(StringRef("hello world "))); + EXPECT_EQ(hash_value(std::string("hello world ")), + hash_value(StringRef("hello world "))); + EXPECT_EQ(H, hash_value(StringRef("hello world\0"))); + EXPECT_NE(hash_value(std::string("ello worl")), + hash_value(StringRef("hello world").slice(1, -1))); +} + +struct UnsignedPair { + const char *Str; + uint64_t Expected; +} Unsigned[] = + { {"0", 0} + , {"255", 255} + , {"256", 256} + , {"65535", 65535} + , {"65536", 65536} + , {"4294967295", 4294967295ULL} + , {"4294967296", 4294967296ULL} + , {"18446744073709551615", 18446744073709551615ULL} + , {"042", 34} + , {"0x42", 66} + , {"0b101010", 42} + }; + +struct SignedPair { + const char *Str; + int64_t Expected; +} Signed[] = + { {"0", 0} + , {"-0", 0} + , {"127", 127} + , {"128", 128} + , {"-128", -128} + , {"-129", -129} + , {"32767", 32767} + , {"32768", 32768} + , {"-32768", -32768} + , {"-32769", -32769} + , {"2147483647", 2147483647LL} + , {"2147483648", 2147483648LL} + , {"-2147483648", -2147483648LL} + , {"-2147483649", -2147483649LL} + , {"-9223372036854775808", -(9223372036854775807LL) - 1} + , {"042", 34} + , {"0x42", 66} + , {"0b101010", 42} + , {"-042", -34} + , {"-0x42", -66} + , {"-0b101010", -42} + }; + +TEST(StringRefTest, getAsInteger) { + uint8_t U8; + uint16_t U16; + uint32_t U32; + uint64_t U64; + + for (size_t i = 0; i < array_lengthof(Unsigned); ++i) { + bool U8Success = StringRef(Unsigned[i].Str).getAsInteger(0, U8); + if (static_cast<uint8_t>(Unsigned[i].Expected) == Unsigned[i].Expected) { + ASSERT_FALSE(U8Success); + EXPECT_EQ(U8, Unsigned[i].Expected); + } else { + ASSERT_TRUE(U8Success); + } + bool U16Success = StringRef(Unsigned[i].Str).getAsInteger(0, U16); + if (static_cast<uint16_t>(Unsigned[i].Expected) == Unsigned[i].Expected) { + ASSERT_FALSE(U16Success); + EXPECT_EQ(U16, Unsigned[i].Expected); + } else { + ASSERT_TRUE(U16Success); + } + bool U32Success = StringRef(Unsigned[i].Str).getAsInteger(0, U32); + if (static_cast<uint32_t>(Unsigned[i].Expected) == Unsigned[i].Expected) { + ASSERT_FALSE(U32Success); + EXPECT_EQ(U32, Unsigned[i].Expected); + } else { + ASSERT_TRUE(U32Success); + } + bool U64Success = StringRef(Unsigned[i].Str).getAsInteger(0, U64); + if (static_cast<uint64_t>(Unsigned[i].Expected) == Unsigned[i].Expected) { + ASSERT_FALSE(U64Success); + EXPECT_EQ(U64, Unsigned[i].Expected); + } else { + ASSERT_TRUE(U64Success); + } + } + + int8_t S8; + int16_t S16; + int32_t S32; + int64_t S64; + + for (size_t i = 0; i < array_lengthof(Signed); ++i) { + bool S8Success = StringRef(Signed[i].Str).getAsInteger(0, S8); + if (static_cast<int8_t>(Signed[i].Expected) == Signed[i].Expected) { + ASSERT_FALSE(S8Success); + EXPECT_EQ(S8, Signed[i].Expected); + } else { + ASSERT_TRUE(S8Success); + } + bool S16Success = StringRef(Signed[i].Str).getAsInteger(0, S16); + if (static_cast<int16_t>(Signed[i].Expected) == Signed[i].Expected) { + ASSERT_FALSE(S16Success); + EXPECT_EQ(S16, Signed[i].Expected); + } else { + ASSERT_TRUE(S16Success); + } + bool S32Success = StringRef(Signed[i].Str).getAsInteger(0, S32); + if (static_cast<int32_t>(Signed[i].Expected) == Signed[i].Expected) { + ASSERT_FALSE(S32Success); + EXPECT_EQ(S32, Signed[i].Expected); + } else { + ASSERT_TRUE(S32Success); + } + bool S64Success = StringRef(Signed[i].Str).getAsInteger(0, S64); + if (static_cast<int64_t>(Signed[i].Expected) == Signed[i].Expected) { + ASSERT_FALSE(S64Success); + EXPECT_EQ(S64, Signed[i].Expected); + } else { + ASSERT_TRUE(S64Success); + } + } +} + } // end anonymous namespace diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index 160b69253b6f..479046e01d7f 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -87,6 +87,24 @@ TEST(TripleTest, ParsedIDs) { EXPECT_EQ(Triple::Linux, T.getOS()); EXPECT_EQ(Triple::GNU, T.getEnvironment()); + T = Triple("powerpc-bgp-linux"); + EXPECT_EQ(Triple::ppc, T.getArch()); + EXPECT_EQ(Triple::BGP, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + + T = Triple("powerpc-bgp-cnk"); + EXPECT_EQ(Triple::ppc, T.getArch()); + EXPECT_EQ(Triple::BGP, T.getVendor()); + EXPECT_EQ(Triple::CNK, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + + T = Triple("powerpc64-bgq-linux"); + EXPECT_EQ(Triple::ppc64, T.getArch()); + EXPECT_EQ(Triple::BGQ, T.getVendor()); + EXPECT_EQ(Triple::Linux, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + T = Triple("powerpc-dunno-notsure"); EXPECT_EQ(Triple::ppc, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); @@ -154,7 +172,7 @@ TEST(TripleTest, Normalization) { // Check that normalizing a permutated set of valid components returns a // triple with the unpermuted components. StringRef C[4]; - for (int Arch = 1+Triple::UnknownArch; Arch < Triple::InvalidArch; ++Arch) { + for (int Arch = 1+Triple::UnknownArch; Arch <= Triple::amdil; ++Arch) { C[0] = Triple::getArchTypeName(Triple::ArchType(Arch)); for (int Vendor = 1+Triple::UnknownVendor; Vendor <= Triple::PC; ++Vendor) { @@ -162,12 +180,6 @@ TEST(TripleTest, Normalization) { for (int OS = 1+Triple::UnknownOS; OS <= Triple::Minix; ++OS) { C[2] = Triple::getOSTypeName(Triple::OSType(OS)); - // If a value has multiple interpretations, then the permutation - // test will inevitably fail. Currently this is only the case for - // "psp" which parses as both an architecture and an O/S. - if (OS == Triple::Psp) - continue; - std::string E = Join(C[0], C[1], C[2]); EXPECT_EQ(E, Triple::normalize(Join(C[0], C[1], C[2]))); @@ -212,9 +224,6 @@ TEST(TripleTest, Normalization) { } } - EXPECT_EQ("a-b-psp", Triple::normalize("a-b-psp")); - EXPECT_EQ("psp-b-c", Triple::normalize("psp-b-c")); - // Various real-world funky triples. The value returned by GCC's config.sub // is given in the comment. EXPECT_EQ("i386--mingw32", Triple::normalize("i386-mingw32")); // i386-pc-mingw32 @@ -267,4 +276,118 @@ TEST(TripleTest, MutateName) { } +TEST(TripleTest, BitWidthPredicates) { + Triple T; + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::arm); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::hexagon); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::mips); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::mips64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::msp430); + EXPECT_TRUE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::ppc); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::ppc64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::x86); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::x86_64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); +} + +TEST(TripleTest, BitWidthArchVariants) { + Triple T; + EXPECT_EQ(Triple::UnknownArch, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::UnknownArch); + EXPECT_EQ(Triple::UnknownArch, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::arm); + EXPECT_EQ(Triple::arm, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::mips); + EXPECT_EQ(Triple::mips, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::mips64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::mipsel); + EXPECT_EQ(Triple::mipsel, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::mips64el, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::ppc); + EXPECT_EQ(Triple::ppc, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::ppc64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::ptx32); + EXPECT_EQ(Triple::ptx32, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::ptx64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::sparc); + EXPECT_EQ(Triple::sparc, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::sparcv9, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::x86); + EXPECT_EQ(Triple::x86, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::x86_64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::mips64); + EXPECT_EQ(Triple::mips, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::mips64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::mips64el); + EXPECT_EQ(Triple::mipsel, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::mips64el, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::ppc64); + EXPECT_EQ(Triple::ppc, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::ppc64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::ptx64); + EXPECT_EQ(Triple::ptx32, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::ptx64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::sparcv9); + EXPECT_EQ(Triple::sparc, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::sparcv9, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::x86_64); + EXPECT_EQ(Triple::x86, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::x86_64, T.get64BitArchVariant().getArch()); +} + } diff --git a/unittests/ADT/VariadicFunctionTest.cpp b/unittests/ADT/VariadicFunctionTest.cpp new file mode 100644 index 000000000000..cde31205966c --- /dev/null +++ b/unittests/ADT/VariadicFunctionTest.cpp @@ -0,0 +1,110 @@ +//===----------- VariadicFunctionTest.cpp - VariadicFunction unit tests ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/VariadicFunction.h" + +using namespace llvm; +namespace { + +// Defines a variadic function StringCat() to join strings. +// StringCat()'s arguments and return value have class types. +std::string StringCatImpl(ArrayRef<const std::string *> Args) { + std::string S; + for (unsigned i = 0, e = Args.size(); i < e; ++i) + S += *Args[i]; + return S; +} +const VariadicFunction<std::string, std::string, StringCatImpl> StringCat = {}; + +TEST(VariadicFunctionTest, WorksForClassTypes) { + EXPECT_EQ("", StringCat()); + EXPECT_EQ("a", StringCat("a")); + EXPECT_EQ("abc", StringCat("a", "bc")); + EXPECT_EQ("0123456789abcdefghijklmnopqrstuv", + StringCat("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", + "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", + "u", "v")); +} + +// Defines a variadic function Sum(), whose arguments and return value +// have primitive types. +// The return type of SumImp() is deliberately different from its +// argument type, as we want to test that this works. +long SumImpl(ArrayRef<const int *> Args) { + long Result = 0; + for (unsigned i = 0, e = Args.size(); i < e; ++i) + Result += *Args[i]; + return Result; +} +const VariadicFunction<long, int, SumImpl> Sum = {}; + +TEST(VariadicFunctionTest, WorksForPrimitiveTypes) { + EXPECT_EQ(0, Sum()); + EXPECT_EQ(1, Sum(1)); + EXPECT_EQ(12, Sum(10, 2)); + EXPECT_EQ(1234567, Sum(1000000, 200000, 30000, 4000, 500, 60, 7)); +} + +// Appends an array of strings to dest and returns the number of +// characters appended. +int StringAppendImpl(std::string *Dest, ArrayRef<const std::string *> Args) { + int Chars = 0; + for (unsigned i = 0, e = Args.size(); i < e; ++i) { + Chars += Args[i]->size(); + *Dest += *Args[i]; + } + return Chars; +} +const VariadicFunction1<int, std::string *, std::string, + StringAppendImpl> StringAppend = {}; + +TEST(VariadicFunction1Test, Works) { + std::string S0("hi"); + EXPECT_EQ(0, StringAppend(&S0)); + EXPECT_EQ("hi", S0); + + std::string S1("bin"); + EXPECT_EQ(2, StringAppend(&S1, "go")); + EXPECT_EQ("bingo", S1); + + std::string S4("Fab4"); + EXPECT_EQ(4 + 4 + 6 + 5, + StringAppend(&S4, "John", "Paul", "George", "Ringo")); + EXPECT_EQ("Fab4JohnPaulGeorgeRingo", S4); +} + +// Counts how many optional arguments fall in the given range. +// Returns the result in *num_in_range. We make the return type void +// as we want to test that VariadicFunction* can handle it. +void CountInRangeImpl(int *NumInRange, int Low, int High, + ArrayRef<const int *> Args) { + *NumInRange = 0; + for (unsigned i = 0, e = Args.size(); i < e; ++i) + if (Low <= *Args[i] && *Args[i] <= High) + ++(*NumInRange); +} +const VariadicFunction3<void, int *, int, int, int, + CountInRangeImpl> CountInRange = {}; + +TEST(VariadicFunction3Test, Works) { + int N = -1; + CountInRange(&N, -100, 100); + EXPECT_EQ(0, N); + + CountInRange(&N, -100, 100, 42); + EXPECT_EQ(1, N); + + CountInRange(&N, -100, 100, 1, 999, -200, 42); + EXPECT_EQ(2, N); +} + +} // namespace |