1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 #pragma once
7 
8 #include "gtest/gtest.h"
9 
10 #include <Eigen/Core>
11 #include <type_traits>
12 
13 namespace alps { namespace testing {
14 
15 template <typename T>
16 struct is_scalar : public std::false_type { };
17 
18 template <typename T>
19 struct is_scalar< std::complex<T> > : public is_scalar<T> { };
20 
21 template <> struct is_scalar<float> : public std::true_type { };
22 template <> struct is_scalar<double> : public std::true_type { };
23 template <> struct is_scalar<long double> : public std::true_type { };
24 
25 /** Helper function for implementing ALPS_EXPECT_NEAR. */
26 template <typename T,
27           typename std::enable_if<is_scalar<T>::value,int>::type = 0>
NearPredFormat(const char * expr1,const char * expr2,const char * abs_error_expr,const T & val1,const T & val2,double abs_error)28 ::testing::AssertionResult NearPredFormat(const char* expr1,
29                                           const char* expr2,
30                                           const char* abs_error_expr,
31                                           const T &val1,
32                                           const T &val2,
33                                           double abs_error)
34 {
35     const double diff = std::abs(val1 - val2);
36     if (diff <= abs_error)
37         return ::testing::AssertionSuccess();
38 
39     return ::testing::AssertionFailure()
40         << "The difference between " << expr1 << " and " << expr2
41         << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
42         << expr1 << " evaluates to " << val1 << ",\n"
43         << expr2 << " evaluates to " << val2 << ".";
44 }
45 
46 /** Helper function for implementing ALPS_EXPECT_NEAR. */
47 template <typename Derived1, typename Derived2>
NearPredFormat(const char * expr1,const char * expr2,const char * abs_error_expr,const Eigen::MatrixBase<Derived1> & val1,const Eigen::MatrixBase<Derived2> & val2,double abs_error)48 ::testing::AssertionResult NearPredFormat(const char* expr1,
49                                           const char* expr2,
50                                           const char* abs_error_expr,
51                                           const Eigen::MatrixBase<Derived1> &val1,
52                                           const Eigen::MatrixBase<Derived2> &val2,
53                                           double abs_error)
54 {
55     if (val1.isApprox(val2, abs_error))
56         return ::testing::AssertionSuccess();
57 
58     return ::testing::AssertionFailure()
59            << "The difference between " << expr1 << " and " << expr2
60            << " exceeds " << abs_error_expr << ", where\n"
61            << expr1 << " evaluates to\n" << val1 << ",\n"
62            << expr2 << " evaluates to\n" << val2 << "\n.";
63 }
64 
65 }}  /* namespace alps::testing */
66 
67 /**
68  * Extends gtest's EXPECT_NEAR to complex variables and Eigen matrices
69  */
70 #define ALPS_EXPECT_NEAR(val1, val2, abs_error) \
71     EXPECT_PRED_FORMAT3(::alps::testing::NearPredFormat, val1, val2, abs_error)
72 
73