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 }