Seamly2D
Code documentation
abstracttest.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2017 Seamly, LLC *
4  * *
5  * https://github.com/fashionfreedom/seamly2d *
6  * *
7  ***************************************************************************
8  **
9  ** Seamly2D is free software: you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation, either version 3 of the License, or
12  ** (at your option) any later version.
13  **
14  ** Seamly2D 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
17  ** GNU General Public License for more details.
18  **
19  ** You should have received a copy of the GNU General Public License
20  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
21  **
22  **************************************************************************
23 
24  ************************************************************************
25  **
26  ** @file abstracttest.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date 7 5, 2015
29  **
30  ** @brief
31  ** @copyright
32  ** This source code is part of the Valentine project, a pattern making
33  ** program, whose allow create and modeling patterns of clothing.
34  ** Copyright (C) 2015 Seamly2D project
35  ** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
36  **
37  ** Seamly2D is free software: you can redistribute it and/or modify
38  ** it under the terms of the GNU General Public License as published by
39  ** the Free Software Foundation, either version 3 of the License, or
40  ** (at your option) any later version.
41  **
42  ** Seamly2D is distributed in the hope that it will be useful,
43  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
44  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45  ** GNU General Public License for more details.
46  **
47  ** You should have received a copy of the GNU General Public License
48  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
49  **
50  *************************************************************************/
51 
52 #include "abstracttest.h"
53 
54 #include <qtestcase.h>
55 #include <QApplication>
56 #include <QByteArray>
57 #include <QDir>
58 #include <QFile>
59 #include <QFileInfo>
60 #include <QFlags>
61 #include <QIODevice>
62 #include <QPointF>
63 #include <QProcess>
64 #include <QScopedPointer>
65 #include <QStaticStringData>
66 #include <QStringData>
67 #include <QStringDataPtr>
68 #include <QStringList>
69 #include <QVector>
70 #include <QtGlobal>
71 #include <QLineF>
72 
73 #include "logging.h"
74 #include "vsysexits.h"
75 #include "../vgeometry/vgeometrydef.h"
76 #include "../vgeometry/vgobject.h"
77 #include "../vgeometry/vpointf.h"
78 #include "../vgeometry/vspline.h"
79 #include "../vgeometry/vsplinepath.h"
80 #include "../vlayout/vabstractpiece.h"
81 #include "../vpatterndb/vcontainer.h"
82 #include "../vpatterndb/vpiece.h"
83 #include "../vpatterndb/vpiecenode.h"
84 
85 //---------------------------------------------------------------------------------------------------------------------
86 AbstractTest::AbstractTest(QObject *parent) :
87  QObject(parent)
88 {
89 }
90 
91 //---------------------------------------------------------------------------------------------------------------------
92 void AbstractTest::Comparison(const QVector<QPointF> &ekv, const QVector<QPointF> &ekvOrig) const
93 {
94  // Begin comparison
95  QCOMPARE(ekv.size(), ekvOrig.size());// First check if sizes equal
96  const qreal testAccuracy = (1.0/*mm*/ / 25.4) * PrintDPI;
97 
98  for (int i=0; i < ekv.size(); i++)
99  {
100  Comparison(ekv.at(i), ekvOrig.at(i), testAccuracy);
101  }
102 }
103 
104 //---------------------------------------------------------------------------------------------------------------------
105 void AbstractTest::Comparison(const QPointF &result, const QPointF &expected, qreal testAccuracy) const
106 {
107  const QString msg = QStringLiteral("Actual '%2;%3', Expected '%4;%5'. Distance between points %6 mm.")
108  .arg(result.x()).arg(result.y()).arg(expected.x()).arg(expected.y())
109  .arg(UnitConvertor(QLineF(result, expected).length(), Unit::Px, Unit::Mm));
110  // Check each point. Don't use comparison float values
111  QVERIFY2(VFuzzyComparePoints(result, expected, testAccuracy), qUtf8Printable(msg));
112 }
113 
114 //---------------------------------------------------------------------------------------------------------------------
116 {
117  const QString path = QStringLiteral("/../../../app/seamly2d/bin/");
118 #if defined(Q_OS_WIN)
119  return QCoreApplication::applicationDirPath() + path + QLatin1String("seamly2d.exe");
120 #elif defined(Q_OS_MACOS)
121  return QCoreApplication::applicationDirPath() + path + QLatin1String("Seamly2D.app/Contents/MacOS/seamly2d");
122 #else
123  return QCoreApplication::applicationDirPath() + path + QLatin1String("seamly2d");
124 #endif
125 }
126 
127 //---------------------------------------------------------------------------------------------------------------------
129 {
130  const QString path = QStringLiteral("/../../../app/seamlyme/bin/");
131 #if defined(Q_OS_WIN)
132  return QCoreApplication::applicationDirPath() + path + QLatin1String("seamlyme.exe");
133 #elif defined(Q_OS_MACOS)
134  return QCoreApplication::applicationDirPath() + path + QLatin1String("seamlyme.app/Contents/MacOS/seamlyme");
135 #else
136  return QCoreApplication::applicationDirPath() + path + QLatin1String("seamlyme");
137 #endif
138 }
139 
140 //---------------------------------------------------------------------------------------------------------------------
142 {
143  return QCoreApplication::applicationDirPath() + QStringLiteral("/../../../app/seamly2d/.qm");
144 }
145 
146 //---------------------------------------------------------------------------------------------------------------------
147 int AbstractTest::Run(int exit, const QString &program, const QStringList &arguments, QString &error, int msecs)
148 {
149  const QString parameters = QString("Program: %1 \nArguments: %2.").arg(program).arg(arguments.join(", "));
150 
151  QFileInfo info(program);
152  if (not info.exists())
153  {
154  error = QString("Can't find binary.\n%1").arg(parameters);
155  return TST_EX_BIN;
156  }
157 
158  QScopedPointer<QProcess> process(new QProcess());
159  process->setWorkingDirectory(info.absoluteDir().absolutePath());
160  process->start(program, arguments);
161 
162  if (not process->waitForStarted(msecs))
163  {
164  error = QString("The start operation timed out or an error occurred.\n%1").arg(parameters);
165  process->kill();
166  return TST_EX_START_TIME_OUT;
167  }
168 
169  if (not process->waitForFinished(msecs))
170  {
171  error = QString("The finish operation timed out or an error occurred.\n%1").arg(parameters);
172  process->kill();
173  return TST_EX_FINISH_TIME_OUT;
174  }
175 
176  if (process->exitStatus() == QProcess::CrashExit)
177  {
178  error = QString("Program crashed.\n%1\n%2").arg(parameters).arg(QString(process->readAllStandardError()));
179  return TST_EX_CRASH;
180  }
181 
182  if (process->exitCode() != exit)
183  {
184  error = QString("Unexpected finish.\n%1").arg(QString(process->readAllStandardError()));
185  return process->exitCode();
186  }
187 
188  return process->exitCode();
189 }
190 
191 //---------------------------------------------------------------------------------------------------------------------
192 bool AbstractTest::CopyRecursively(const QString &srcFilePath, const QString &tgtFilePath) const
193 {
194  QFileInfo srcFileInfo(srcFilePath);
195  if (srcFileInfo.isDir())
196  {
197  QDir targetDir(tgtFilePath);
198  targetDir.cdUp();
199  const QString dirName = QFileInfo(tgtFilePath).fileName();
200  if (not targetDir.mkdir(dirName))
201  {
202  const QString msg = QString("Can't create dir '%1'.").arg(dirName);
203  QWARN(qUtf8Printable(msg));
204  return false;
205  }
206  QDir sourceDir(srcFilePath);
207  QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden |
208  QDir::System);
209  foreach (const QString &fileName, fileNames)
210  {
211  const QString newSrcFilePath = srcFilePath + QDir::separator() + fileName;
212  const QString newTgtFilePath = tgtFilePath + QDir::separator() + fileName;
213  if (not CopyRecursively(newSrcFilePath, newTgtFilePath))
214  {
215  return false;
216  }
217  }
218  }
219  else
220  {
221  if (QFileInfo(tgtFilePath).exists())
222  {
223  const QString msg = QString("File '%1' exists.").arg(srcFilePath);
224  QWARN(qUtf8Printable(msg));
225 
226  if (QFile::remove(tgtFilePath))
227  {
228  QWARN("File successfully removed.");
229  }
230  else
231  {
232  QWARN("Can't remove file.");
233  return false;
234  }
235  }
236 
237  // Check error: Cannot open %file for input
238  QFile srcFile(srcFilePath);
239  if (not srcFile.open(QFile::ReadOnly))
240  {
241  const QString msg = QString("Can't copy file '%1'. Error: %2").arg(srcFilePath).arg(srcFile.errorString());
242  QWARN(qUtf8Printable(msg));
243  return false;
244  }
245  srcFile.close();
246 
247  if (not srcFile.copy(tgtFilePath))
248  {
249  const QString msg = QString("Can't copy file '%1' to '%2'. Error: %3").arg(srcFilePath).arg(tgtFilePath)
250  .arg(srcFile.errorString());
251  QWARN(qUtf8Printable(msg));
252  return false;
253  }
254  }
255  return true;
256 }
static const auto TST_EX_CRASH
Definition: abstracttest.h:75
static const auto TST_EX_BIN
Definition: abstracttest.h:72
static const auto TST_EX_START_TIME_OUT
Definition: abstracttest.h:74
static const auto TST_EX_FINISH_TIME_OUT
Definition: abstracttest.h:73
QString TranslationsPath() const
int Run(int exit, const QString &program, const QStringList &arguments, QString &error, int msecs=120000)
bool CopyRecursively(const QString &srcFilePath, const QString &tgtFilePath) const
AbstractTest(QObject *parent=nullptr)
QString SeamlyMePath() const
QString Seamly2DPath() const
void Comparison(const QVector< QPointF > &ekv, const QVector< QPointF > &ekvOrig) const
const qreal PrintDPI
Definition: def.cpp:228
qreal UnitConvertor(qreal value, const Unit &from, const Unit &to)
Definition: def.cpp:269
static Q_REQUIRED_RESULT bool VFuzzyComparePoints(const QPointF &p1, const QPointF &p2, qreal accuracy=accuracyPointOnLine)
Definition: def.h:484