Developer Documentation
compareTool.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #include <QString>
51 #include <QStringList>
52 #include <QSettings>
53 #include <QFileInfo>
54 #include <QTextStream>
55 
56 #include <cmath>
57 #include <limits>
58 #include <iostream>
59 
60 
61 /* Test File specification:
62 Doubles can be given as:
63 
64 Exact test:
65 VALUE_DOUBLE=1.0
66 
67 Tolerance test (0.0001)
68 VALUE_DOUBLE=1.0,0.0001
69 
70 
71 */
72 
73 
74 bool compareDouble(QString _key , QVariant _result, QVariant _reference) {
75 
76  // maximal allowed double tolerance
77  double tolerance = std::numeric_limits<double>::epsilon();
78 
79  // Check if the reference consists of two colon separated values
80  // Second value would specify maximal allowed tolerance
81  QStringList referenceData = _reference.toString().split(':');
82  if ( referenceData.size() == 2) {
83  tolerance = referenceData[1].toDouble();
84  }
85 
86 
87  double result = _result.toDouble();
88  double reference = referenceData[0].toDouble();
89 
90  if ( fabs(result-reference) <= tolerance ) {
91  return true;
92  } else {
93 
94  //qcerr.setRealNumberPrecision(40);
95  std::cerr.precision(40);
96  std::cerr << "===================================================================\n";
97  std::cerr << "Comparison failed for key " << _key.toStdString() << " :\n";
98  std::cerr << "Result: " << result << "\n";
99  std::cerr << "Expected: " << reference << "\n";
100  std::cerr << "Difference: " << fabs(result-reference) << "\n";
101  std::cerr << "Allowed tolerance was: " << tolerance << "\n";
102  std::cerr << "===================================================================\n";
103  return false;
104  }
105 
106 }
107 
108 bool compareString(QString _key ,QVariant _result, QVariant _reference) {
109 
110  QString resultStr = _result.toString().simplified();
111  QString resultRef = _reference.toString().simplified();
112 
113  if (resultStr == resultRef ) {
114  return true;
115  } else {
116  std::cerr << "Comparison failed for key " << _key.toStdString() << " :\n";
117  std::cerr << "Result: " << resultStr.toStdString() << " ; Expected: " << resultRef.toStdString() << "\n";
118  return false;
119  }
120 
121 }
122 
123 int main(int argv, char **args)
124 {
125  std::cout << "============================================================\n" ;
126  std::cout << "Executing compare tool\n";
127  std::cout << "Comparing results to reference:\n" ;
128 
129  // Flag if everything went fine
130  bool ok = true;
131 
132  // Return if we did not get exactly two arguments
133  if ( argv != 3 ) {
134  std::cerr << "Wrong number of arguments!\n";
135  std::cerr << "Usage:\n";
136  std::cerr << "compareTool ResultFile ReferenceFile\n";
137  return(1);
138  }
139 
140  QString file1(args[1]);
141  QString file2(args[2]);
142 
143  QFileInfo resultFileInfo(file1);
144  if ( !resultFileInfo.exists() ) {
145  std::cerr << "ERROR! Result file: " << file1.toStdString() << " does not exist!\n";
146 
147  return 1;
148  }
149 
150  QFileInfo referenceFileInfo(file2);
151  if ( !referenceFileInfo.exists() ) {
152  std::cerr << "ERROR! Reference file: " << file2.toStdString() << " does not exist!\n";
153  return 1;
154  }
155 
156  QSettings resultFile(file1,QSettings::IniFormat);
157  QSettings referenceFile(file2,QSettings::IniFormat);
158 
159  if ( resultFile.status() != QSettings::NoError) {
160  std::cerr << "QSettings error when opening result file: " << file1.toStdString() << "\n";
161  return 1;
162  }
163 
164  if ( referenceFile.status() != QSettings::NoError) {
165  std::cerr << "QSettings error when opening result reference file: " << file2.toStdString() << "\n";
166  return 1;
167  }
168 
169  QStringList toplevelKeys = referenceFile.childKeys();
170  QStringList groups = referenceFile.childGroups();
171 
172  if ( groups.size() == 0 ) {
173  for ( int i = 0 ; i < toplevelKeys.size(); ++i) {
174  if ( resultFile.contains(toplevelKeys[i]) ) {
175  if ( toplevelKeys[i].endsWith("_DOUBLE") ) {
176  ok &= compareDouble(toplevelKeys[i],resultFile.value(toplevelKeys[i]), referenceFile.value(toplevelKeys[i]));
177  } else
178  ok &= compareString( toplevelKeys[i],resultFile.value(toplevelKeys[i]), referenceFile.value(toplevelKeys[i]));
179  } else {
180  std::cerr << "Missing key in result file: " << toplevelKeys[i].toStdString() << "\n";
181  ok = false;
182  }
183 
184  }
185 
186 
187  } else {
188  std::cerr << "Multiple levels!" << "\n";
189  return 1;
190  }
191 
192 
193  if ( ! ok ) {
194  std::cerr << "At least one of the tests failed!\n";
195  return 1;
196  }
197 
198  return(0);
199 }