valentina/src/libs/vtest/abstracttest.h

370 lines
14 KiB
C
Raw Normal View History

/************************************************************************
**
** @file abstracttest.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 7 5, 2015
**
** @brief
** @copyright
** This source code is part of the Valentina project, a pattern making
** program, whose allow create and modeling patterns of clothing.
** Copyright (C) 2015 Valentina project
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef ABSTRACTTEST_H
#define ABSTRACTTEST_H
2023-05-17 15:24:27 +02:00
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMetaObject>
#include <QObject>
#include <QString>
2023-05-17 15:24:27 +02:00
#include <QtCore/qcontainerfwd.h>
2022-10-28 15:16:02 +02:00
#include <qtestcase.h>
#include <typeinfo>
2022-10-28 15:16:02 +02:00
2023-05-17 15:24:27 +02:00
#include "../ifc/exception/vexception.h"
2022-10-28 15:16:02 +02:00
#include "../vgeometry/vpointf.h"
#include "../vlayout/vrawsapoint.h"
2023-05-17 15:24:27 +02:00
#include "../vlayout/vsapoint.h"
2023-07-17 15:33:57 +02:00
// Header <ciso646> is removed in C++20.
#if __cplusplus <= 201703L
#include <ciso646> // and, not, or
#endif
#ifdef __GNUC__
2023-05-17 15:24:27 +02:00
#define V_UNUSED __attribute__((unused))
#else
#define V_UNUSED
#endif
// Return codes for testing run application
2023-05-17 15:24:27 +02:00
static const auto V_UNUSED TST_EX_BIN = -1; // Can't find binary.
static const auto V_UNUSED TST_EX_FINISH_TIME_OUT = -2; // The operation timed out or an error occurred.
2023-05-17 15:24:27 +02:00
static const auto V_UNUSED TST_EX_START_TIME_OUT = -3; // The operation timed out or an error occurred.
static const auto V_UNUSED TST_EX_CRASH = -4; // Program crashed.
#undef V_UNUSED
2023-05-17 15:24:27 +02:00
enum ErrorState
{
ErrorLoad = 0,
ErrorInstall,
ErrorSize,
2023-05-17 15:25:27 +02:00
ErrorMissing,
2023-05-17 15:24:27 +02:00
NoError
};
class VPiece;
class VContainer;
class VPointF;
class VSplinePoint;
class VPieceNode;
enum class GOType : qint8;
struct VPiecePassmarkData;
class VRawSAPoint;
class AbstractTest : public QObject
{
2022-08-12 17:50:13 +02:00
Q_OBJECT // NOLINT
2023-07-17 15:33:57 +02:00
public:
explicit AbstractTest(QObject *parent = nullptr);
2023-05-17 15:24:27 +02:00
template <class T> static auto VectorFromJson(const QString &json) -> QVector<T>;
void PieceFromJson(const QString &json, VPiece &piece, QSharedPointer<VContainer> &data);
2023-05-17 15:24:27 +02:00
void PassmarkDataFromJson(const QString &json, VPiecePassmarkData &data);
void PassmarkShapeFromJson(const QString &json, QVector<QLineF> &shape);
protected:
2022-11-11 16:57:34 +01:00
static void ComparePaths(const QVector<QPointF> &actual, const QVector<QPointF> &expected);
2022-10-28 15:16:02 +02:00
void ComparePathsDistance(const QVector<QPointF> &ekv, const QVector<QPointF> &ekvOrig) const;
void ComparePointsDistance(const QPointF &result, const QPointF &expected, qreal testAccuracy) const;
void CompareLinesDistance(const QVector<QLineF> &result, const QVector<QLineF> &expected) const;
2023-01-06 16:41:45 +01:00
auto PuzzlePath() const -> QString;
2022-10-28 15:16:02 +02:00
auto ValentinaPath() const -> QString;
auto TapePath() const -> QString;
2023-06-23 08:12:36 +02:00
static auto TranslationsPath() -> QString;
2022-10-28 15:16:02 +02:00
static auto RunTimeout(int defMsecs) -> int;
2022-10-28 15:16:02 +02:00
auto Run(int exit, const QString &program, const QStringList &arguments, QString &error, int msecs = 120000) -> int;
auto CopyRecursively(const QString &srcFilePath, const QString &tgtFilePath) const -> bool;
2022-10-28 15:16:02 +02:00
static void PrepareDocument(const QString &json, QByteArray &data);
static void TestRoot(const QJsonObject &root, const QString &attribute, const QString &file);
2023-05-17 15:24:27 +02:00
template <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
2022-10-28 15:16:02 +02:00
static void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
const QString &defaultValue = QString());
2023-05-17 15:24:27 +02:00
template <typename T, typename std::enable_if<std::is_enum<T>::value>::type * = nullptr>
2022-10-28 15:16:02 +02:00
static void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
const QString &defaultValue = QString());
2023-05-17 15:24:27 +02:00
template <typename T, typename std::enable_if<std::is_integral<T>::value>::type * = nullptr>
2022-10-28 15:16:02 +02:00
static void ReadDoubleValue(const QJsonObject &itemObject, const QString &attribute, T &value,
2023-05-17 15:24:27 +02:00
const QString &defaultValue = QString());
2022-10-28 15:16:02 +02:00
static void ReadStringValue(const QJsonObject &itemObject, const QString &attribute, QString &value,
const QString &defaultValue = QString());
static void ReadBooleanValue(const QJsonObject &itemObject, const QString &attribute, bool &value,
const QString &defaultValue = QString());
void ReadPointValue(const QJsonObject &itemObject, const QString &attribute, VPointF &value);
void ReadSplinePointValues(const QJsonObject &itemObject, const QString &attribute, QVector<VSplinePoint> &points);
void ReadSplinePointValue(const QJsonObject &itemObject, VSplinePoint &point);
void ReadPieceNodeValue(const QJsonObject &itemObject, VPieceNode &node);
2023-05-17 15:24:27 +02:00
template <class T> static void CheckClassType(const QJsonObject &itemObject);
2022-10-28 15:16:02 +02:00
2023-05-17 15:24:27 +02:00
template <class T> static auto ReadPointData(const QJsonObject &pointObject) -> T;
2022-10-28 15:16:02 +02:00
2023-05-17 15:24:27 +02:00
template <class T> static auto PointFromJson(const QJsonObject &pointObject, T &point) -> void;
2022-10-28 15:16:02 +02:00
auto QLineFromJson(const QJsonObject &itemObject) -> QLineF;
void SplineFromJson(const QJsonObject &itemObject, QSharedPointer<VContainer> &data);
void SplinePathFromJson(const QJsonObject &itemObject, QSharedPointer<VContainer> &data);
void DBFromJson(const QJsonObject &dbObject, QSharedPointer<VContainer> &data);
void MainPathFromJson(const QJsonObject &pieceObject, VPiece &piece);
};
2022-10-28 15:16:02 +02:00
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <class T> inline auto AbstractTest::VectorFromJson(const QString &json) -> QVector<T>
2022-10-28 15:16:02 +02:00
{
QByteArray saveData;
PrepareDocument(json, saveData);
QJsonDocument loadDoc(QJsonDocument::fromJson(saveData));
const QString vectorKey = QStringLiteral("vector");
QJsonObject vectorObject = loadDoc.object();
TestRoot(vectorObject, vectorKey, json);
QJsonArray vectorArray = vectorObject[vectorKey].toArray();
2022-10-29 13:46:10 +02:00
QVector<T> vector;
vector.reserve(vectorArray.size());
2022-10-28 15:16:02 +02:00
2022-11-10 15:15:11 +01:00
for (auto item : vectorArray)
2022-10-28 15:16:02 +02:00
{
try
{
2022-10-29 13:46:10 +02:00
T point;
PointFromJson(item.toObject(), point);
vector.append(point);
2022-10-28 15:16:02 +02:00
}
catch (const VException &e)
{
throw VException(QStringLiteral("Invalid json file '%1'. %2").arg(json, e.ErrorMessage()));
}
}
return vector;
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <class T> inline void AbstractTest::CheckClassType(const QJsonObject &itemObject)
2022-10-28 15:16:02 +02:00
{
const QString typeKey = QStringLiteral("type");
QString type;
AbstractTest::ReadStringValue(itemObject, typeKey, type);
2023-05-17 15:24:27 +02:00
const QStringList types{
2022-10-29 13:46:10 +02:00
QStringLiteral("QPointF"), // 0
QStringLiteral("VLayoutPoint"), // 1
QStringLiteral("VRawSAPoint"), // 2
QStringLiteral("VSAPoint"), // 3
};
bool res = false;
switch (types.indexOf(type))
{
case 0:
res = (typeid(T) == typeid(QPointF));
break;
case 1:
res = (typeid(T) == typeid(VLayoutPoint));
break;
case 2:
res = (typeid(T) == typeid(VRawSAPoint));
break;
case 3:
res = (typeid(T) == typeid(VSAPoint));
break;
default:
break;
}
if (not res)
2022-10-28 15:16:02 +02:00
{
throw VException(QStringLiteral("Unexpected class '%2'.").arg(itemObject[typeKey].toString()));
}
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <class T> inline auto AbstractTest::ReadPointData(const QJsonObject &pointObject) -> T
2022-10-28 15:16:02 +02:00
{
T point;
qreal x = 0;
AbstractTest::ReadDoubleValue(pointObject, QChar('x'), x);
point.setX(x);
qreal y = 0;
AbstractTest::ReadDoubleValue(pointObject, QChar('y'), y);
point.setY(y);
return point;
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <class T> inline auto AbstractTest::PointFromJson(const QJsonObject &pointObject, T &point) -> void
2022-10-28 15:16:02 +02:00
{
CheckClassType<T>(pointObject);
2022-10-29 13:46:10 +02:00
point = ReadPointData<T>(pointObject);
2022-10-28 15:16:02 +02:00
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <> inline auto AbstractTest::PointFromJson(const QJsonObject &pointObject, VPointF &point) -> void
2022-10-28 15:16:02 +02:00
{
vidtype id = NULL_ID;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("id"), id);
qreal mx = 0;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("mx"), mx);
qreal my = 0;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("my"), my);
QString name;
AbstractTest::ReadStringValue(pointObject, QStringLiteral("name"), name);
qreal x = 0;
AbstractTest::ReadDoubleValue(pointObject, QChar('x'), x);
qreal y = 0;
AbstractTest::ReadDoubleValue(pointObject, QChar('y'), y);
2022-10-29 13:46:10 +02:00
point = VPointF(x, y, name, mx, my);
2022-10-28 15:16:02 +02:00
point.setId(id);
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <> inline auto AbstractTest::ReadPointData(const QJsonObject &pointObject) -> VLayoutPoint
2022-10-28 15:16:02 +02:00
{
VLayoutPoint point(ReadPointData<QPointF>(pointObject));
bool turnPoint;
AbstractTest::ReadBooleanValue(pointObject, QStringLiteral("turnPoint"), turnPoint, QStringLiteral("0"));
point.SetTurnPoint(turnPoint);
bool curvePoint;
AbstractTest::ReadBooleanValue(pointObject, QStringLiteral("curvePoint"), curvePoint, QStringLiteral("0"));
point.SetCurvePoint(curvePoint);
return point;
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <> inline auto AbstractTest::PointFromJson(const QJsonObject &pointObject, VLayoutPoint &point) -> void
2022-10-28 15:16:02 +02:00
{
CheckClassType<VLayoutPoint>(pointObject);
2022-10-29 13:46:10 +02:00
point = ReadPointData<VLayoutPoint>(pointObject);
2022-10-28 15:16:02 +02:00
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <> inline auto AbstractTest::PointFromJson(const QJsonObject &pointObject, VSAPoint &point) -> void
2022-10-28 15:16:02 +02:00
{
CheckClassType<VSAPoint>(pointObject);
2022-10-29 13:46:10 +02:00
point = VSAPoint(ReadPointData<VLayoutPoint>(pointObject));
2022-10-28 15:16:02 +02:00
qreal saBefore;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("saBefore"), saBefore, QStringLiteral("-1"));
point.SetSABefore(saBefore);
qreal saAfter;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("saAfter"), saAfter, QStringLiteral("-1"));
point.SetSAAfter(saAfter);
PieceNodeAngle angleType = PieceNodeAngle::ByLength;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("angle"), angleType,
QString::number(static_cast<int>(PieceNodeAngle::ByLength)));
point.SetAngleType(angleType);
bool manualPassmarkLength = false;
AbstractTest::ReadBooleanValue(pointObject, QLatin1String("manualPassmarkLength"), manualPassmarkLength,
QStringLiteral("0"));
point.SetManualPasskmarkLength(manualPassmarkLength);
if (manualPassmarkLength)
{
qreal passmarkLength = 0;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("passmarkLength"), passmarkLength,
QStringLiteral("0"));
point.SetPasskmarkLength(passmarkLength);
}
bool manualPassmarkWidth = false;
AbstractTest::ReadBooleanValue(pointObject, QLatin1String("manualPassmarkWidth"), manualPassmarkWidth,
QStringLiteral("0"));
point.SetManualPasskmarkWidth(manualPassmarkWidth);
if (manualPassmarkWidth)
{
qreal passmarkWidth = 0;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("passmarkWidth"), passmarkWidth, QStringLiteral("0"));
point.SetPasskmarkWidth(passmarkWidth);
}
else
{
bool passmarkClockwiseOpening = false;
AbstractTest::ReadBooleanValue(pointObject, QLatin1String("passmarkClockwiseOpening"), passmarkClockwiseOpening,
QStringLiteral("0"));
point.SetPassmarkClockwiseOpening(passmarkClockwiseOpening);
}
bool manualPassmarkAngle = false;
AbstractTest::ReadBooleanValue(pointObject, QLatin1String("manualPassmarkAngle"), manualPassmarkAngle,
QStringLiteral("0"));
point.SetManualPasskmarkAngle(manualPassmarkAngle);
if (manualPassmarkAngle)
{
qreal passmarkAngle = 0;
AbstractTest::ReadDoubleValue(pointObject, QStringLiteral("passmarkAngle"), passmarkAngle, QStringLiteral("0"));
point.SetPasskmarkAngle(passmarkAngle);
}
2022-10-28 15:16:02 +02:00
}
//---------------------------------------------------------------------------------------------------------------------
2023-05-17 15:24:27 +02:00
template <> inline auto AbstractTest::PointFromJson(const QJsonObject &pointObject, VRawSAPoint &point) -> void
2022-10-28 15:16:02 +02:00
{
CheckClassType<VRawSAPoint>(pointObject);
2022-10-29 13:46:10 +02:00
point = VRawSAPoint(ReadPointData<VLayoutPoint>(pointObject));
2022-10-28 15:16:02 +02:00
bool loopPoint;
AbstractTest::ReadBooleanValue(pointObject, QStringLiteral("loopPoint"), loopPoint, QStringLiteral("0"));
point.SetLoopPoint(loopPoint);
}
#endif // ABSTRACTTEST_H