1//
2// immer: immutable data structures for C++
3// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4//
5// This software is distributed under the Boost Software License, Version 1.0.
6// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7//
8
9#pragma once
10
11#include <boost/range/irange.hpp>
12#include <boost/range/join.hpp>
13#include <cstddef>
14
15namespace {
16
17struct identity_t
18{
19 template <typename T>
20 decltype(auto) operator() (T&& x)
21 {
22 return std::forward<decltype(x)>(x);
23 }
24};
25
26template <typename Integer>
27auto test_irange(Integer from, Integer to)
28{
29#if IMMER_SLOW_TESTS
30 return boost::irange(from, to);
31#else
32 if (to - from < Integer{10})
33 return boost::join(
34 boost::irange(Integer{}, Integer{}),
35 boost::join(boost::irange(from, to, 1),
36 boost::irange(Integer{}, Integer{})));
37 else
38 return boost::join(
39 boost::irange(from, from + Integer{2}),
40 boost::join(
41 boost::irange(from + Integer{2},
42 to - Integer{2},
43 (to - from) / Integer{5}),
44 boost::irange(to - Integer{2}, to)));
45#endif
46}
47
48} // anonymous namespace
49
50#if IMMER_SLOW_TESTS
51#define CHECK_SLOW(...) CHECK(__VA_ARGS__)
52#else
53#define CHECK_SLOW(...)
54#endif
55
56#if IMMER_SLOW_TESTS
57#define CHECK_VECTOR_EQUALS_RANGE_AUX(v1_, first_, last_, xf_) \
58 [] (auto&& v1, auto&& first, auto&& last, auto&& xf) { \
59 auto size = std::distance(first, last); \
60 CHECK(static_cast<std::ptrdiff_t>(v1.size()) == size); \
61 if (static_cast<std::ptrdiff_t>(v1.size()) != size) return; \
62 for (auto j = 0u; j < size; ++j) \
63 CHECK(xf(v1[j]) == xf(*first++)); \
64 } (v1_, first_, last_, xf_) \
65 // CHECK_EQUALS
66#else
67#define CHECK_VECTOR_EQUALS_RANGE_AUX(v1_, first_, last_, ...) \
68 [] (auto&& v1, auto&& first, auto&& last, auto&& xf) { \
69 auto size = std::distance(first, last); \
70 CHECK(static_cast<std::ptrdiff_t>(v1.size()) == size); \
71 if (static_cast<std::ptrdiff_t>(v1.size()) != size) return; \
72 if (size > 0) { \
73 CHECK(xf(v1[0]) == xf(*(first + (0)))); \
74 CHECK(xf(v1[size - 1]) == xf(*(first + (size - 1)))); \
75 CHECK(xf(v1[size / 2]) == xf(*(first + (size / 2)))); \
76 CHECK(xf(v1[size / 3]) == xf(*(first + (size / 3)))); \
77 CHECK(xf(v1[size / 4]) == xf(*(first + (size / 4)))); \
78 CHECK(xf(v1[size - 1 - size / 2]) == xf(*(first + (size - 1 - size / 2)))); \
79 CHECK(xf(v1[size - 1 - size / 3]) == xf(*(first + (size - 1 - size / 3)))); \
80 CHECK(xf(v1[size - 1 - size / 4]) == xf(*(first + (size - 1 - size / 4)))); \
81 } \
82 if (size > 1) { \
83 CHECK(xf(v1[1]) == xf(*(first + (1)))); \
84 CHECK(xf(v1[size - 2]) == xf(*(first + (size - 2)))); \
85 } \
86 if (size > 2) { \
87 CHECK(xf(v1[2]) == xf(*(first + (2)))); \
88 CHECK(xf(v1[size - 3]) == xf(*(first + (size - 3)))); \
89 } \
90 } (v1_, first_, last_, __VA_ARGS__) \
91 // CHECK_EQUALS
92#endif // IMMER_SLOW_TESTS
93
94#define CHECK_VECTOR_EQUALS_AUX(v1_, v2_, ...) \
95 [] (auto&& v1, auto&& v2, auto&& ...xs) { \
96 CHECK_VECTOR_EQUALS_RANGE_AUX(v1, v2.begin(), v2.end(), xs...); \
97 } (v1_, v2_, __VA_ARGS__)
98
99#define CHECK_VECTOR_EQUALS_RANGE(v1, b, e) \
100 CHECK_VECTOR_EQUALS_RANGE_AUX((v1), (b), (e), identity_t{})
101
102#define CHECK_VECTOR_EQUALS(v1, v2) \
103 CHECK_VECTOR_EQUALS_AUX((v1), (v2), identity_t{})
104