[compiler-rt] f35d060 - [test][sanitizer] Add ArrayRef tests

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 13 08:53:10 PDT 2023


Author: Vitaly Buka
Date: 2023-06-13T08:52:56-07:00
New Revision: f35d0608fbd926c7ba2bf62ca6a2fa45287c0936

URL: https://github.com/llvm/llvm-project/commit/f35d0608fbd926c7ba2bf62ca6a2fa45287c0936
DIFF: https://github.com/llvm/llvm-project/commit/f35d0608fbd926c7ba2bf62ca6a2fa45287c0936.diff

LOG: [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

Added: 
    compiler-rt/lib/sanitizer_common/tests/sanitizer_array_ref_test.cpp

Modified: 
    compiler-rt/lib/sanitizer_common/sanitizer_array_ref.h
    compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_array_ref.h b/compiler-rt/lib/sanitizer_common/sanitizer_array_ref.h
index d19c46d031525..28d125383da41 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_array_ref.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_array_ref.h
@@ -27,11 +27,20 @@ namespace __sanitizer {
 template <typename T>
 class ArrayRef {
  public:
-  ArrayRef() {}
-  ArrayRef(const T *begin, const T *end) : begin_(begin), end_(end) {}
-
+  constexpr ArrayRef() {}
+  constexpr ArrayRef(const T *begin, const T *end) : begin_(begin), end_(end) {
+    DCHECK(empty() || begin);
+  }
+  constexpr ArrayRef(const T *data, uptr length)
+      : ArrayRef(data, data + length) {}
+  template <uptr N>
+  constexpr ArrayRef(const T (&src)[N]) : ArrayRef(src, src + N) {}
   template <typename C>
-  ArrayRef(const C &src) : ArrayRef(src.data(), src.data() + src.size()) {}
+  constexpr ArrayRef(const C &src)
+      : ArrayRef(src.data(), src.data() + src.size()) {}
+  ArrayRef(const T &one_elt) : ArrayRef(&one_elt, &one_elt + 1) {}
+
+  const T *data() const { return empty() ? nullptr : begin_; }
 
   const T *begin() const { return begin_; }
   const T *end() const { return end_; }
@@ -40,11 +49,75 @@ class ArrayRef {
 
   uptr size() const { return end_ - begin_; }
 
+  /// equals - Check for element-wise equality.
+  bool equals(ArrayRef rhs) const {
+    if (size() != rhs.size())
+      return false;
+    auto r = rhs.begin();
+    for (auto &l : *this) {
+      if (!(l == *r))
+        return false;
+      ++r;
+    }
+    return true;
+  }
+
+  /// slice(n, m) - Chop off the first N elements of the array, and keep M
+  /// elements in the array.
+  ArrayRef<T> slice(uptr N, uptr M) const {
+    DCHECK_LE(N + M, size());
+    return ArrayRef<T>(data() + N, M);
+  }
+
+  /// slice(n) - Chop off the first N elements of the array.
+  ArrayRef<T> slice(uptr N) const { return slice(N, size() - N); }
+
+  /// Drop the first \p N elements of the array.
+  ArrayRef<T> drop_front(uptr N = 1) const {
+    DCHECK_GE(size(), N);
+    return slice(N, size() - N);
+  }
+
+  /// Drop the last \p N elements of the array.
+  ArrayRef<T> drop_back(uptr N = 1) const {
+    DCHECK_GE(size(), N);
+    return slice(0, size() - N);
+  }
+
+  /// Return a copy of *this with only the first \p N elements.
+  ArrayRef<T> take_front(uptr N = 1) const {
+    if (N >= size())
+      return *this;
+    return drop_back(size() - N);
+  }
+
+  /// Return a copy of *this with only the last \p N elements.
+  ArrayRef<T> take_back(uptr N = 1) const {
+    if (N >= size())
+      return *this;
+    return drop_front(size() - N);
+  }
+
+  const T &operator[](uptr index) const {
+    DCHECK_LT(index, size());
+    return begin_[index];
+  }
+
  private:
   const T *begin_ = nullptr;
   const T *end_ = nullptr;
 };
 
+template <typename T>
+inline bool operator==(ArrayRef<T> lhs, ArrayRef<T> rhs) {
+  return lhs.equals(rhs);
+}
+
+template <typename T>
+inline bool operator!=(ArrayRef<T> lhs, ArrayRef<T> rhs) {
+  return !(lhs == rhs);
+}
+
 }  // namespace __sanitizer
 
 #endif  // SANITIZER_ARRAY_REF_H

diff  --git a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
index e1a3f82ca573c..972176dccc004 100644
--- a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
+++ b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt
@@ -12,6 +12,7 @@ endif()
 set(SANITIZER_UNITTESTS
   sanitizer_addrhashmap_test.cpp
   sanitizer_allocator_test.cpp
+  sanitizer_array_ref_test.cpp
   sanitizer_atomic_test.cpp
   sanitizer_bitvector_test.cpp
   sanitizer_bvgraph_test.cpp

diff  --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_array_ref_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_array_ref_test.cpp
new file mode 100644
index 0000000000000..d8244c59532b0
--- /dev/null
+++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_array_ref_test.cpp
@@ -0,0 +1,148 @@
+//===- sanitizer_array_ref.cpp - ArrayRef 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 "sanitizer_common/sanitizer_array_ref.h"
+
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "sanitizer_internal_defs.h"
+
+using namespace __sanitizer;
+namespace {
+
+TEST(ArrayRefTest, Constructors) {
+  ArrayRef<int> ar0;
+  EXPECT_TRUE(ar0.empty());
+  EXPECT_EQ(ar0.size(), 0u);
+
+  static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
+  ArrayRef<int> ar1(kTheNumbers);
+  EXPECT_FALSE(ar1.empty());
+  EXPECT_EQ(ar1.size(), ARRAY_SIZE(kTheNumbers));
+
+  ArrayRef<int> ar2(&kTheNumbers[0], &kTheNumbers[2]);
+  EXPECT_FALSE(ar2.empty());
+  EXPECT_EQ(ar2.size(), 2u);
+
+  ArrayRef<int> ar3(&kTheNumbers[0], 3);
+  EXPECT_FALSE(ar3.empty());
+  EXPECT_EQ(ar3.size(), 3u);
+
+  std::vector<int> v(4, 1);
+  ArrayRef<int> ar4(v);
+  EXPECT_FALSE(ar4.empty());
+  EXPECT_EQ(ar4.size(), 4u);
+
+  int n;
+  ArrayRef<int> ar5(n);
+  EXPECT_FALSE(ar5.empty());
+  EXPECT_EQ(ar5.size(), 1u);
+}
+
+TEST(ArrayRefTest, DropBack) {
+  static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
+  ArrayRef<int> ar1(kTheNumbers);
+  ArrayRef<int> ar2(kTheNumbers, ar1.size() - 1);
+  EXPECT_TRUE(ar1.drop_back().equals(ar2));
+}
+
+TEST(ArrayRefTest, DropFront) {
+  static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
+  ArrayRef<int> ar1(kTheNumbers);
+  ArrayRef<int> ar2(&kTheNumbers[2], ar1.size() - 2);
+  EXPECT_TRUE(ar1.drop_front(2).equals(ar2));
+}
+
+TEST(ArrayRefTest, TakeBack) {
+  static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
+  ArrayRef<int> ar1(kTheNumbers);
+  ArrayRef<int> ar2(ar1.end() - 1, 1);
+  EXPECT_TRUE(ar1.take_back().equals(ar2));
+}
+
+TEST(ArrayRefTest, TakeFront) {
+  static const int kTheNumbers[] = {4, 8, 15, 16, 23, 42};
+  ArrayRef<int> ar1(kTheNumbers);
+  ArrayRef<int> ar2(ar1.data(), 2);
+  EXPECT_TRUE(ar1.take_front(2).equals(ar2));
+}
+
+TEST(ArrayRefTest, Equals) {
+  static const int kA1[] = {1, 2, 3, 4, 5, 6, 7, 8};
+  ArrayRef<int> ar1(kA1);
+  EXPECT_TRUE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({8, 1, 2, 4, 5, 6, 6, 7})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({2, 4, 5, 6, 6, 7, 8, 1})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({0, 1, 2, 4, 5, 6, 6, 7})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 42, 4, 5, 6, 7, 8})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({42, 2, 3, 4, 5, 6, 7, 8})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 42})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7})));
+  EXPECT_FALSE(ar1.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8, 9})));
+
+  ArrayRef<int> ar1_a = ar1.drop_back();
+  EXPECT_TRUE(ar1_a.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7})));
+  EXPECT_FALSE(ar1_a.equals(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8})));
+
+  ArrayRef<int> ar1_b = ar1_a.slice(2, 4);
+  EXPECT_TRUE(ar1_b.equals(std::vector<int>({3, 4, 5, 6})));
+  EXPECT_FALSE(ar1_b.equals(std::vector<int>({2, 3, 4, 5, 6})));
+  EXPECT_FALSE(ar1_b.equals(std::vector<int>({3, 4, 5, 6, 7})));
+}
+
+TEST(ArrayRefTest, EmptyEquals) {
+  EXPECT_TRUE(ArrayRef<unsigned>() == ArrayRef<unsigned>());
+}
+
+TEST(ArrayRefTest, ConstConvert) {
+  int buf[4];
+  for (int i = 0; i < 4; ++i) buf[i] = i;
+
+  static int *ptrs[] = {&buf[0], &buf[1], &buf[2], &buf[3]};
+  ArrayRef<const int *> a((ArrayRef<int *>(ptrs)));
+  a = ArrayRef<int *>(ptrs);
+}
+
+static std::vector<int> ReturnTest12() { return {1, 2}; }
+static void ArgTest12(ArrayRef<int> a) {
+  EXPECT_EQ(2U, a.size());
+  EXPECT_EQ(1, a[0]);
+  EXPECT_EQ(2, a[1]);
+}
+
+TEST(ArrayRefTest, ArrayRef) {
+  static const int kA1[] = {1, 2, 3, 4, 5, 6, 7, 8};
+
+  // A copy is expected for non-const ArrayRef (thin copy)
+  ArrayRef<int> ar1(kA1);
+  const ArrayRef<int> &ar1_ref = ArrayRef(ar1);
+  EXPECT_NE(&ar1, &ar1_ref);
+  EXPECT_TRUE(ar1.equals(ar1_ref));
+
+  // A copy is expected for non-const ArrayRef (thin copy)
+  const ArrayRef<int> ar2(kA1);
+  const ArrayRef<int> &ar2_ref = ArrayRef(ar2);
+  EXPECT_NE(&ar2_ref, &ar2);
+  EXPECT_TRUE(ar2.equals(ar2_ref));
+}
+
+TEST(ArrayRefTest, ArrayRefFromStdArray) {
+  std::array<int, 5> a1{{42, -5, 0, 1000000, -1000000}};
+  ArrayRef<int> a2 = ArrayRef<int>(a1);
+
+  EXPECT_EQ(a1.size(), a2.size());
+  for (std::size_t i = 0; i < a1.size(); ++i) {
+    EXPECT_EQ(a1[i], a2[i]);
+  }
+}
+
+static_assert(std::is_trivially_copyable_v<ArrayRef<int>>,
+              "trivially copyable");
+
+}  // namespace


        


More information about the llvm-commits mailing list