1 /* *****************************************************************
2     MESQUITE -- The Mesh Quality Improvement Toolkit
3 
4     Copyright 2006 Lawrence Livermore National Laboratory.  Under
5     the terms of Contract B545069 with the University of Wisconsin --
6     Madison, Lawrence Livermore National Laboratory retains certain
7     rights in this software.
8 
9     This library is free software; you can redistribute it and/or
10     modify it under the terms of the GNU Lesser General Public
11     License as published by the Free Software Foundation; either
12     version 2.1 of the License, or (at your option) any later version.
13 
14     This library is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17     Lesser General Public License for more details.
18 
19     You should have received a copy of the GNU Lesser General Public License
20     (lgpl.txt) along with this library; if not, write to the Free Software
21     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 
23     (2006) kraftche@cae.wisc.edu
24 
25   ***************************************************************** */
26 
27 
28 /** \file UnitUtil.hpp
29  *  \brief Utility functions for use in unit tests
30  *  \author Jason Kraftcheck
31  */
32 
33 #ifndef MSQ_UNIT_UTIL_HPP
34 #define MSQ_UNIT_UTIL_HPP
35 
36 #include "Mesquite.hpp"
37 #include "Vector3D.hpp"
38 #include "Matrix3D.hpp"
39 #include "MsqMatrix.hpp"
40 #include "MsqError.hpp"
41 
42 #include <string>
43 #include <stdio.h>
44 
45 #include "cppunit/extensions/HelperMacros.h"
46 
47 #define ASSERT_MESSAGE( MSG, COND ) \
48   CPPUNIT_NS::Asserter::failIf( !(COND), (MSG), CPPUNIT_SOURCELINE() )
49 
50 /** Assert that MBMesquite API has not flagged an error */
51 #define ASSERT_NO_ERROR( A ) \
52   ASSERT_MESSAGE( (A).error_message(), ! MSQ_CHKERR( (A) ) )
53 
54 /**\brief compare two vectors (Vector3D)
55  *
56  * Ensure that the test result Vector3D \a v2 is within \a eps of the
57  * expected vector \a v1 .
58  */
59 #define CPPUNIT_ASSERT_VECTORS_EQUAL( v1, v2, eps ) \
60   ASSERT_MESSAGE( utest_vect_message((v1),(v2)), \
61                           utest_vect_equal((v1),(v2),(eps)) )
62 
63 /**\brief compare two matrices (Matrix3D)
64  *
65  * Ensure that the test result Matrix3D \a m2 is within \a eps of the
66  * expected matrix \a m1
67  */
68 #define CPPUNIT_ASSERT_MATRICES_EQUAL( m1, m2, eps ) \
69   ASSERT_MESSAGE( utest_mat_message((m1),(m2)), \
70                           utest_mat_equal((m1),(m2),(eps)) )
71 
72 
73 /** compare matrix (MsqMatrix) with the identity matrix  */
74 #define ASSERT_IDENTITY_MATRIX( M ) \
75   ASSERT_MESSAGE( ident_check_msg(M), ident_check(M) )
76 
77 /** compare two matrices (MsqMatrix) */
78 #define ASSERT_MATRICES_EQUAL( A, B, E ) \
79   ASSERT_MESSAGE( mat_equal_check_msg( A, B), mat_equal_check(A,B,E) )
80 
81 /** compare two matrices (MsqMatrix) */
82 #define ASSERT_MATRICES_DIFFERENT( A, B, E ) \
83   ASSERT_MESSAGE( mat_not_equal_check_msg(A, B), !mat_equal_check(A,B,E) )
84 
85 /** compare two arrays of values */
86 #define ASSERT_ARRAYS_EQUAL( A, B, LEN ) \
87   CPPUNIT_NS::Asserter::failIf( !(arrays_equal((A),(B),(LEN))), arrays_not_equal_msg((A),(LEN),(B),(LEN)), CPPUNIT_SOURCELINE() )
88 
89 #define ASSERT_STD_VECTORS_EQUAL( A, B ) \
90   CPPUNIT_NS::Asserter::failIf( ((A) != (B)), arrays_not_equal_msg(&(A)[0],(A).size(),&(B)[0],(B).size()), CPPUNIT_SOURCELINE() )
91 
92 
93 /** make string representation of cartesian vector */
utest_vect_str(const MBMesquite::Vector3D & v)94 inline std::string utest_vect_str( const MBMesquite::Vector3D& v )
95 {
96   char buffer[128];
97   sprintf(buffer, "[%f, %f, %f]", v[0], v[1], v[2]);
98   return buffer;
99 }
100 
101 /** make string representation of 3x3 matrix */
utest_mat_str(const MBMesquite::Matrix3D & m)102 inline std::string utest_mat_str( const MBMesquite::Matrix3D& m )
103 {
104   char buffer[256];
105   sprintf(buffer, "[%f, %f, %f] [%f, %f, %f] [%f, %f, %f]",
106           m[0][0], m[0][1], m[0][2],
107           m[1][0], m[1][1], m[1][2],
108           m[2][0], m[2][1], m[2][2] );
109   return buffer;
110 }
111 
112 /** make string representation of 3x3 symetric matrix */
utest_mat_str(const MBMesquite::SymMatrix3D & m)113 inline std::string utest_mat_str( const MBMesquite::SymMatrix3D& m )
114 {
115   char buffer[256];
116   sprintf(buffer, "[%f, %f, %f] [%f, %f, %f] [%f, %f, %f]",
117           m(0,0), m(0,1), m(0,2),
118           m(1,0), m(1,1), m(1,2),
119           m(2,0), m(2,1), m(2,2) );
120   return buffer;
121 }
122 
123 /** make error message for failed vector copmarison */
utest_vect_message(const MBMesquite::Vector3D & v1,const MBMesquite::Vector3D & v2)124 inline CppUnit::Message utest_vect_message( const MBMesquite::Vector3D& v1,
125                                       const MBMesquite::Vector3D& v2 )
126 {
127   CppUnit::Message m( "equality assertion failed" );
128   m.addDetail( std::string("Expected: ") + utest_vect_str(v1) );
129   m.addDetail( std::string("Actual  : ") + utest_vect_str(v2) );
130   return m;
131 }
132 
133 /** make error message for failed matrix copmarison */
utest_mat_message(const MBMesquite::Matrix3D & m1,const MBMesquite::Matrix3D & m2)134 inline CppUnit::Message utest_mat_message( const MBMesquite::Matrix3D& m1,
135                                      const MBMesquite::Matrix3D& m2 )
136 {
137   CppUnit::Message m( "equality assertion failed" );
138   m.addDetail( std::string("Expected: ") + utest_mat_str(m1) );
139   m.addDetail( std::string("Actual  : ") + utest_mat_str(m2) );
140   return m;
141 }
142 
143 /** make error message for failed symmetric matrix copmarison */
utest_mat_message(const MBMesquite::SymMatrix3D & m1,const MBMesquite::SymMatrix3D & m2)144 inline CppUnit::Message utest_mat_message( const MBMesquite::SymMatrix3D& m1,
145                                      const MBMesquite::SymMatrix3D& m2 )
146 {
147   CppUnit::Message m( "equality assertion failed" );
148   m.addDetail( std::string("Expected: ") + utest_mat_str(m1) );
149   m.addDetail( std::string("Actual  : ") + utest_mat_str(m2) );
150   return m;
151 }
152 
153 /** compare vectors */
utest_vect_equal(const MBMesquite::Vector3D & v1,const MBMesquite::Vector3D & v2,double eps)154 inline bool utest_vect_equal( const MBMesquite::Vector3D& v1, const MBMesquite::Vector3D& v2, double eps )
155 {
156   return (fabs(v1[0] - v2[0]) < eps) &&
157          (fabs(v1[1] - v2[1]) < eps) &&
158          (fabs(v1[2] - v2[2]) < eps);
159 }
160 
161 /** compare matrices */
utest_mat_equal(const MBMesquite::Matrix3D & m1,const MBMesquite::Matrix3D & m2,double eps)162 inline bool utest_mat_equal( const MBMesquite::Matrix3D& m1, const MBMesquite::Matrix3D& m2, double eps )
163 {
164   return (fabs(m1[0][0] - m2[0][0]) < eps) &&
165          (fabs(m1[0][1] - m2[0][1]) < eps) &&
166          (fabs(m1[0][2] - m2[0][2]) < eps) &&
167          (fabs(m1[1][0] - m2[1][0]) < eps) &&
168          (fabs(m1[1][1] - m2[1][1]) < eps) &&
169          (fabs(m1[1][2] - m2[1][2]) < eps) &&
170          (fabs(m1[2][0] - m2[2][0]) < eps) &&
171          (fabs(m1[2][1] - m2[2][1]) < eps) &&
172          (fabs(m1[2][2] - m2[2][2]) < eps);
173 }
174 
175 /** compare matrices */
utest_mat_equal(const MBMesquite::SymMatrix3D & m1,const MBMesquite::SymMatrix3D & m2,double eps)176 inline bool utest_mat_equal( const MBMesquite::SymMatrix3D& m1, const MBMesquite::SymMatrix3D& m2, double eps )
177 {
178   return (fabs(m1(0,0) - m2(0,0)) < eps) &&
179          (fabs(m1(0,1) - m2(0,1)) < eps) &&
180          (fabs(m1(0,2) - m2(0,2)) < eps) &&
181          (fabs(m1(1,1) - m2(1,1)) < eps) &&
182          (fabs(m1(1,2) - m2(1,2)) < eps) &&
183          (fabs(m1(2,2) - m2(2,2)) < eps);
184 }
185 
186 template <unsigned R, unsigned C>
msq_mat_str(const MBMesquite::MsqMatrix<R,C> & m)187 inline std::string msq_mat_str( const MBMesquite::MsqMatrix<R,C>& m )
188 {
189   std::ostringstream os;
190   for (unsigned i = 0; i < R; ++i) {
191     os << "[" << m(i,0);
192     for (unsigned j = 1; j < C; ++j)
193       os << ", " << m(i,j);
194     os << "]";
195   }
196   return os.str();
197 }
198 
199 template <unsigned R, unsigned C>
ident_check_msg(const MBMesquite::MsqMatrix<R,C> & m)200 inline CppUnit::Message ident_check_msg( const MBMesquite::MsqMatrix<R,C>& m )
201 {
202   CppUnit::Message mes( "Identity Assertion Failed" );
203   mes.addDetail( std::string("Actual: ") + msq_mat_str(m) );
204   return mes;
205 }
206 
207 template <unsigned R, unsigned C>
ident_check(const MBMesquite::MsqMatrix<R,C> & m)208 inline bool ident_check( const MBMesquite::MsqMatrix<R,C>& m )
209 {
210   for (unsigned i = 0; i < R; ++i)
211     for (unsigned j = 0; j < C; ++j)
212       if (i == j && fabs(m(i,j) - 1.0) > 1e-6)
213         return false;
214       else if (i != j && fabs(m(i,j)) > 1e-6)
215         return false;
216   return true;
217 }
218 
219 template <unsigned R, unsigned C>
mat_equal_check_msg(const MBMesquite::MsqMatrix<R,C> & A,const MBMesquite::MsqMatrix<R,C> & B)220 inline CppUnit::Message mat_equal_check_msg( const MBMesquite::MsqMatrix<R,C>& A,
221                                              const MBMesquite::MsqMatrix<R,C>& B )
222 {
223   CppUnit::Message mes( "Matrix Equality Assertion Failed" );
224   mes.addDetail( std::string( "Expected: ") + msq_mat_str(A) );
225   mes.addDetail( std::string( "Actual:   ") + msq_mat_str(B) );
226   return mes;
227 }
228 
229 template <unsigned R, unsigned C>
mat_not_equal_check_msg(const MBMesquite::MsqMatrix<R,C> & A,const MBMesquite::MsqMatrix<R,C> & B)230 inline CppUnit::Message mat_not_equal_check_msg( const MBMesquite::MsqMatrix<R,C>& A,
231                                              const MBMesquite::MsqMatrix<R,C>& B )
232 {
233   CppUnit::Message mes( "Matrix Inequality Assertion Failed" );
234   mes.addDetail( std::string( "Expected: ") + msq_mat_str(A) );
235   mes.addDetail( std::string( "Actual:   ") + msq_mat_str(B) );
236   return mes;
237 }
238 
239 template <unsigned R, unsigned C>
mat_equal_check(const MBMesquite::MsqMatrix<R,C> & A,const MBMesquite::MsqMatrix<R,C> & B,double eps)240 inline bool mat_equal_check( const MBMesquite::MsqMatrix<R,C>& A,
241                              const MBMesquite::MsqMatrix<R,C>& B,
242                              double eps  )
243 {
244   for (unsigned i = 0; i < R; ++i)
245     for (unsigned j = 0; j < C; ++j)
246       if (fabs(A(i,j)-B(i,j)) > eps)
247         return false;
248   return true;
249 }
250 
251 template <typename T1, typename T2>
arrays_equal(const T1 * A,const T2 * B,size_t len)252 inline bool arrays_equal( const T1* A, const T2* B, size_t len )
253 {
254   for (size_t i = 0; i < len; ++i)
255     if (A[i] != B[i])
256       return false;
257   return true;
258 }
259 
260 template <typename T1, typename T2>
arrays_not_equal_msg(const T1 * A,size_t A_len,const T2 * B,size_t B_len)261 inline CppUnit::Message arrays_not_equal_msg( const T1* A, size_t A_len,
262                                               const T2* B, size_t B_len )
263 {
264   CppUnit::Message mes( "Equality Assertion Failed for Arrays" );
265 
266   std::ostringstream strA;
267   if (A_len == 0)
268     strA << "(empty)";
269   else {
270     strA << '[' << A[0];
271     for (size_t i = 1; i < A_len; ++i)
272       strA << ',' << A[i];
273     strA << ']';
274   }
275   mes.addDetail( std::string( "Expected: ") + strA.str() );
276 
277   std::ostringstream strB;
278   if (B_len == 0)
279     strB << "(empty)";
280   else {
281     strB << '[' << B[0];
282     for (size_t i = 1; i < B_len; ++i)
283       strB << ',' << B[i];
284     strB << ']';
285   }
286   mes.addDetail( std::string( "Actual: ") + strB.str() );
287 
288   return mes;
289 }
290 
291 #endif
292