Skip to content

Commit f35d060

Browse files
committed
[test][sanitizer] Add ArrayRef tests
Tests are subset of llvm/unittests/ADT/ArrayRefTest.cpp. Added more members to match tests and make class more useful. Reviewed By: hctim Differential Revision: https://reviews.llvm.org/D152760
1 parent bd66f4b commit f35d060

File tree

3 files changed

+226
-4
lines changed

3 files changed

+226
-4
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_array_ref.h

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,20 @@ namespace __sanitizer {
2727
template <typename T>
2828
class ArrayRef {
2929
public:
30-
ArrayRef() {}
31-
ArrayRef(const T *begin, const T *end) : begin_(begin), end_(end) {}
32-
30+
constexpr ArrayRef() {}
31+
constexpr ArrayRef(const T *begin, const T *end) : begin_(begin), end_(end) {
32+
DCHECK(empty() || begin);
33+
}
34+
constexpr ArrayRef(const T *data, uptr length)
35+
: ArrayRef(data, data + length) {}
36+
template <uptr N>
37+
constexpr ArrayRef(const T (&src)[N]) : ArrayRef(src, src + N) {}
3338
template <typename C>
34-
ArrayRef(const C &src) : ArrayRef(src.data(), src.data() + src.size()) {}
39+
constexpr ArrayRef(const C &src)
40+
: ArrayRef(src.data(), src.data() + src.size()) {}
41+
ArrayRef(const T &one_elt) : ArrayRef(&one_elt, &one_elt + 1) {}
42+
43+
const T *data() const { return empty() ? nullptr : begin_; }
3544

3645
const T *begin() const { return begin_; }
3746
const T *end() const { return end_; }
@@ -40,11 +49,75 @@ class ArrayRef {
4049

4150
uptr size() const { return end_ - begin_; }
4251

52+
/// equals - Check for element-wise equality.
53+
bool equals(ArrayRef rhs) const {
54+
if (size() != rhs.size())
55+
return false;
56+
auto r = rhs.begin();
57+
for (auto &l : *this) {
58+
if (!(l == *r))
59+
return false;
60+
++r;
61+
}
62+
return true;
63+
}
64+
65+
/// slice(n, m) - Chop off the first N elements of the array, and keep M
66+
/// elements in the array.
67+
ArrayRef<T> slice(uptr N, uptr M) const {
68+
DCHECK_LE(N + M, size());
69+
return ArrayRef<T>(data() + N, M);
70+
}
71+
72+
/// slice(n) - Chop off the first N elements of the array.
73+
ArrayRef<T> slice(uptr N) const { return slice(N, size() - N); }
74+
75+
/// Drop the first \p N elements of the array.
76+
ArrayRef<T> drop_front(uptr N = 1) const {
77+
DCHECK_GE(size(), N);
78+
return slice(N, size() - N);
79+
}
80+
81+
/// Drop the last \p N elements of the array.
82+
ArrayRef<T> drop_back(uptr N = 1) const {
83+
DCHECK_GE(size(), N);
84+
return slice(0, size() - N);
85+
}
86+
87+
/// Return a copy of *this with only the first \p N elements.
88+
ArrayRef<T> take_front(uptr N = 1) const {
89+
if (N >= size())
90+
return *this;
91+
return drop_back(size() - N);
92+
}
93+
94+
/// Return a copy of *this with only the last \p N elements.
95+
ArrayRef<T> take_back(uptr N = 1) const {
96+
if (N >= size())
97+
return *this;
98+
return drop_front(size() - N);
99+
}
100+
101+
const T &operator[](uptr index) const {
102+
DCHECK_LT(index, size());
103+
return begin_[index];
104+
}
105+
43106
private:
44107
const T *begin_ = nullptr;
45108
const T *end_ = nullptr;
46109
};
47110

111+
template <typename T>
112+
inline bool operator==(ArrayRef<T> lhs, ArrayRef<T> rhs) {
113+
return lhs.equals(rhs);
114+
}
115+
116+
template <typename T>
117+
inline bool operator!=(ArrayRef<T> lhs, ArrayRef<T> rhs) {
118+
return !(lhs == rhs);
119+
}
120+
48121
} // namespace __sanitizer
49122

50123
#endif // SANITIZER_ARRAY_REF_H

compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ endif()
1212
set(SANITIZER_UNITTESTS
1313
sanitizer_addrhashmap_test.cpp
1414
sanitizer_allocator_test.cpp
15+
sanitizer_array_ref_test.cpp
1516
sanitizer_atomic_test.cpp
1617
sanitizer_bitvector_test.cpp
1718
sanitizer_bvgraph_test.cpp
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//===- sanitizer_array_ref.cpp - ArrayRef unit tests ----------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "sanitizer_common/sanitizer_array_ref.h"
10+
11+
#include <vector>
12+
13+
#include "gtest/gtest.h"
14+
#include "sanitizer_internal_defs.h"
15+
16+
using namespace __sanitizer;
17+
namespace {
18+
19+
TEST(ArrayRefTest, Constructors) {
20+
ArrayRef<int> ar0;
21+
EXPECT_TRUE(ar0.empty());
22+
EXPECT_EQ(ar0.size(), 0u);
23+
24+
static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
25+
ArrayRef<int> ar1(kTheNumbers);
26+
EXPECT_FALSE(ar1.empty());
27+
EXPECT_EQ(ar1.size(), ARRAY_SIZE(kTheNumbers));
28+
29+
ArrayRef<int> ar2(&kTheNumbers[0], &kTheNumbers[2]);
30+
EXPECT_FALSE(ar2.empty());
31+
EXPECT_EQ(ar2.size(), 2u);
32+
33+
ArrayRef<int> ar3(&kTheNumbers[0], 3);
34+
EXPECT_FALSE(ar3.empty());
35+
EXPECT_EQ(ar3.size(), 3u);
36+
37+
std::vector<int> v(4, 1);
38+
ArrayRef<int> ar4(v);
39+
EXPECT_FALSE(ar4.empty());
40+
EXPECT_EQ(ar4.size(), 4u);
41+
42+
int n;
43+
ArrayRef<int> ar5(n);
44+
EXPECT_FALSE(ar5.empty());
45+
EXPECT_EQ(ar5.size(), 1u);
46+
}
47+
48+
TEST(ArrayRefTest, DropBack) {
49+
static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
50+
ArrayRef<int> ar1(kTheNumbers);
51+
ArrayRef<int> ar2(kTheNumbers, ar1.size() - 1);
52+
EXPECT_TRUE(ar1.drop_back().equals(ar2));
53+
}
54+
55+
TEST(ArrayRefTest, DropFront) {
56+
static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
57+
ArrayRef<int> ar1(kTheNumbers);
58+
ArrayRef<int> ar2(&kTheNumbers[2], ar1.size() - 2);
59+
EXPECT_TRUE(ar1.drop_front(2).equals(ar2));
60+
}
61+
62+
TEST(ArrayRefTest, TakeBack) {
63+
static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
64+
ArrayRef<int> ar1(kTheNumbers);
65+
ArrayRef<int> ar2(ar1.end() - 1, 1);
66+
EXPECT_TRUE(ar1.take_back().equals(ar2));
67+
}
68+
69+
TEST(ArrayRefTest, TakeFront) {
70+
static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
71+
ArrayRef<int> ar1(kTheNumbers);
72+
ArrayRef<int> ar2(ar1.data(), 2);
73+
EXPECT_TRUE(ar1.take_front(2).equals(ar2));
74+
}
75+
76+
TEST(ArrayRefTest, Equals) {
77+
static const int kA1[] = {1, 2, 3, 4, 5, 6, 7, 8};
78+
ArrayRef<int> ar1(kA1);
79+
EXPECT_TRUE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8})));
80+
EXPECT_FALSE(ar1.equals(std::vector<int>({8, 1, 2, 4, 5, 6, 6, 7})));
81+
EXPECT_FALSE(ar1.equals(std::vector<int>({2, 4, 5, 6, 6, 7, 8, 1})));
82+
EXPECT_FALSE(ar1.equals(std::vector<int>({0, 1, 2, 4, 5, 6, 6, 7})));
83+
EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 42, 4, 5, 6, 7, 8})));
84+
EXPECT_FALSE(ar1.equals(std::vector<int>({42, 2, 3, 4, 5, 6, 7, 8})));
85+
EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 42})));
86+
EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7})));
87+
EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8, 9})));
88+
89+
ArrayRef<int> ar1_a = ar1.drop_back();
90+
EXPECT_TRUE(ar1_a.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7})));
91+
EXPECT_FALSE(ar1_a.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8})));
92+
93+
ArrayRef<int> ar1_b = ar1_a.slice(2, 4);
94+
EXPECT_TRUE(ar1_b.equals(std::vector<int>({3, 4, 5, 6})));
95+
EXPECT_FALSE(ar1_b.equals(std::vector<int>({2, 3, 4, 5, 6})));
96+
EXPECT_FALSE(ar1_b.equals(std::vector<int>({3, 4, 5, 6, 7})));
97+
}
98+
99+
TEST(ArrayRefTest, EmptyEquals) {
100+
EXPECT_TRUE(ArrayRef<unsigned>() == ArrayRef<unsigned>());
101+
}
102+
103+
TEST(ArrayRefTest, ConstConvert) {
104+
int buf[4];
105+
for (int i = 0; i < 4; ++i) buf[i] = i;
106+
107+
static int *ptrs[] = {&buf[0], &buf[1], &buf[2], &buf[3]};
108+
ArrayRef<const int *> a((ArrayRef<int *>(ptrs)));
109+
a = ArrayRef<int *>(ptrs);
110+
}
111+
112+
static std::vector<int> ReturnTest12() { return {1, 2}; }
113+
static void ArgTest12(ArrayRef<int> a) {
114+
EXPECT_EQ(2U, a.size());
115+
EXPECT_EQ(1, a[0]);
116+
EXPECT_EQ(2, a[1]);
117+
}
118+
119+
TEST(ArrayRefTest, ArrayRef) {
120+
static const int kA1[] = {1, 2, 3, 4, 5, 6, 7, 8};
121+
122+
// A copy is expected for non-const ArrayRef (thin copy)
123+
ArrayRef<int> ar1(kA1);
124+
const ArrayRef<int> &ar1_ref = ArrayRef(ar1);
125+
EXPECT_NE(&ar1, &ar1_ref);
126+
EXPECT_TRUE(ar1.equals(ar1_ref));
127+
128+
// A copy is expected for non-const ArrayRef (thin copy)
129+
const ArrayRef<int> ar2(kA1);
130+
const ArrayRef<int> &ar2_ref = ArrayRef(ar2);
131+
EXPECT_NE(&ar2_ref, &ar2);
132+
EXPECT_TRUE(ar2.equals(ar2_ref));
133+
}
134+
135+
TEST(ArrayRefTest, ArrayRefFromStdArray) {
136+
std::array<int, 5> a1{{42, -5, 0, 1000000, -1000000}};
137+
ArrayRef<int> a2 = ArrayRef<int>(a1);
138+
139+
EXPECT_EQ(a1.size(), a2.size());
140+
for (std::size_t i = 0; i < a1.size(); ++i) {
141+
EXPECT_EQ(a1[i], a2[i]);
142+
}
143+
}
144+
145+
static_assert(std::is_trivially_copyable_v<ArrayRef<int>>,
146+
"trivially copyable");
147+
148+
} // namespace

0 commit comments

Comments
 (0)