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 #include <QString>
45 #include <QStringList>
46 #include <QSettings>
47 #include <QFileInfo>
48 #include <QTextStream>
49 
50 #include <cmath>
51 #include <limits>
52 #include <iostream>
53 
54 
55 /* Test File specification:
56 Doubles can be given as:
57 
58 Exact test:
59 VALUE_DOUBLE=1.0
60 
61 Tolerance test (0.0001)
62 VALUE_DOUBLE=1.0,0.0001
63 
64 
65 */
66 
67 
68 bool compareDouble(QString _key , QVariant _result, QVariant _reference) {
69 
70  // maximal allowed double tolerance
71  double tolerance = std::numeric_limits<double>::epsilon();
72 
73  // Check if the reference consists of two colon separated values
74  // Second value would specify maximal allowed tolerance
75  QStringList referenceData = _reference.toString().split(':');
76  if ( referenceData.size() == 2) {
77  tolerance = referenceData[1].toDouble();
78  }
79 
80 
81  double result = _result.toDouble();
82  double reference = referenceData[0].toDouble();
83 
84  if ( fabs(result-reference) <= tolerance ) {
85  return true;
86  } else {
87 
88  //qcerr.setRealNumberPrecision(40);
89  std::cerr.precision(40);
90  std::cerr << "===================================================================\n";
91  std::cerr << "Comparison failed for key " << _key.toStdString() << " :\n";
92  std::cerr << "Result: " << result << "\n";
93  std::cerr << "Expected: " << reference << "\n";
94  std::cerr << "Difference: " << fabs(result-reference) << "\n";
95  std::cerr << "Allowed tolerance was: " << tolerance << "\n";
96  std::cerr << "===================================================================\n";
97  return false;
98  }
99 
100 }
101 
102 bool compareString(QString _key ,QVariant _result, QVariant _reference) {
103 
104  QString resultStr = _result.toString().simplified();
105  QString resultRef = _reference.toString().simplified();
106 
107  if (resultStr == resultRef ) {
108  return true;
109  } else {
110  std::cerr << "Comparison failed for key " << _key.toStdString() << " :\n";
111  std::cerr << "Result: " << resultStr.toStdString() << " ; Expected: " << resultRef.toStdString() << "\n";
112  return false;
113  }
114 
115 }
116 
117 int main(int argv, char **args)
118 {
119  std::cout << "============================================================\n" ;
120  std::cout << "Executing compare tool\n";
121  std::cout << "Comparing results to reference:\n" ;
122 
123  // Flag if everything went fine
124  bool ok = true;
125 
126  // Return if we did not get exactly two arguments
127  if ( argv != 3 ) {
128  std::cerr << "Wrong number of arguments!\n";
129  std::cerr << "Usage:\n";
130  std::cerr << "compareTool ResultFile ReferenceFile\n";
131  return(1);
132  }
133 
134  QString file1(args[1]);
135  QString file2(args[2]);
136 
137  QFileInfo resultFileInfo(file1);
138  if ( !resultFileInfo.exists() ) {
139  std::cerr << "ERROR! Result file: " << file1.toStdString() << " does not exist!\n";
140 
141  return 1;
142  }
143 
144  QFileInfo referenceFileInfo(file2);
145  if ( !referenceFileInfo.exists() ) {
146  std::cerr << "ERROR! Reference file: " << file2.toStdString() << " does not exist!\n";
147  return 1;
148  }
149 
150  QSettings resultFile(file1,QSettings::IniFormat);
151  QSettings referenceFile(file2,QSettings::IniFormat);
152 
153  if ( resultFile.status() != QSettings::NoError) {
154  std::cerr << "QSettings error when opening result file: " << file1.toStdString() << "\n";
155  return 1;
156  }
157 
158  if ( referenceFile.status() != QSettings::NoError) {
159  std::cerr << "QSettings error when opening result reference file: " << file2.toStdString() << "\n";
160  return 1;
161  }
162 
163  QStringList toplevelKeys = referenceFile.childKeys();
164  QStringList groups = referenceFile.childGroups();
165 
166  if ( groups.size() == 0 ) {
167  for ( int i = 0 ; i < toplevelKeys.size(); ++i) {
168  if ( resultFile.contains(toplevelKeys[i]) ) {
169  if ( toplevelKeys[i].endsWith("_DOUBLE") ) {
170  ok &= compareDouble(toplevelKeys[i],resultFile.value(toplevelKeys[i]), referenceFile.value(toplevelKeys[i]));
171  } else
172  ok &= compareString( toplevelKeys[i],resultFile.value(toplevelKeys[i]), referenceFile.value(toplevelKeys[i]));
173  } else {
174  std::cerr << "Missing key in result file: " << toplevelKeys[i].toStdString() << "\n";
175  ok = false;
176  }
177 
178  }
179 
180 
181  } else {
182  std::cerr << "Multiple levels!" << "\n";
183  return 1;
184  }
185 
186 
187  if ( ! ok ) {
188  std::cerr << "At least one of the tests failed!\n";
189  return 1;
190  }
191 
192  return(0);
193 }