OR-Tools  9.3
test_util_test.cc
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <cmath>
17#include <deque>
18#include <limits>
19#include <list>
20#include <vector>
21
22#include "Eigen/Core"
23#include "absl/types/span.h"
24#include "gmock/gmock.h"
25#include "gtest/gtest.h"
27
29namespace {
30
31using ::absl::Span;
32using ::Eigen::ColMajor;
33using ::Eigen::Dynamic;
34using ::Eigen::RowMajor;
35using ::testing::Matcher;
37
38TEST(FloatArrayNearTest, TypicalUse) {
39 std::vector<double> test_vector({0.998, -1.414, 3.142});
40 std::vector<double> reference_vector({1.0, -M_SQRT2, M_PI});
41 EXPECT_THAT(test_vector, FloatArrayNear(reference_vector, 1e-2));
42 EXPECT_THAT(test_vector, Not(FloatArrayNear(reference_vector, 1e-4)));
43}
44
45template <typename ContainerType>
46class FloatArrayNearContainerTypeTest : public testing::Test {};
47
48using TestContainerTypes = testing::Types<std::vector<float>, std::deque<float>,
49 std::list<float>, Span<const float>>;
50TYPED_TEST_SUITE(FloatArrayNearContainerTypeTest, TestContainerTypes);
51
52TYPED_TEST(FloatArrayNearContainerTypeTest, MatchesApproximately) {
53 using ContainerType = TypeParam;
54 auto test_values = {0.505f, 1.0f, -0.992f, 1.995f};
55 ContainerType test_container(test_values);
56 auto reference_values = {0.5f, 1.0f, -1.0f, 2.0f};
57 ContainerType reference_container(reference_values);
58
59 const Matcher<ContainerType> m1 = FloatArrayNear(reference_container, 1e-2);
60 EXPECT_TRUE(m1.Matches(test_container));
61 const Matcher<ContainerType> m2 = FloatArrayNear(reference_container, 1e-3);
62 EXPECT_FALSE(m2.Matches(test_container));
63}
64
65TYPED_TEST(FloatArrayNearContainerTypeTest, DoesNotMatchWrongSize) {
66 using ContainerType = TypeParam;
67 EXPECT_THAT(ContainerType({1.0f, 2.0f}),
68 Not(FloatArrayNear(ContainerType({1.0f, 2.0f, 3.0f}), 1e-2)));
69}
70
71TYPED_TEST(FloatArrayNearContainerTypeTest, DoesNotMatchWrongOrder) {
72 using ContainerType = TypeParam;
73 EXPECT_THAT(ContainerType({1.0f, 3.0f, 2.0f}),
74 Not(FloatArrayNear(ContainerType({1.0f, 2.0f, 3.0f}), 1e-2)));
75}
76
77TYPED_TEST(FloatArrayNearContainerTypeTest, DoesNotMatchNaNs) {
78 using ContainerType = TypeParam;
79 auto test_values = {1.0f, std::numeric_limits<float>::quiet_NaN()};
80 ContainerType test_container(test_values);
81
82 EXPECT_THAT(test_container,
83 Not(FloatArrayNear(ContainerType({1.0f, 2.0f}), 1e0)));
84 EXPECT_THAT(test_container, Not(FloatArrayNear(test_container, 1e0)));
85}
86
87TEST(FloatArrayNearTest, WithIntegerElements) {
88 std::vector<int> test_vector({505, 1000, -992, 1990});
89 std::vector<int> reference_vector({500, 1000, -1000, 2000});
90
91 const Matcher<std::vector<int>> m1 = FloatArrayNear(reference_vector, 10);
92 EXPECT_TRUE(m1.Matches(test_vector));
93 const Matcher<std::vector<int>> m2 = FloatArrayNear(reference_vector, 1);
94 EXPECT_FALSE(m2.Matches(test_vector));
95}
96
97TEST(FloatArrayEqTest, TypicalUse) {
98 std::vector<float> reference_vector({1e6, -M_SQRT2, M_PI});
99 // Values are within 4 ULPs.
100 std::vector<float> test_vector({1e6 + 0.25, -1.41421323, 3.14159262});
101 EXPECT_THAT(test_vector, FloatArrayEq(reference_vector));
102 // Create a difference of 5 ULPs in the first element.
103 test_vector[0] = 1e6 + 0.3125;
104 EXPECT_THAT(test_vector, Not(FloatArrayEq(reference_vector)));
105}
106
107template <typename ContainerType>
108class FloatArrayEqContainerTypeTest : public testing::Test {};
109
110TYPED_TEST_SUITE(FloatArrayEqContainerTypeTest, TestContainerTypes);
111
112TYPED_TEST(FloatArrayEqContainerTypeTest, MatchesApproximately) {
113 using ContainerType = TypeParam;
114 auto reference_values = {-1e6f, 0.0f, 1.0f};
115 ContainerType reference_container(reference_values);
116 const Matcher<ContainerType> m = FloatArrayEq(reference_container);
117 EXPECT_TRUE(m.Matches(reference_container));
118 EXPECT_TRUE(m.Matches(ContainerType({-1e6 + 0.25, 5e-45, 1.0000002})));
119 EXPECT_TRUE(m.Matches(ContainerType({-1e6 - 0.25, -5e-45, 0.9999998})));
120 EXPECT_FALSE(m.Matches(ContainerType({-1e6 + 0.3125, 0.0, 1.0})));
121 EXPECT_FALSE(m.Matches(ContainerType({-1e6, 1e-44, 1.0})));
122 EXPECT_FALSE(m.Matches(ContainerType({-1e6, 0.0, 1.0000006})));
123}
124
125TYPED_TEST(FloatArrayEqContainerTypeTest, DoesNotMatchWrongSize) {
126 using ContainerType = TypeParam;
127 EXPECT_THAT(ContainerType({1.0f, 2.0f}),
128 Not(FloatArrayEq(ContainerType({1.0f, 2.0f, 3.0f}))));
129}
130
131TYPED_TEST(FloatArrayEqContainerTypeTest, DoesNotMatchWrongOrder) {
132 using ContainerType = TypeParam;
133 EXPECT_THAT(ContainerType({1.0f, 3.0f, 2.0f}),
134 Not(FloatArrayEq(ContainerType({1.0f, 2.0f, 3.0f}))));
135}
136
137TYPED_TEST(FloatArrayEqContainerTypeTest, DoesNotMatchNaNs) {
138 using ContainerType = TypeParam;
139 auto reference_values = {1.0f, std::numeric_limits<float>::quiet_NaN()};
140 ContainerType reference_container(reference_values);
141 const Matcher<ContainerType> m = FloatArrayEq(reference_container);
142 EXPECT_FALSE(m.Matches(reference_container));
143 EXPECT_FALSE(m.Matches(ContainerType({1.0f, 2.0f})));
144}
145
146TYPED_TEST(FloatArrayEqContainerTypeTest, HandlesInfinities) {
147 using ContainerType = TypeParam;
148 auto reference_values = {1.0f, std::numeric_limits<float>::infinity(),
149 -std::numeric_limits<float>::infinity()};
150 ContainerType reference_container(reference_values);
151 const Matcher<ContainerType> m = FloatArrayEq(reference_container);
152 EXPECT_TRUE(m.Matches(reference_container));
153 EXPECT_FALSE(m.Matches(ContainerType({1.0f, 2.0f, 3.0f})));
154}
155
156static const double kEps = 1e-6;
157
158TEST(EigenArrayNearTest, ArrayXd) {
159 const Eigen::ArrayXd expected = Eigen::ArrayXd::Random(4);
160 Eigen::ArrayXd actual = expected;
161 EXPECT_THAT(actual, EigenArrayNear(expected, kEps));
162 EXPECT_THAT(actual, EigenArrayNear(expected, 1e-100));
163
164 actual += 100;
165 EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
166 // Wrong shape.
167 actual.resize(2);
168 EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
169}
170
171TEST(EigenArrayNearTest, ArrayXdInlinedValues) {
172 Eigen::ArrayXd actual(3);
173 actual << 1.0, 2.0, 3.0;
174 EXPECT_THAT(actual, EigenArrayNear<double>({1.0, 2.0, 3.0}, kEps));
175 EXPECT_THAT(actual,
176 EigenArrayNear<double>({1.0, 2.0 + 0.5 * kEps, 3.0}, kEps));
177
178 EXPECT_THAT(actual, Not(EigenArrayNear<double>({1.0, 2.0, 5.0}, kEps)));
179 // Wrong shape.
180 EXPECT_THAT(actual, Not(EigenArrayNear<double>({1.0, 2.0}, kEps)));
181}
182
183TEST(EigenArrayNearTest, EmptyArrayX) {
184 const Eigen::ArrayXi empty;
185 EXPECT_THAT(empty, EigenArrayNear(empty, kEps));
186 // Can pass in an Eigen expression type.
187 EXPECT_THAT(empty, EigenArrayNear(Eigen::ArrayXi(), kEps));
188
189 EXPECT_THAT(empty, Not(EigenArrayNear<int>({1, 2}, kEps)));
190 EXPECT_THAT(empty, Not(EigenArrayNear(Eigen::ArrayXi::Zero(3), kEps)));
191}
192
193TEST(EigenArrayNearTest, ArrayXXf) {
194 const Eigen::ArrayXXf expected = Eigen::ArrayXXf::Random(4, 5);
195 Eigen::ArrayXXf actual = expected;
196 EXPECT_THAT(actual, EigenArrayNear(expected, kEps));
197 EXPECT_THAT(actual, EigenArrayNear(expected, 1e-100));
198
199 actual.row(2) += 100;
200 EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
201 // Wrong shape.
202 EXPECT_THAT(expected, Not(EigenArrayNear(expected.transpose(), kEps)));
203 actual.resize(4, 3);
204 EXPECT_THAT(actual, Not(EigenArrayNear(expected, kEps)));
205
206 // Expression type.
207 actual.resize(3, 2);
208 actual.col(0) << 1.0, 2.0, 3.0;
209 actual.col(1) << 4.0, 5.0, 6.0;
210 std::vector<float> expected_vector({1.0, 2.0, 3.0, 4.0, 5.0, 6.0});
211 EXPECT_THAT(actual, EigenArrayNear(Eigen::Map<Eigen::ArrayXXf>(
212 &expected_vector[0], /*rows=*/3,
213 /*cols=*/2),
214 kEps));
215 // Wrong shape.
216 EXPECT_THAT(actual, Not(EigenArrayNear(Eigen::Map<Eigen::ArrayXXf>(
217 &expected_vector[0], /*rows=*/3,
218 /*cols=*/1),
219 kEps)));
220}
221
222TEST(EigenArrayNearTest, DifferentMajor) {
223 Eigen::Array<float, Dynamic, Dynamic, ColMajor> col_major(2, 3);
224 col_major << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0;
225 Eigen::Array<float, Dynamic, Dynamic, RowMajor> row_major(2, 3);
226 row_major << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0;
227 CHECK_EQ(col_major(1, 0), row_major(1, 0));
228
229 EXPECT_THAT(row_major, EigenArrayNear(col_major, 0.0));
230 EXPECT_THAT(row_major, EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
231 {4.0, 5.0, 6.0}},
232 0.0));
233 EXPECT_THAT(col_major, EigenArrayNear(row_major, 0.0));
234 EXPECT_THAT(col_major, EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
235 {4.0, 5.0, 6.0}},
236 0.0));
237}
238
239TEST(EigenArrayNearTest, ArrayXXfInlinedValues) {
240 Eigen::ArrayXXf actual(2, 3);
241 actual.row(0) << 1.0, 2.0, 3.0;
242 actual.row(1) << 4.0, -5.0, -6.0;
243
244 EXPECT_THAT(actual, EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
245 {4.0, -5.0, -6.0}},
246 kEps));
247 EXPECT_THAT(actual, EigenArrayNear<float>(
248 {{1.0, 2.0, 3.0},
249 {4.0, -5.0, static_cast<float>(-6.0 - 0.9 * kEps)}},
250 kEps));
251 EXPECT_THAT(actual, Not(EigenArrayNear<float>({{1.0, 2.0, 3.0}, //
252 {4.0, -5.0, -8.0}},
253 kEps)));
254 // Wrong shape.
255 EXPECT_THAT(actual, Not(EigenArrayNear<float>({{1.0, 2.0, 3.0}}, kEps)));
256}
257
258TEST(EigenArrayEqTest, ArrayXd) {
259 const Eigen::ArrayXd expected = Eigen::ArrayXd::Random(4);
260 Eigen::ArrayXd actual = expected;
261 EXPECT_THAT(actual, EigenArrayEq(expected));
262
263 actual += 100;
264 EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
265 // Wrong shape.
266 actual.resize(2);
267 EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
268}
269
270TEST(EigenArrayEqTest, ArrayXdInlinedValues) {
271 Eigen::ArrayXd actual(3);
272 actual << 1.0, 2.0, 3.0;
273 EXPECT_THAT(actual, EigenArrayEq<double>({1.0, 2.0, 3.0}));
274 EXPECT_THAT(actual, EigenArrayEq<double>({1.0, 2.0 + 5e-7, 3.0}));
275
276 EXPECT_THAT(actual, Not(EigenArrayEq<double>({1.0, 2.0, 5.0})));
277 // Wrong shape.
278 EXPECT_THAT(actual, Not(EigenArrayEq<double>({1.0, 2.0})));
279}
280
281TEST(EigenArrayEqTest, EmptyArrayX) {
282 const Eigen::ArrayXi empty;
283 EXPECT_THAT(empty, EigenArrayEq(empty));
284 // Can pass in an Eigen expression type.
285 EXPECT_THAT(empty, EigenArrayEq(Eigen::ArrayXi()));
286
287 EXPECT_THAT(empty, Not(EigenArrayEq<int>({1, 2})));
288 EXPECT_THAT(empty, Not(EigenArrayEq(Eigen::ArrayXi::Zero(3))));
289}
290
291TEST(EigenArrayEqTest, ArrayXXf) {
292 const Eigen::ArrayXXf expected = Eigen::ArrayXXf::Random(4, 5);
293 Eigen::ArrayXXf actual = expected;
294 EXPECT_THAT(actual, EigenArrayEq(expected));
295
296 actual.row(2) += 100;
297 EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
298 // Wrong shape.
299 EXPECT_THAT(expected, Not(EigenArrayEq(expected.transpose())));
300 actual.resize(4, 3);
301 EXPECT_THAT(actual, Not(EigenArrayEq(expected)));
302
303 // Expression type.
304 actual.resize(3, 2);
305 actual.col(0) << 1.0, 2.0, 3.0;
306 actual.col(1) << 4.0, 5.0, 6.0;
307 std::vector<float> expected_vector({1.0, 2.0, 3.0, 4.0, 5.0, 6.0});
308 EXPECT_THAT(actual, EigenArrayEq(Eigen::Map<Eigen::ArrayXXf>(
309 &expected_vector[0], /*rows=*/3, /*cols=*/2)));
310 // Wrong shape.
311 EXPECT_THAT(actual, Not(EigenArrayEq(Eigen::Map<Eigen::ArrayXXf>(
312 &expected_vector[0], /*rows=*/3, /*cols=*/1))));
313}
314
315TEST(EigenArrayEqTest, ArrayXXfInlinedValues) {
316 Eigen::ArrayXXf actual(2, 3);
317 actual.row(0) << 1.0, 2.0, 3.0;
318 actual.row(1) << 4.0, -5.0, -6.0;
319
320 EXPECT_THAT(actual, EigenArrayEq<float>({{1.0, 2.0, 3.0}, //
321 {4.0, -5.0, -6.0}}));
322 EXPECT_THAT(actual, EigenArrayEq<float>({{1.0, 2.0, 3.0}, //
323 {4.0, -5.0, -6.0 - 1e-6}}));
324 EXPECT_THAT(actual, Not(EigenArrayEq<float>({{1.0, 2.0, 3.0}, //
325 {4.0, -5.0, -8.0}})));
326 // Wrong shape.
327 EXPECT_THAT(actual, Not(EigenArrayEq<float>({{1.0, 2.0, 3.0}})));
328}
329
330} // namespace
331} // namespace operations_research::pdlp
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:703
EigenArrayNearMatcherP2< Eigen::Array< T, Eigen::Dynamic, 1 >, double > EigenArrayNear(absl::Span< const T > data, double tolerance)
Definition: test_util.h:375
decltype(testing::Pointwise(internal::TupleFloatEq(), ContainerType())) FloatArrayEq(const ContainerType &container)
Definition: test_util.h:289
EigenArrayEqMatcherP< Eigen::Array< T, Eigen::Dynamic, 1 > > EigenArrayEq(absl::Span< const T > data)
Definition: test_util.h:389
decltype(testing::Pointwise(internal::TupleIsNear(0.0), ContainerType())) FloatArrayNear(const ContainerType &container, double tolerance)
Definition: test_util.h:271
BoolVar Not(BoolVar x)
A convenient wrapper so we can write Not(x) instead of x.Not() which is sometimes clearer.
Definition: cp_model.cc:87
int64_t Zero()
NOLINT.
TEST(LinearAssignmentTest, NullMatrix)