1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
|
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include <gtest/gtest.h>
#include <QProcess>
#include <QTemporaryDir>
#include <QFile>
#include <QTextStream>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRegularExpression>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
class ut_dconfig2cpp : public testing::Test
{
protected:
void SetUp() override {
tempDir = new QTemporaryDir();
ASSERT_TRUE(tempDir->isValid());
}
void TearDown() override {
delete tempDir;
tempDir = nullptr;
}
// Get dconfig2cpp tool path
QString getToolPath() const {
QStringList possiblePaths = {
"../tools/dconfig2cpp/dconfig2cpp",
"../../tools/dconfig2cpp/dconfig2cpp",
"./tools/dconfig2cpp/dconfig2cpp",
"tools/dconfig2cpp/dconfig2cpp"
};
for (const QString &path : possiblePaths) {
if (QFile::exists(path)) {
return path;
}
}
return "dconfig2cpp"; // Assume it's in PATH
}
// Call dconfig2cpp to generate code
struct GenerationResult {
bool success;
QString generatedFilePath;
QString errorMessage;
int exitCode;
};
GenerationResult generateCode(const QString& jsonFilePath) {
GenerationResult result;
result.success = false;
result.exitCode = -1;
// If it's a QRC path, copy to temporary directory first
QString actualJsonPath = jsonFilePath;
if (jsonFilePath.startsWith(":/")) {
QFile sourceFile(jsonFilePath);
if (!sourceFile.open(QIODevice::ReadOnly)) {
result.errorMessage = QString("Failed to open resource file: %1").arg(jsonFilePath);
return result;
}
QFileInfo fileInfo(jsonFilePath);
QString tempJsonPath = tempDir->path() + "/" + fileInfo.fileName();
QFile tempFile(tempJsonPath);
if (!tempFile.open(QIODevice::WriteOnly)) {
result.errorMessage = QString("Failed to create temp file: %1").arg(tempJsonPath);
return result;
}
tempFile.write(sourceFile.readAll());
tempFile.close();
sourceFile.close();
actualJsonPath = tempJsonPath;
}
if (!QFile::exists(actualJsonPath)) {
result.errorMessage = QString("Input JSON file does not exist: %1").arg(actualJsonPath);
return result;
}
QString toolPath = getToolPath();
QProcess process;
QFileInfo fileInfo(actualJsonPath);
QString baseName = fileInfo.completeBaseName().replace('.', '_').replace('-', '_');
result.generatedFilePath = tempDir->path() + "/" + baseName + ".hpp";
QStringList arguments;
arguments << "-o" << result.generatedFilePath << actualJsonPath;
process.start(toolPath, arguments);
if (!process.waitForStarted(5000)) {
result.errorMessage = QString("Failed to start dconfig2cpp tool: %1").arg(process.errorString());
return result;
}
if (!process.waitForFinished(10000)) {
result.errorMessage = "dconfig2cpp tool execution timeout";
process.kill();
return result;
}
result.exitCode = process.exitCode();
if (result.exitCode == 0) {
result.success = true;
if (!QFile::exists(result.generatedFilePath)) {
result.success = false;
result.errorMessage = QString("Generated file not found: %1").arg(result.generatedFilePath);
}
} else {
result.errorMessage = QString("dconfig2cpp failed with exit code %1. Error: %2")
.arg(result.exitCode)
.arg(QString::fromUtf8(process.readAllStandardError()));
}
return result;
}
QTemporaryDir *tempDir;
};
TEST_F(ut_dconfig2cpp, BasicTypesGeneration) {
QString testFile = ":/data/dconfig2cpp/basic-types.meta.json";
// If resource file doesn't exist, use filesystem path
if (!QFile::exists(testFile)) {
testFile = "./data/dconfig2cpp/basic-types.meta.json";
}
ASSERT_TRUE(QFile::exists(testFile)) << "Test data file not found: " << testFile.toStdString();
auto result = generateCode(testFile);
ASSERT_TRUE(result.success) << result.errorMessage.toStdString();
ASSERT_TRUE(QFile::exists(result.generatedFilePath));
}
TEST_F(ut_dconfig2cpp, BasicTypesPropertyValidation) {
QString testFile = ":/data/dconfig2cpp/basic-types.meta.json";
if (!QFile::exists(testFile)) {
testFile = "./data/dconfig2cpp/basic-types.meta.json";
}
ASSERT_TRUE(QFile::exists(testFile));
auto result = generateCode(testFile);
ASSERT_TRUE(result.success) << result.errorMessage.toStdString();
// Read generated header file content
QFile generatedFile(result.generatedFilePath);
ASSERT_TRUE(generatedFile.open(QIODevice::ReadOnly | QIODevice::Text));
QString generatedContent = generatedFile.readAll();
generatedFile.close();
// Expected Q_PROPERTY declarations
QStringList expectedProperties = {
"Q_PROPERTY(bool booleanTrue READ booleanTrue WRITE setBooleanTrue",
"Q_PROPERTY(bool booleanFalse READ booleanFalse WRITE setBooleanFalse",
"Q_PROPERTY(QString stringValue READ stringValue WRITE setStringValue",
"Q_PROPERTY(QString emptyString READ emptyString WRITE setEmptyString",
"Q_PROPERTY(qlonglong integerPositive READ integerPositive WRITE setIntegerPositive",
"Q_PROPERTY(qlonglong integerNegative READ integerNegative WRITE setIntegerNegative",
"Q_PROPERTY(qlonglong integerZero READ integerZero WRITE setIntegerZero",
"Q_PROPERTY(double doubleValue READ doubleValue WRITE setDoubleValue",
"Q_PROPERTY(double doubleZero READ doubleZero WRITE setDoubleZero",
"Q_PROPERTY(double scientificValue READ scientificValue WRITE setScientificValue"
};
// Verify each expected Q_PROPERTY exists
for (const QString &expectedProperty : expectedProperties) {
EXPECT_TRUE(generatedContent.contains(expectedProperty))
<< "Expected property not found: " << expectedProperty.toStdString();
}
}
TEST_F(ut_dconfig2cpp, NumericTypesDetection) {
QString testFile = ":/data/dconfig2cpp/numeric-types.meta.json";
if (!QFile::exists(testFile)) {
testFile = "./data/dconfig2cpp/numeric-types.meta.json";
}
ASSERT_TRUE(QFile::exists(testFile));
auto result = generateCode(testFile);
ASSERT_TRUE(result.success) << result.errorMessage.toStdString();
// Read generated header file content
QFile generatedFile(result.generatedFilePath);
ASSERT_TRUE(generatedFile.open(QIODevice::ReadOnly | QIODevice::Text));
QString generatedContent = generatedFile.readAll();
generatedFile.close();
// Expected Q_PROPERTY declarations - based on numeric type detection rules
QStringList expectedProperties = {
"Q_PROPERTY(qlonglong pureInteger READ pureInteger WRITE setPureInteger", // Pure integer -> qlonglong
"Q_PROPERTY(double doubleWithDecimal READ doubleWithDecimal WRITE setDoubleWithDecimal", // Decimal -> double
"Q_PROPERTY(double doubleWithZeroDecimal READ doubleWithZeroDecimal WRITE setDoubleWithZeroDecimal", // .0 -> double
"Q_PROPERTY(double scientificNotation READ scientificNotation WRITE setScientificNotation", // Scientific notation -> double
"Q_PROPERTY(qlonglong largeInteger READ largeInteger WRITE setLargeInteger" // Large integer -> qlonglong
};
// Verify each expected Q_PROPERTY exists
for (const QString &expectedProperty : expectedProperties) {
EXPECT_TRUE(generatedContent.contains(expectedProperty))
<< "Expected property not found: " << expectedProperty.toStdString();
}
}
TEST_F(ut_dconfig2cpp, ComplexTypesGeneration) {
QString testFile = ":/data/dconfig2cpp/complex-types.meta.json";
if (!QFile::exists(testFile)) {
testFile = "./data/dconfig2cpp/complex-types.meta.json";
}
ASSERT_TRUE(QFile::exists(testFile));
auto result = generateCode(testFile);
ASSERT_TRUE(result.success) << result.errorMessage.toStdString();
// Read generated header file content
QFile generatedFile(result.generatedFilePath);
ASSERT_TRUE(generatedFile.open(QIODevice::ReadOnly | QIODevice::Text));
QString generatedContent = generatedFile.readAll();
generatedFile.close();
// Expected Q_PROPERTY declarations - complex types
QStringList expectedProperties = {
"Q_PROPERTY(QList<QVariant> emptyArray READ emptyArray WRITE setEmptyArray",
"Q_PROPERTY(QList<QVariant> stringArray READ stringArray WRITE setStringArray",
"Q_PROPERTY(QList<QVariant> mixedArray READ mixedArray WRITE setMixedArray",
"Q_PROPERTY(QVariantMap emptyObject READ emptyObject WRITE setEmptyObject",
"Q_PROPERTY(QVariantMap simpleObject READ simpleObject WRITE setSimpleObject"
};
// Verify each expected Q_PROPERTY exists
for (const QString &expectedProperty : expectedProperties) {
EXPECT_TRUE(generatedContent.contains(expectedProperty))
<< "Expected property not found: " << expectedProperty.toStdString();
}
}
|