From fb911942f1434f3d1750f83f25f5e42c80e60638 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Tue, 24 Mar 2015 21:31:36 +0000 Subject: Vendor import of lld trunk r233088: https://llvm.org/svn/llvm-project/lld/trunk@233088 --- unittests/CoreTests/RangeTest.cpp | 240 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 unittests/CoreTests/RangeTest.cpp (limited to 'unittests/CoreTests/RangeTest.cpp') diff --git a/unittests/CoreTests/RangeTest.cpp b/unittests/CoreTests/RangeTest.cpp new file mode 100644 index 0000000000000..2b2fcd5f78753 --- /dev/null +++ b/unittests/CoreTests/RangeTest.cpp @@ -0,0 +1,240 @@ +//===- lld/unittest/RangeTest.cpp -----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief range.h unit tests. +/// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "lld/Core/range.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template struct AssertTypesSame; +template struct AssertTypesSame {}; +#define ASSERT_TYPES_SAME(T, U) AssertTypesSame() + +struct no_begin {}; +struct member_begin { + int *begin(); +}; +struct free_begin {}; +int *begin(free_begin); + +template +auto type_of_forward(T &&t) -> decltype(std::forward(t)) { + return std::forward(t); +} + +template To implicit_cast(To val) { return val; } + +void test_traits() { + using namespace lld::detail; + ASSERT_TYPES_SAME(begin_result::type, undefined); + // This causes clang to segfault. +#if 0 + ASSERT_TYPES_SAME( + begin_result::type, int *); +#endif + ASSERT_TYPES_SAME(begin_result::type, int *); +} + +TEST(Range, constructors) { + std::vector v(5); + std::iota(v.begin(), v.end(), 0); + lld::range::iterator> r = v; + EXPECT_EQ(v.begin(), r.begin()); + EXPECT_EQ(v.end(), r.end()); + + int arr[] = { 1, 2, 3, 4, 5 }; + std::begin(arr); + lld::range r2 = arr; + EXPECT_EQ(5, r2.back()); +} + +TEST(Range, conversion_to_pointer_range) { + std::vector v(5); + std::iota(v.begin(), v.end(), 0); + lld::range r = v; + EXPECT_EQ(&*v.begin(), r.begin()); + EXPECT_EQ(2, r[2]); +} + +template void takes_range(lld::range r) { + int expected = 0; + for (int val : r) { + EXPECT_EQ(expected++, val); + } +} + +void takes_ptr_range(lld::range r) { + int expected = 0; + for (int val : r) { + EXPECT_EQ(expected++, val); + } +} + +TEST(Range, passing) { + using lld::make_range; + using lld::make_ptr_range; + std::list l(5); + std::iota(l.begin(), l.end(), 0); + takes_range(make_range(l)); + takes_range(make_range(implicit_cast &>(l))); + std::deque d(5); + std::iota(d.begin(), d.end(), 0); + takes_range(make_range(d)); + takes_range(make_range(implicit_cast &>(d))); + std::vector v(5); + std::iota(v.begin(), v.end(), 0); + takes_range(make_range(v)); + takes_range(make_range(implicit_cast &>(v))); + static_assert( + std::is_same>::value, + "make_ptr_range should return a range of pointers"); + takes_range(make_ptr_range(v)); + takes_range(make_ptr_range(implicit_cast &>(v))); + int arr[] = { 0, 1, 2, 3, 4 }; + takes_range(make_range(arr)); + const int carr[] = { 0, 1, 2, 3, 4 }; + takes_range(make_range(carr)); + + takes_ptr_range(v); + takes_ptr_range(implicit_cast &>(v)); + takes_ptr_range(arr); + takes_ptr_range(carr); +} + +TEST(Range, access) { + std::array a = { { 1, 2, 3, 4, 5 } }; + lld::range r = a; + EXPECT_EQ(4, r[3]); + EXPECT_EQ(4, r[-2]); +} + +template struct CompileAssert; +template <> struct CompileAssert {}; + +#if __has_feature(cxx_constexpr) +constexpr int arr[] = { 1, 2, 3, 4, 5 }; +TEST(Range, constexpr) { + constexpr lld::range r(arr, arr + 5); + CompileAssert(); + CompileAssert(); + CompileAssert(); +} +#endif + +template void test_slice() { + Container cont(10); + std::iota(cont.begin(), cont.end(), 0); + lld::range r = cont; + + // One argument. + EXPECT_EQ(10, r.slice(0).size()); + EXPECT_EQ(8, r.slice(2).size()); + EXPECT_EQ(2, r.slice(2).front()); + EXPECT_EQ(1, r.slice(-1).size()); + EXPECT_EQ(9, r.slice(-1).front()); + + // Two positive arguments. + EXPECT_TRUE(r.slice(5, 2).empty()); + EXPECT_EQ(next(cont.begin(), 5), r.slice(5, 2).begin()); + EXPECT_EQ(1, r.slice(1, 2).size()); + EXPECT_EQ(1, r.slice(1, 2).front()); + + // Two negative arguments. + EXPECT_TRUE(r.slice(-2, -5).empty()); + EXPECT_EQ(next(cont.begin(), 8), r.slice(-2, -5).begin()); + EXPECT_EQ(1, r.slice(-2, -1).size()); + EXPECT_EQ(8, r.slice(-2, -1).front()); + + // Positive start, negative stop. + EXPECT_EQ(1, r.slice(6, -3).size()); + EXPECT_EQ(6, r.slice(6, -3).front()); + EXPECT_TRUE(r.slice(6, -5).empty()); + EXPECT_EQ(next(cont.begin(), 6), r.slice(6, -5).begin()); + + // Negative start, positive stop. + EXPECT_TRUE(r.slice(-3, 6).empty()); + EXPECT_EQ(next(cont.begin(), 7), r.slice(-3, 6).begin()); + EXPECT_EQ(1, r.slice(-5, 6).size()); + EXPECT_EQ(5, r.slice(-5, 6).front()); +} + +TEST(Range, slice) { + // -fsanitize=undefined complains about this, but only if optimizations are + // enabled. +#if 0 + test_slice>(); +#endif + test_slice>(); +// This doesn't build with libstdc++ 4.7 +#if 0 + test_slice>(); +#endif +} + +// This test is flaky and I've yet to pin down why. Changing between +// EXPECT_EQ(1, input.front()) and EXPECT_TRUE(input.front() == 1) makes it work +// with VS 2012 in Debug mode. Clang on Linux seems to fail with -03 and -02 -g +// -fsanitize=undefined. +#if 0 +TEST(Range, istream_range) { + std::istringstream stream("1 2 3 4 5"); + // MSVC interprets input as a function declaration if you don't declare start + // and instead directly pass std::istream_iterator(stream). + auto start = std::istream_iterator(stream); + lld::range> input( + start, std::istream_iterator()); + EXPECT_TRUE(input.front() == 1); + input.pop_front(); + EXPECT_TRUE(input.front() == 2); + input.pop_front(2); + EXPECT_TRUE(input.front() == 4); + input.pop_front_upto(7); + EXPECT_TRUE(input.empty()); +} +#endif + +//! [algorithm using range] +template void partial_sum(T &container) { + using lld::make_range; + auto range = make_range(container); + typename T::value_type sum = 0; + // One would actually use a range-based for loop + // in this case, but you get the idea: + for (; !range.empty(); range.pop_front()) { + sum += range.front(); + range.front() = sum; + } +} + +TEST(Range, user1) { + std::vector v(5, 2); + partial_sum(v); + EXPECT_EQ(8, v[3]); +} +//! [algorithm using range] + +//! [algorithm using ptr_range] +void my_write(int fd, lld::range buffer) {} + +TEST(Range, user2) { + std::string s("Hello world"); + my_write(1, s); +} -- cgit v1.2.3