mirror of https://github.com/oxen-io/lokinet
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
783 lines
25 KiB
C++
783 lines
25 KiB
C++
// Copyright 2017 The Abseil Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "absl/types/span.h"
|
|
|
|
#include <array>
|
|
#include <initializer_list>
|
|
#include <numeric>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
#include "absl/base/attributes.h"
|
|
#include "absl/base/config.h"
|
|
#include "absl/base/internal/exception_testing.h"
|
|
#include "absl/container/fixed_array.h"
|
|
#include "absl/container/inlined_vector.h"
|
|
#include "absl/hash/hash_testing.h"
|
|
#include "absl/strings/str_cat.h"
|
|
|
|
namespace {
|
|
|
|
MATCHER_P(DataIs, data,
|
|
absl::StrCat("data() is ", negation ? "is " : "isn't ",
|
|
testing::PrintToString(data))) {
|
|
return arg.data() == data;
|
|
}
|
|
|
|
template <typename T>
|
|
auto SpanIs(T data, size_t size)
|
|
-> decltype(testing::AllOf(DataIs(data), testing::SizeIs(size))) {
|
|
return testing::AllOf(DataIs(data), testing::SizeIs(size));
|
|
}
|
|
|
|
template <typename Container>
|
|
auto SpanIs(const Container& c) -> decltype(SpanIs(c.data(), c.size())) {
|
|
return SpanIs(c.data(), c.size());
|
|
}
|
|
|
|
std::vector<int> MakeRamp(int len, int offset = 0) {
|
|
std::vector<int> v(len);
|
|
std::iota(v.begin(), v.end(), offset);
|
|
return v;
|
|
}
|
|
|
|
TEST(IntSpan, EmptyCtors) {
|
|
absl::Span<int> s;
|
|
EXPECT_THAT(s, SpanIs(nullptr, 0));
|
|
}
|
|
|
|
TEST(IntSpan, PtrLenCtor) {
|
|
int a[] = {1, 2, 3};
|
|
absl::Span<int> s(&a[0], 2);
|
|
EXPECT_THAT(s, SpanIs(a, 2));
|
|
}
|
|
|
|
TEST(IntSpan, ArrayCtor) {
|
|
int a[] = {1, 2, 3};
|
|
absl::Span<int> s(a);
|
|
EXPECT_THAT(s, SpanIs(a, 3));
|
|
|
|
EXPECT_TRUE((std::is_constructible<absl::Span<const int>, int[3]>::value));
|
|
EXPECT_TRUE(
|
|
(std::is_constructible<absl::Span<const int>, const int[3]>::value));
|
|
EXPECT_FALSE((std::is_constructible<absl::Span<int>, const int[3]>::value));
|
|
EXPECT_TRUE((std::is_convertible<int[3], absl::Span<const int>>::value));
|
|
EXPECT_TRUE(
|
|
(std::is_convertible<const int[3], absl::Span<const int>>::value));
|
|
}
|
|
|
|
template <typename T>
|
|
void TakesGenericSpan(absl::Span<T>) {}
|
|
|
|
TEST(IntSpan, ContainerCtor) {
|
|
std::vector<int> empty;
|
|
absl::Span<int> s_empty(empty);
|
|
EXPECT_THAT(s_empty, SpanIs(empty));
|
|
|
|
std::vector<int> filled{1, 2, 3};
|
|
absl::Span<int> s_filled(filled);
|
|
EXPECT_THAT(s_filled, SpanIs(filled));
|
|
|
|
absl::Span<int> s_from_span(filled);
|
|
EXPECT_THAT(s_from_span, SpanIs(s_filled));
|
|
|
|
absl::Span<const int> const_filled = filled;
|
|
EXPECT_THAT(const_filled, SpanIs(filled));
|
|
|
|
absl::Span<const int> const_from_span = s_filled;
|
|
EXPECT_THAT(const_from_span, SpanIs(s_filled));
|
|
|
|
EXPECT_TRUE(
|
|
(std::is_convertible<std::vector<int>&, absl::Span<const int>>::value));
|
|
EXPECT_TRUE(
|
|
(std::is_convertible<absl::Span<int>&, absl::Span<const int>>::value));
|
|
|
|
TakesGenericSpan(absl::Span<int>(filled));
|
|
}
|
|
|
|
// A struct supplying shallow data() const.
|
|
struct ContainerWithShallowConstData {
|
|
std::vector<int> storage;
|
|
int* data() const { return const_cast<int*>(storage.data()); }
|
|
int size() const { return storage.size(); }
|
|
};
|
|
|
|
TEST(IntSpan, ShallowConstness) {
|
|
const ContainerWithShallowConstData c{MakeRamp(20)};
|
|
absl::Span<int> s(
|
|
c); // We should be able to do this even though data() is const.
|
|
s[0] = -1;
|
|
EXPECT_EQ(c.storage[0], -1);
|
|
}
|
|
|
|
TEST(CharSpan, StringCtor) {
|
|
std::string empty = "";
|
|
absl::Span<char> s_empty(empty);
|
|
EXPECT_THAT(s_empty, SpanIs(empty));
|
|
|
|
std::string abc = "abc";
|
|
absl::Span<char> s_abc(abc);
|
|
EXPECT_THAT(s_abc, SpanIs(abc));
|
|
|
|
absl::Span<const char> s_const_abc = abc;
|
|
EXPECT_THAT(s_const_abc, SpanIs(abc));
|
|
|
|
EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value));
|
|
EXPECT_FALSE((std::is_constructible<absl::Span<const int>, std::string>::value));
|
|
EXPECT_TRUE((std::is_convertible<std::string, absl::Span<const char>>::value));
|
|
}
|
|
|
|
TEST(IntSpan, FromConstPointer) {
|
|
EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>,
|
|
std::vector<int*>>::value));
|
|
EXPECT_TRUE((std::is_constructible<absl::Span<const int* const>,
|
|
std::vector<const int*>>::value));
|
|
EXPECT_FALSE((
|
|
std::is_constructible<absl::Span<const int*>, std::vector<int*>>::value));
|
|
EXPECT_FALSE((
|
|
std::is_constructible<absl::Span<int*>, std::vector<const int*>>::value));
|
|
}
|
|
|
|
struct TypeWithMisleadingData {
|
|
int& data() { return i; }
|
|
int size() { return 1; }
|
|
int i;
|
|
};
|
|
|
|
struct TypeWithMisleadingSize {
|
|
int* data() { return &i; }
|
|
const char* size() { return "1"; }
|
|
int i;
|
|
};
|
|
|
|
TEST(IntSpan, EvilTypes) {
|
|
EXPECT_FALSE(
|
|
(std::is_constructible<absl::Span<int>, TypeWithMisleadingData&>::value));
|
|
EXPECT_FALSE(
|
|
(std::is_constructible<absl::Span<int>, TypeWithMisleadingSize&>::value));
|
|
}
|
|
|
|
struct Base {
|
|
int* data() { return &i; }
|
|
int size() { return 1; }
|
|
int i;
|
|
};
|
|
struct Derived : Base {};
|
|
|
|
TEST(IntSpan, SpanOfDerived) {
|
|
EXPECT_TRUE((std::is_constructible<absl::Span<int>, Base&>::value));
|
|
EXPECT_TRUE((std::is_constructible<absl::Span<int>, Derived&>::value));
|
|
EXPECT_FALSE(
|
|
(std::is_constructible<absl::Span<Base>, std::vector<Derived>>::value));
|
|
}
|
|
|
|
void TestInitializerList(absl::Span<const int> s, const std::vector<int>& v) {
|
|
EXPECT_TRUE(absl::equal(s.begin(), s.end(), v.begin(), v.end()));
|
|
}
|
|
|
|
TEST(ConstIntSpan, InitializerListConversion) {
|
|
TestInitializerList({}, {});
|
|
TestInitializerList({1}, {1});
|
|
TestInitializerList({1, 2, 3}, {1, 2, 3});
|
|
|
|
EXPECT_FALSE((std::is_constructible<absl::Span<int>,
|
|
std::initializer_list<int>>::value));
|
|
EXPECT_FALSE((
|
|
std::is_convertible<absl::Span<int>, std::initializer_list<int>>::value));
|
|
}
|
|
|
|
TEST(IntSpan, Data) {
|
|
int i;
|
|
absl::Span<int> s(&i, 1);
|
|
EXPECT_EQ(&i, s.data());
|
|
}
|
|
|
|
TEST(IntSpan, SizeLengthEmpty) {
|
|
absl::Span<int> empty;
|
|
EXPECT_EQ(empty.size(), 0);
|
|
EXPECT_TRUE(empty.empty());
|
|
EXPECT_EQ(empty.size(), empty.length());
|
|
|
|
auto v = MakeRamp(10);
|
|
absl::Span<int> s(v);
|
|
EXPECT_EQ(s.size(), 10);
|
|
EXPECT_FALSE(s.empty());
|
|
EXPECT_EQ(s.size(), s.length());
|
|
}
|
|
|
|
TEST(IntSpan, ElementAccess) {
|
|
auto v = MakeRamp(10);
|
|
absl::Span<int> s(v);
|
|
for (int i = 0; i < s.size(); ++i) {
|
|
EXPECT_EQ(s[i], s.at(i));
|
|
}
|
|
|
|
EXPECT_EQ(s.front(), s[0]);
|
|
EXPECT_EQ(s.back(), s[9]);
|
|
}
|
|
|
|
TEST(IntSpan, AtThrows) {
|
|
auto v = MakeRamp(10);
|
|
absl::Span<int> s(v);
|
|
|
|
EXPECT_EQ(s.at(9), 9);
|
|
ABSL_BASE_INTERNAL_EXPECT_FAIL(s.at(10), std::out_of_range,
|
|
"failed bounds check");
|
|
}
|
|
|
|
TEST(IntSpan, RemovePrefixAndSuffix) {
|
|
auto v = MakeRamp(20, 1);
|
|
absl::Span<int> s(v);
|
|
EXPECT_EQ(s.size(), 20);
|
|
|
|
s.remove_suffix(0);
|
|
s.remove_prefix(0);
|
|
EXPECT_EQ(s.size(), 20);
|
|
|
|
s.remove_prefix(1);
|
|
EXPECT_EQ(s.size(), 19);
|
|
EXPECT_EQ(s[0], 2);
|
|
|
|
s.remove_suffix(1);
|
|
EXPECT_EQ(s.size(), 18);
|
|
EXPECT_EQ(s.back(), 19);
|
|
|
|
s.remove_prefix(7);
|
|
EXPECT_EQ(s.size(), 11);
|
|
EXPECT_EQ(s[0], 9);
|
|
|
|
s.remove_suffix(11);
|
|
EXPECT_EQ(s.size(), 0);
|
|
|
|
EXPECT_EQ(v, MakeRamp(20, 1));
|
|
}
|
|
|
|
TEST(IntSpan, Subspan) {
|
|
std::vector<int> empty;
|
|
EXPECT_EQ(absl::MakeSpan(empty).subspan(), empty);
|
|
EXPECT_THAT(absl::MakeSpan(empty).subspan(0, 0), SpanIs(empty));
|
|
EXPECT_THAT(absl::MakeSpan(empty).subspan(0, absl::Span<const int>::npos),
|
|
SpanIs(empty));
|
|
|
|
auto ramp = MakeRamp(10);
|
|
EXPECT_THAT(absl::MakeSpan(ramp).subspan(), SpanIs(ramp));
|
|
EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 10), SpanIs(ramp));
|
|
EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, absl::Span<const int>::npos),
|
|
SpanIs(ramp));
|
|
EXPECT_THAT(absl::MakeSpan(ramp).subspan(0, 3), SpanIs(ramp.data(), 3));
|
|
EXPECT_THAT(absl::MakeSpan(ramp).subspan(5, absl::Span<const int>::npos),
|
|
SpanIs(ramp.data() + 5, 5));
|
|
EXPECT_THAT(absl::MakeSpan(ramp).subspan(3, 3), SpanIs(ramp.data() + 3, 3));
|
|
EXPECT_THAT(absl::MakeSpan(ramp).subspan(10, 5), SpanIs(ramp.data() + 10, 0));
|
|
|
|
#ifdef ABSL_HAVE_EXCEPTIONS
|
|
EXPECT_THROW(absl::MakeSpan(ramp).subspan(11, 5), std::out_of_range);
|
|
#else
|
|
EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).subspan(11, 5), "");
|
|
#endif
|
|
}
|
|
|
|
TEST(IntSpan, MakeSpanPtrLength) {
|
|
std::vector<int> empty;
|
|
auto s_empty = absl::MakeSpan(empty.data(), empty.size());
|
|
EXPECT_THAT(s_empty, SpanIs(empty));
|
|
|
|
std::array<int, 3> a{{1, 2, 3}};
|
|
auto s = absl::MakeSpan(a.data(), a.size());
|
|
EXPECT_THAT(s, SpanIs(a));
|
|
|
|
EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.size()), SpanIs(s_empty));
|
|
EXPECT_THAT(absl::MakeConstSpan(a.data(), a.size()), SpanIs(s));
|
|
}
|
|
|
|
TEST(IntSpan, MakeSpanTwoPtrs) {
|
|
std::vector<int> empty;
|
|
auto s_empty = absl::MakeSpan(empty.data(), empty.data());
|
|
EXPECT_THAT(s_empty, SpanIs(empty));
|
|
|
|
std::vector<int> v{1, 2, 3};
|
|
auto s = absl::MakeSpan(v.data(), v.data() + 1);
|
|
EXPECT_THAT(s, SpanIs(v.data(), 1));
|
|
|
|
EXPECT_THAT(absl::MakeConstSpan(empty.data(), empty.data()), SpanIs(s_empty));
|
|
EXPECT_THAT(absl::MakeConstSpan(v.data(), v.data() + 1), SpanIs(s));
|
|
}
|
|
|
|
TEST(IntSpan, MakeSpanContainer) {
|
|
std::vector<int> empty;
|
|
auto s_empty = absl::MakeSpan(empty);
|
|
EXPECT_THAT(s_empty, SpanIs(empty));
|
|
|
|
std::vector<int> v{1, 2, 3};
|
|
auto s = absl::MakeSpan(v);
|
|
EXPECT_THAT(s, SpanIs(v));
|
|
|
|
EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty));
|
|
EXPECT_THAT(absl::MakeConstSpan(v), SpanIs(s));
|
|
|
|
EXPECT_THAT(absl::MakeSpan(s), SpanIs(s));
|
|
EXPECT_THAT(absl::MakeConstSpan(s), SpanIs(s));
|
|
}
|
|
|
|
TEST(CharSpan, MakeSpanString) {
|
|
std::string empty = "";
|
|
auto s_empty = absl::MakeSpan(empty);
|
|
EXPECT_THAT(s_empty, SpanIs(empty));
|
|
|
|
std::string str = "abc";
|
|
auto s_str = absl::MakeSpan(str);
|
|
EXPECT_THAT(s_str, SpanIs(str));
|
|
|
|
EXPECT_THAT(absl::MakeConstSpan(empty), SpanIs(s_empty));
|
|
EXPECT_THAT(absl::MakeConstSpan(str), SpanIs(s_str));
|
|
}
|
|
|
|
TEST(IntSpan, MakeSpanArray) {
|
|
int a[] = {1, 2, 3};
|
|
auto s = absl::MakeSpan(a);
|
|
EXPECT_THAT(s, SpanIs(a, 3));
|
|
|
|
const int ca[] = {1, 2, 3};
|
|
auto s_ca = absl::MakeSpan(ca);
|
|
EXPECT_THAT(s_ca, SpanIs(ca, 3));
|
|
|
|
EXPECT_THAT(absl::MakeConstSpan(a), SpanIs(s));
|
|
EXPECT_THAT(absl::MakeConstSpan(ca), SpanIs(s_ca));
|
|
}
|
|
|
|
// Compile-asserts that the argument has the expected decayed type.
|
|
template <typename Expected, typename T>
|
|
void CheckType(const T& /* value */) {
|
|
testing::StaticAssertTypeEq<Expected, T>();
|
|
}
|
|
|
|
TEST(IntSpan, MakeSpanTypes) {
|
|
std::vector<int> vec;
|
|
const std::vector<int> cvec;
|
|
int a[1];
|
|
const int ca[] = {1};
|
|
int* ip = a;
|
|
const int* cip = ca;
|
|
std::string s = "";
|
|
const std::string cs = "";
|
|
CheckType<absl::Span<int>>(absl::MakeSpan(vec));
|
|
CheckType<absl::Span<const int>>(absl::MakeSpan(cvec));
|
|
CheckType<absl::Span<int>>(absl::MakeSpan(ip, ip + 1));
|
|
CheckType<absl::Span<int>>(absl::MakeSpan(ip, 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeSpan(cip, cip + 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeSpan(cip, 1));
|
|
CheckType<absl::Span<int>>(absl::MakeSpan(a));
|
|
CheckType<absl::Span<int>>(absl::MakeSpan(a, a + 1));
|
|
CheckType<absl::Span<int>>(absl::MakeSpan(a, 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeSpan(ca));
|
|
CheckType<absl::Span<const int>>(absl::MakeSpan(ca, ca + 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeSpan(ca, 1));
|
|
CheckType<absl::Span<char>>(absl::MakeSpan(s));
|
|
CheckType<absl::Span<const char>>(absl::MakeSpan(cs));
|
|
}
|
|
|
|
TEST(ConstIntSpan, MakeConstSpanTypes) {
|
|
std::vector<int> vec;
|
|
const std::vector<int> cvec;
|
|
int array[1];
|
|
const int carray[] = {0};
|
|
int* ptr = array;
|
|
const int* cptr = carray;
|
|
std::string s = "";
|
|
std::string cs = "";
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(vec));
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(cvec));
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, ptr + 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(ptr, 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, cptr + 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(cptr, 1));
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(array));
|
|
CheckType<absl::Span<const int>>(absl::MakeConstSpan(carray));
|
|
CheckType<absl::Span<const char>>(absl::MakeConstSpan(s));
|
|
CheckType<absl::Span<const char>>(absl::MakeConstSpan(cs));
|
|
}
|
|
|
|
TEST(IntSpan, Equality) {
|
|
const int arr1[] = {1, 2, 3, 4, 5};
|
|
int arr2[] = {1, 2, 3, 4, 5};
|
|
std::vector<int> vec1(std::begin(arr1), std::end(arr1));
|
|
std::vector<int> vec2 = vec1;
|
|
std::vector<int> other_vec = {2, 4, 6, 8, 10};
|
|
// These two slices are from different vectors, but have the same size and
|
|
// have the same elements (right now). They should compare equal. Test both
|
|
// == and !=.
|
|
const absl::Span<const int> from1 = vec1;
|
|
const absl::Span<const int> from2 = vec2;
|
|
EXPECT_EQ(from1, from1);
|
|
EXPECT_FALSE(from1 != from1);
|
|
EXPECT_EQ(from1, from2);
|
|
EXPECT_FALSE(from1 != from2);
|
|
|
|
// These two slices have different underlying vector values. They should be
|
|
// considered not equal. Test both == and !=.
|
|
const absl::Span<const int> from_other = other_vec;
|
|
EXPECT_NE(from1, from_other);
|
|
EXPECT_FALSE(from1 == from_other);
|
|
|
|
// Comparison between a vector and its slice should be equal. And vice-versa.
|
|
// This ensures implicit conversion to Span works on both sides of ==.
|
|
EXPECT_EQ(vec1, from1);
|
|
EXPECT_FALSE(vec1 != from1);
|
|
EXPECT_EQ(from1, vec1);
|
|
EXPECT_FALSE(from1 != vec1);
|
|
|
|
// This verifies that absl::Span<T> can be compared freely with
|
|
// absl::Span<const T>.
|
|
const absl::Span<int> mutable_from1(vec1);
|
|
const absl::Span<int> mutable_from2(vec2);
|
|
EXPECT_EQ(from1, mutable_from1);
|
|
EXPECT_EQ(mutable_from1, from1);
|
|
EXPECT_EQ(mutable_from1, mutable_from2);
|
|
EXPECT_EQ(mutable_from2, mutable_from1);
|
|
|
|
// Comparison between a vector and its slice should be equal for mutable
|
|
// Spans as well.
|
|
EXPECT_EQ(vec1, mutable_from1);
|
|
EXPECT_FALSE(vec1 != mutable_from1);
|
|
EXPECT_EQ(mutable_from1, vec1);
|
|
EXPECT_FALSE(mutable_from1 != vec1);
|
|
|
|
// Comparison between convertible-to-Span-of-const and Span-of-mutable. Arrays
|
|
// are used because they're the only value type which converts to a
|
|
// Span-of-mutable. EXPECT_TRUE is used instead of EXPECT_EQ to avoid
|
|
// array-to-pointer decay.
|
|
EXPECT_TRUE(arr1 == mutable_from1);
|
|
EXPECT_FALSE(arr1 != mutable_from1);
|
|
EXPECT_TRUE(mutable_from1 == arr1);
|
|
EXPECT_FALSE(mutable_from1 != arr1);
|
|
|
|
// Comparison between convertible-to-Span-of-mutable and Span-of-const
|
|
EXPECT_TRUE(arr2 == from1);
|
|
EXPECT_FALSE(arr2 != from1);
|
|
EXPECT_TRUE(from1 == arr2);
|
|
EXPECT_FALSE(from1 != arr2);
|
|
|
|
// With a different size, the array slices should not be equal.
|
|
EXPECT_NE(from1, absl::Span<const int>(from1).subspan(0, from1.size() - 1));
|
|
|
|
// With different contents, the array slices should not be equal.
|
|
++vec2.back();
|
|
EXPECT_NE(from1, from2);
|
|
}
|
|
|
|
class IntSpanOrderComparisonTest : public testing::Test {
|
|
public:
|
|
IntSpanOrderComparisonTest()
|
|
: arr_before_{1, 2, 3},
|
|
arr_after_{1, 2, 4},
|
|
carr_after_{1, 2, 4},
|
|
vec_before_(std::begin(arr_before_), std::end(arr_before_)),
|
|
vec_after_(std::begin(arr_after_), std::end(arr_after_)),
|
|
before_(vec_before_),
|
|
after_(vec_after_),
|
|
cbefore_(vec_before_),
|
|
cafter_(vec_after_) {}
|
|
|
|
protected:
|
|
int arr_before_[3], arr_after_[3];
|
|
const int carr_after_[3];
|
|
std::vector<int> vec_before_, vec_after_;
|
|
absl::Span<int> before_, after_;
|
|
absl::Span<const int> cbefore_, cafter_;
|
|
};
|
|
|
|
TEST_F(IntSpanOrderComparisonTest, CompareSpans) {
|
|
EXPECT_TRUE(cbefore_ < cafter_);
|
|
EXPECT_TRUE(cbefore_ <= cafter_);
|
|
EXPECT_TRUE(cafter_ > cbefore_);
|
|
EXPECT_TRUE(cafter_ >= cbefore_);
|
|
|
|
EXPECT_FALSE(cbefore_ > cafter_);
|
|
EXPECT_FALSE(cafter_ < cbefore_);
|
|
|
|
EXPECT_TRUE(before_ < after_);
|
|
EXPECT_TRUE(before_ <= after_);
|
|
EXPECT_TRUE(after_ > before_);
|
|
EXPECT_TRUE(after_ >= before_);
|
|
|
|
EXPECT_FALSE(before_ > after_);
|
|
EXPECT_FALSE(after_ < before_);
|
|
|
|
EXPECT_TRUE(cbefore_ < after_);
|
|
EXPECT_TRUE(cbefore_ <= after_);
|
|
EXPECT_TRUE(after_ > cbefore_);
|
|
EXPECT_TRUE(after_ >= cbefore_);
|
|
|
|
EXPECT_FALSE(cbefore_ > after_);
|
|
EXPECT_FALSE(after_ < cbefore_);
|
|
}
|
|
|
|
TEST_F(IntSpanOrderComparisonTest, SpanOfConstAndContainer) {
|
|
EXPECT_TRUE(cbefore_ < vec_after_);
|
|
EXPECT_TRUE(cbefore_ <= vec_after_);
|
|
EXPECT_TRUE(vec_after_ > cbefore_);
|
|
EXPECT_TRUE(vec_after_ >= cbefore_);
|
|
|
|
EXPECT_FALSE(cbefore_ > vec_after_);
|
|
EXPECT_FALSE(vec_after_ < cbefore_);
|
|
|
|
EXPECT_TRUE(arr_before_ < cafter_);
|
|
EXPECT_TRUE(arr_before_ <= cafter_);
|
|
EXPECT_TRUE(cafter_ > arr_before_);
|
|
EXPECT_TRUE(cafter_ >= arr_before_);
|
|
|
|
EXPECT_FALSE(arr_before_ > cafter_);
|
|
EXPECT_FALSE(cafter_ < arr_before_);
|
|
}
|
|
|
|
TEST_F(IntSpanOrderComparisonTest, SpanOfMutableAndContainer) {
|
|
EXPECT_TRUE(vec_before_ < after_);
|
|
EXPECT_TRUE(vec_before_ <= after_);
|
|
EXPECT_TRUE(after_ > vec_before_);
|
|
EXPECT_TRUE(after_ >= vec_before_);
|
|
|
|
EXPECT_FALSE(vec_before_ > after_);
|
|
EXPECT_FALSE(after_ < vec_before_);
|
|
|
|
EXPECT_TRUE(before_ < carr_after_);
|
|
EXPECT_TRUE(before_ <= carr_after_);
|
|
EXPECT_TRUE(carr_after_ > before_);
|
|
EXPECT_TRUE(carr_after_ >= before_);
|
|
|
|
EXPECT_FALSE(before_ > carr_after_);
|
|
EXPECT_FALSE(carr_after_ < before_);
|
|
}
|
|
|
|
TEST_F(IntSpanOrderComparisonTest, EqualSpans) {
|
|
EXPECT_FALSE(before_ < before_);
|
|
EXPECT_TRUE(before_ <= before_);
|
|
EXPECT_FALSE(before_ > before_);
|
|
EXPECT_TRUE(before_ >= before_);
|
|
}
|
|
|
|
TEST_F(IntSpanOrderComparisonTest, Subspans) {
|
|
auto subspan = before_.subspan(0, 1);
|
|
EXPECT_TRUE(subspan < before_);
|
|
EXPECT_TRUE(subspan <= before_);
|
|
EXPECT_TRUE(before_ > subspan);
|
|
EXPECT_TRUE(before_ >= subspan);
|
|
|
|
EXPECT_FALSE(subspan > before_);
|
|
EXPECT_FALSE(before_ < subspan);
|
|
}
|
|
|
|
TEST_F(IntSpanOrderComparisonTest, EmptySpans) {
|
|
absl::Span<int> empty;
|
|
EXPECT_FALSE(empty < empty);
|
|
EXPECT_TRUE(empty <= empty);
|
|
EXPECT_FALSE(empty > empty);
|
|
EXPECT_TRUE(empty >= empty);
|
|
|
|
EXPECT_TRUE(empty < before_);
|
|
EXPECT_TRUE(empty <= before_);
|
|
EXPECT_TRUE(before_ > empty);
|
|
EXPECT_TRUE(before_ >= empty);
|
|
|
|
EXPECT_FALSE(empty > before_);
|
|
EXPECT_FALSE(before_ < empty);
|
|
}
|
|
|
|
TEST(IntSpan, ExposesContainerTypesAndConsts) {
|
|
absl::Span<int> slice;
|
|
CheckType<absl::Span<int>::iterator>(slice.begin());
|
|
EXPECT_TRUE((std::is_convertible<decltype(slice.begin()),
|
|
absl::Span<int>::const_iterator>::value));
|
|
CheckType<absl::Span<int>::const_iterator>(slice.cbegin());
|
|
EXPECT_TRUE((std::is_convertible<decltype(slice.end()),
|
|
absl::Span<int>::const_iterator>::value));
|
|
CheckType<absl::Span<int>::const_iterator>(slice.cend());
|
|
CheckType<absl::Span<int>::reverse_iterator>(slice.rend());
|
|
EXPECT_TRUE(
|
|
(std::is_convertible<decltype(slice.rend()),
|
|
absl::Span<int>::const_reverse_iterator>::value));
|
|
CheckType<absl::Span<int>::const_reverse_iterator>(slice.crend());
|
|
testing::StaticAssertTypeEq<int, absl::Span<int>::value_type>();
|
|
testing::StaticAssertTypeEq<int, absl::Span<const int>::value_type>();
|
|
testing::StaticAssertTypeEq<int*, absl::Span<int>::pointer>();
|
|
testing::StaticAssertTypeEq<const int*, absl::Span<const int>::pointer>();
|
|
testing::StaticAssertTypeEq<int&, absl::Span<int>::reference>();
|
|
testing::StaticAssertTypeEq<const int&, absl::Span<const int>::reference>();
|
|
testing::StaticAssertTypeEq<const int&, absl::Span<int>::const_reference>();
|
|
testing::StaticAssertTypeEq<const int&,
|
|
absl::Span<const int>::const_reference>();
|
|
EXPECT_EQ(static_cast<absl::Span<int>::size_type>(-1), absl::Span<int>::npos);
|
|
}
|
|
|
|
TEST(IntSpan, IteratorsAndReferences) {
|
|
auto accept_pointer = [](int*) {};
|
|
auto accept_reference = [](int&) {};
|
|
auto accept_iterator = [](absl::Span<int>::iterator) {};
|
|
auto accept_const_iterator = [](absl::Span<int>::const_iterator) {};
|
|
auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {};
|
|
auto accept_const_reverse_iterator =
|
|
[](absl::Span<int>::const_reverse_iterator) {};
|
|
|
|
int a[1];
|
|
absl::Span<int> s = a;
|
|
|
|
accept_pointer(s.data());
|
|
accept_iterator(s.begin());
|
|
accept_const_iterator(s.begin());
|
|
accept_const_iterator(s.cbegin());
|
|
accept_iterator(s.end());
|
|
accept_const_iterator(s.end());
|
|
accept_const_iterator(s.cend());
|
|
accept_reverse_iterator(s.rbegin());
|
|
accept_const_reverse_iterator(s.rbegin());
|
|
accept_const_reverse_iterator(s.crbegin());
|
|
accept_reverse_iterator(s.rend());
|
|
accept_const_reverse_iterator(s.rend());
|
|
accept_const_reverse_iterator(s.crend());
|
|
|
|
accept_reference(s[0]);
|
|
accept_reference(s.at(0));
|
|
accept_reference(s.front());
|
|
accept_reference(s.back());
|
|
}
|
|
|
|
TEST(IntSpan, IteratorsAndReferences_Const) {
|
|
auto accept_pointer = [](int*) {};
|
|
auto accept_reference = [](int&) {};
|
|
auto accept_iterator = [](absl::Span<int>::iterator) {};
|
|
auto accept_const_iterator = [](absl::Span<int>::const_iterator) {};
|
|
auto accept_reverse_iterator = [](absl::Span<int>::reverse_iterator) {};
|
|
auto accept_const_reverse_iterator =
|
|
[](absl::Span<int>::const_reverse_iterator) {};
|
|
|
|
int a[1];
|
|
const absl::Span<int> s = a;
|
|
|
|
accept_pointer(s.data());
|
|
accept_iterator(s.begin());
|
|
accept_const_iterator(s.begin());
|
|
accept_const_iterator(s.cbegin());
|
|
accept_iterator(s.end());
|
|
accept_const_iterator(s.end());
|
|
accept_const_iterator(s.cend());
|
|
accept_reverse_iterator(s.rbegin());
|
|
accept_const_reverse_iterator(s.rbegin());
|
|
accept_const_reverse_iterator(s.crbegin());
|
|
accept_reverse_iterator(s.rend());
|
|
accept_const_reverse_iterator(s.rend());
|
|
accept_const_reverse_iterator(s.crend());
|
|
|
|
accept_reference(s[0]);
|
|
accept_reference(s.at(0));
|
|
accept_reference(s.front());
|
|
accept_reference(s.back());
|
|
}
|
|
|
|
TEST(IntSpan, NoexceptTest) {
|
|
int a[] = {1, 2, 3};
|
|
std::vector<int> v;
|
|
EXPECT_TRUE(noexcept(absl::Span<const int>()));
|
|
EXPECT_TRUE(noexcept(absl::Span<const int>(a, 2)));
|
|
EXPECT_TRUE(noexcept(absl::Span<const int>(a)));
|
|
EXPECT_TRUE(noexcept(absl::Span<const int>(v)));
|
|
EXPECT_TRUE(noexcept(absl::Span<int>(v)));
|
|
EXPECT_TRUE(noexcept(absl::Span<const int>({1, 2, 3})));
|
|
EXPECT_TRUE(noexcept(absl::MakeSpan(v)));
|
|
EXPECT_TRUE(noexcept(absl::MakeSpan(a)));
|
|
EXPECT_TRUE(noexcept(absl::MakeSpan(a, 2)));
|
|
EXPECT_TRUE(noexcept(absl::MakeSpan(a, a + 1)));
|
|
EXPECT_TRUE(noexcept(absl::MakeConstSpan(v)));
|
|
EXPECT_TRUE(noexcept(absl::MakeConstSpan(a)));
|
|
EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, 2)));
|
|
EXPECT_TRUE(noexcept(absl::MakeConstSpan(a, a + 1)));
|
|
|
|
absl::Span<int> s(v);
|
|
EXPECT_TRUE(noexcept(s.data()));
|
|
EXPECT_TRUE(noexcept(s.size()));
|
|
EXPECT_TRUE(noexcept(s.length()));
|
|
EXPECT_TRUE(noexcept(s.empty()));
|
|
EXPECT_TRUE(noexcept(s[0]));
|
|
EXPECT_TRUE(noexcept(s.front()));
|
|
EXPECT_TRUE(noexcept(s.back()));
|
|
EXPECT_TRUE(noexcept(s.begin()));
|
|
EXPECT_TRUE(noexcept(s.cbegin()));
|
|
EXPECT_TRUE(noexcept(s.end()));
|
|
EXPECT_TRUE(noexcept(s.cend()));
|
|
EXPECT_TRUE(noexcept(s.rbegin()));
|
|
EXPECT_TRUE(noexcept(s.crbegin()));
|
|
EXPECT_TRUE(noexcept(s.rend()));
|
|
EXPECT_TRUE(noexcept(s.crend()));
|
|
EXPECT_TRUE(noexcept(s.remove_prefix(0)));
|
|
EXPECT_TRUE(noexcept(s.remove_suffix(0)));
|
|
}
|
|
|
|
// ConstexprTester exercises expressions in a constexpr context. Simply placing
|
|
// the expression in a constexpr function is not enough, as some compilers will
|
|
// simply compile the constexpr function as runtime code. Using template
|
|
// parameters forces compile-time execution.
|
|
template <int i>
|
|
struct ConstexprTester {};
|
|
|
|
#define ABSL_TEST_CONSTEXPR(expr) \
|
|
do { \
|
|
ABSL_ATTRIBUTE_UNUSED ConstexprTester<(expr, 1)> t; \
|
|
} while (0)
|
|
|
|
struct ContainerWithConstexprMethods {
|
|
constexpr int size() const { return 1; }
|
|
constexpr const int* data() const { return &i; }
|
|
const int i;
|
|
};
|
|
|
|
TEST(ConstIntSpan, ConstexprTest) {
|
|
static constexpr int a[] = {1, 2, 3};
|
|
static constexpr int sized_arr[2] = {1, 2};
|
|
static constexpr ContainerWithConstexprMethods c{1};
|
|
ABSL_TEST_CONSTEXPR(absl::Span<const int>());
|
|
ABSL_TEST_CONSTEXPR(absl::Span<const int>(a, 2));
|
|
ABSL_TEST_CONSTEXPR(absl::Span<const int>(sized_arr));
|
|
ABSL_TEST_CONSTEXPR(absl::Span<const int>(c));
|
|
ABSL_TEST_CONSTEXPR(absl::MakeSpan(&a[0], 1));
|
|
ABSL_TEST_CONSTEXPR(absl::MakeSpan(c));
|
|
ABSL_TEST_CONSTEXPR(absl::MakeSpan(a));
|
|
ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(&a[0], 1));
|
|
ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(c));
|
|
ABSL_TEST_CONSTEXPR(absl::MakeConstSpan(a));
|
|
|
|
constexpr absl::Span<const int> span = c;
|
|
ABSL_TEST_CONSTEXPR(span.data());
|
|
ABSL_TEST_CONSTEXPR(span.size());
|
|
ABSL_TEST_CONSTEXPR(span.length());
|
|
ABSL_TEST_CONSTEXPR(span.empty());
|
|
ABSL_TEST_CONSTEXPR(span.begin());
|
|
ABSL_TEST_CONSTEXPR(span.cbegin());
|
|
ABSL_TEST_CONSTEXPR(span.subspan(0, 0));
|
|
ABSL_TEST_CONSTEXPR(span[0]);
|
|
}
|
|
|
|
struct BigStruct {
|
|
char bytes[10000];
|
|
};
|
|
|
|
TEST(Span, SpanSize) {
|
|
EXPECT_LE(sizeof(absl::Span<int>), 2 * sizeof(void*));
|
|
EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*));
|
|
}
|
|
|
|
} // namespace
|