File indexing completed on 2024-05-19 05:14:15
0001 /* 0002 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "modelverificationpoint.h" 0008 0009 #include <KItinerary/JsonLdDocument> 0010 0011 #include <QAbstractItemModel> 0012 #include <QDebug> 0013 #include <QFile> 0014 #include <QJsonArray> 0015 #include <QJsonDocument> 0016 #include <QJsonObject> 0017 #include <QProcess> 0018 0019 ModelVerificationPoint::ModelVerificationPoint(const QString &refFile) 0020 : m_refFile(refFile) 0021 { 0022 } 0023 0024 ModelVerificationPoint::~ModelVerificationPoint() = default; 0025 0026 void ModelVerificationPoint::setRoleFilter(std::vector<int> &&filter) 0027 { 0028 m_roleFilter = std::move(filter); 0029 } 0030 0031 void ModelVerificationPoint::setJsonPropertyFilter(std::vector<QString> &&filter) 0032 { 0033 m_jsonPropertyFilter = std::move(filter); 0034 } 0035 0036 QJsonValue ModelVerificationPoint::variantToJson(const QVariant &v) const 0037 { 0038 switch (v.userType()) { 0039 case QMetaType::QString: 0040 return v.toString(); 0041 case QMetaType::QStringList: 0042 { 0043 const auto l = v.toStringList(); 0044 if (l.isEmpty()) { 0045 return {}; 0046 } 0047 QJsonArray a; 0048 std::copy(l.begin(), l.end(), std::back_inserter(a)); 0049 return a; 0050 } 0051 case QMetaType::Bool: 0052 return v.toBool(); 0053 case QMetaType::Int: 0054 return v.toInt(); 0055 default: 0056 break; 0057 } 0058 0059 if (QMetaType(v.userType()).metaObject()) { 0060 auto obj = KItinerary::JsonLdDocument::toJson(v); 0061 for (const auto &filter : m_jsonPropertyFilter) { 0062 obj.remove(filter); 0063 } 0064 return obj; 0065 } else if (v.userType() == qMetaTypeId<QVector<QVariant>>()) { 0066 return KItinerary::JsonLdDocument::toJson(v.value<QVector<QVariant>>()); 0067 } 0068 0069 return {}; 0070 } 0071 0072 bool ModelVerificationPoint::verify(QAbstractItemModel *model) const 0073 { 0074 // serialize model state 0075 QJsonArray array; 0076 const auto roleNames = model->roleNames(); 0077 for (int i = 0; i < model->rowCount(); ++i) { 0078 const auto idx = model->index(i, 0); 0079 QJsonObject obj; 0080 for (auto it = roleNames.begin(); it != roleNames.end(); ++it) { 0081 if (std::find(m_roleFilter.begin(), m_roleFilter.end(), it.key()) != m_roleFilter.end()) { 0082 continue; 0083 } 0084 0085 const auto v = variantToJson(idx.data(it.key())); 0086 if (!v.isNull() && !(v.isArray() && v.toArray().isEmpty())) { 0087 obj.insert(QString::fromUtf8(it.value()), v); 0088 } 0089 } 0090 array.push_back(obj); 0091 } 0092 0093 // reference data 0094 QFile file(m_refFile); 0095 if (!file.open(QFile::ReadOnly)) { 0096 qWarning() << file.fileName() << file.errorString(); 0097 return false; 0098 } 0099 const auto doc = QJsonDocument::fromJson(file.readAll()); 0100 const auto refArray = doc.array(); 0101 0102 // compare 0103 if (array != refArray) { 0104 QFile failFile(m_refFile + QLatin1StringView(".fail")); 0105 failFile.open(QFile::WriteOnly); 0106 failFile.write(QJsonDocument(array).toJson()); 0107 failFile.close(); 0108 0109 QProcess proc; 0110 proc.setProcessChannelMode(QProcess::ForwardedChannels); 0111 proc.start(QStringLiteral("diff"), {QStringLiteral("-u"), m_refFile, failFile.fileName()}); 0112 proc.waitForFinished(); 0113 return false; 0114 } 0115 0116 return true; 0117 }