/**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "testgenerator.h" #include <QtCore/qdatastream.h> #include <QtCore/qdatetime.h> #include <QtCore/qdebug.h> #include <QtCore/qnumeric.h> #include <QtCore/qstringlist.h> #include <QtCore/qtextstream.h> #include <QtCore/qvariant.h> #include <QtScript/qscriptvalue.h> void TestGenerator::save(const QString& data) { QTextStream out(&m_ofile); out << data; } static QString escape(QString txt) { return txt.replace("\\","\\\\").replace("\"","\\\"").replace("\n","\\n"); } template<typename T> QString prepareToInsert(T value) {return QString::fromAscii("\"") + escape(value) + "\"";} template<> QString prepareToInsert<qsreal>(qsreal value) { if (qIsNaN(value)) return "qQNaN()"; if (qIsInf(value)) return "qInf()"; return QString::number(value, 'g', 16); } template<> QString prepareToInsert<qint32>(qint32 value) {return QString::number(value);} template<> QString prepareToInsert<quint32>(quint32 value) {return QString::number(value);} template<> QString prepareToInsert<quint16>(quint16 value) {return QString::number(value);} template<> QString prepareToInsert<bool>(bool value) {return value ? "true" : "false";} template<> QString prepareToInsert<QString>(QString value) {return QString::fromAscii("\"") + escape(value) + "\"";} template<typename T> QString typeName() {return QString();} template<> QString typeName<qsreal>() {return "qsreal";} template<> QString typeName<qint32>() {return "qint32";} template<> QString typeName<quint32>() {return "quint32";} template<> QString typeName<quint16>() {return "quint16";} template<> QString typeName<bool>() {return "bool";} template<> QString typeName<QString>() {return "QString";} static QString generateIsXXXDef(const QString& name, const QList<QString>& list) { static const QString templ("void tst_QScriptValue::%1_initData()\n"\ "{\n"\ " QTest::addColumn<bool>(\"expected\");\n"\ " initScriptValues();\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_makeData(const char* expr)\n"\ "{\n"\ " static QSet<QString> %1;\n"\ " if (%1.isEmpty()) {\n"\ " %1%2\n"\ " }\n"\ " newRow(expr) << %1.contains(expr);\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_test(const char*, const QScriptValue& value)\n"\ "{\n"\ " QFETCH(bool, expected);\n"\ " QCOMPARE(value.%1(), expected);\n"\ "}\n"\ "\n"\ "DEFINE_TEST_FUNCTION(%1)\n"\ "\n"); if (!list.size()) { qWarning() << name << ": nothing to add!" ; return QString(); } QString result = templ; QStringList set; foreach(QString t, list) { t = escape(t); t.append('\"'); t.prepend('\"'); set.append(QString(" << ")); set.append(t); set.append("\n "); } set.append(";"); return result.arg(name, set.join(QString())); } template<typename T> static QString generateToXXXDef(const QString& name, const QList<QPair<QString, T> >& list) { static const QString templ = "\n"\ "void tst_QScriptValue::%1_initData()\n"\ "{\n"\ " QTest::addColumn<%2>(\"expected\");\n"\ " initScriptValues();\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %2> %1;\n"\ " if (%1.isEmpty()) {\n"\ "%3"\ " }\n"\ " newRow(expr) << %1.value(expr);\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_test(const char*, const QScriptValue& value)\n"\ "{\n"\ " QFETCH(%2, expected);\n"\ " QCOMPARE(value.%1(), expected);\n"\ "}\n"\ "\n"\ "DEFINE_TEST_FUNCTION(%1)\n"; QString result = templ; typename QList<QPair<QString, T> >::const_iterator i = list.constBegin(); QStringList set; for(; i != list.constEnd(); ++i) { QPair<QString, T> t = *i; t.first = escape(t.first); set.append(QString(" ")); set.append(name); set.append(".insert(\""); set.append(t.first); set.append(QString::fromAscii("\", ")); set.append(prepareToInsert<T>(t.second)); set.append(QString::fromAscii(");\n")); } return result.arg(name, typeName<T>(), set.join(QString())); } template<> QString generateToXXXDef<qsreal>(const QString& name, const QList<QPair<QString, qsreal> >& list) { static const QString templ = "\n"\ "void tst_QScriptValue::%1_initData()\n"\ "{\n"\ " QTest::addColumn<%2>(\"expected\");\n"\ " initScriptValues();\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %2> %1;\n"\ " if (%1.isEmpty()) {\n"\ "%3"\ " }\n"\ " newRow(expr) << %1.value(expr);\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_test(const char*, const QScriptValue& value)\n"\ "{\n"\ " QFETCH(%2, expected);\n"\ "%666" " if (qIsInf(expected)) {\n"\ " QVERIFY(qIsInf(value.%1()));\n"\ " return;\n"\ " }\n"\ " QCOMPARE(value.%1(), expected);\n"\ "}\n"\ "\n"\ "DEFINE_TEST_FUNCTION(%1)\n"; QString result = templ; QList<QPair<QString, qsreal> >::const_iterator i = list.constBegin(); QStringList set; for(; i != list.constEnd(); ++i) { QPair<QString, qsreal> t = *i; t.first = escape(t.first); set.append(QString(" ")); set.append(name); set.append(".insert(\""); set.append(t.first); set.append(QString::fromAscii("\", ")); set.append(prepareToInsert<qsreal>(t.second)); set.append(QString::fromAscii(");\n")); } // toInteger shouldn't return NaN, so it would be nice to catch the case. QString hook; if (name == "toNumber") { hook = " if (qIsNaN(expected)) {\n"\ " QVERIFY(qIsNaN(value.toNumber()));\n"\ " return;\n"\ " }\n"; } return result.arg(name, typeName<qsreal>(), set.join(QString()), hook); } template<typename T> static QString generateCastDef(const QList<QPair<QString, T> >& list) { static const QString templ = "\n"\ "void tst_QScriptValue::qscriptvalue_cast%2_initData()\n"\ "{\n"\ " QTest::addColumn<%2>(\"expected\");\n"\ " initScriptValues();\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::qscriptvalue_cast%2_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %2> value;\n"\ " if (value.isEmpty()) {\n"\ "%3"\ " }\n"\ " newRow(expr) << value.value(expr);\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::qscriptvalue_cast%2_test(const char*, const QScriptValue& value)\n"\ "{\n"\ " QFETCH(%2, expected);\n"\ " QCOMPARE(qscriptvalue_cast<%2>(value), expected);\n"\ "}\n"\ "\n"\ "DEFINE_TEST_FUNCTION(qscriptvalue_cast%2)\n"; QString result = templ; typename QList<QPair<QString, T> >::const_iterator i = list.constBegin(); QStringList set; for(; i != list.constEnd(); ++i) { QPair<QString, T> t = *i; t.first = escape(t.first); set.append(QString(" ")); set.append("value.insert(\""); set.append(t.first); set.append(QString::fromAscii("\", ")); set.append(prepareToInsert<T>(t.second)); set.append(QString::fromAscii(");\n")); } return result.arg(typeName<T>(), set.join(QString())); } template<> QString generateCastDef<qsreal>(const QList<QPair<QString, qsreal> >& list) { static const QString templ = "\n"\ "void tst_QScriptValue::qscriptvalue_cast%2_initData()\n"\ "{\n"\ " QTest::addColumn<%2>(\"expected\");\n"\ " initScriptValues();\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::qscriptvalue_cast%2_makeData(const char* expr)\n"\ "{\n"\ " static QHash<QString, %2> value;\n"\ " if (value.isEmpty()) {\n"\ "%3"\ " }\n"\ " newRow(expr) << value.value(expr);\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::qscriptvalue_cast%2_test(const char*, const QScriptValue& value)\n"\ "{\n"\ " QFETCH(%2, expected);\n"\ " if (qIsNaN(expected)) {\n" " QVERIFY(qIsNaN(qscriptvalue_cast<%2>(value)));\n" " return;\n" " }\n"\ " if (qIsInf(expected)) {\n" " QVERIFY(qIsInf(qscriptvalue_cast<%2>(value)));\n" " return;\n" " }\n" " QCOMPARE(qscriptvalue_cast<%2>(value), expected);\n"\ "}\n"\ "\n"\ "DEFINE_TEST_FUNCTION(qscriptvalue_cast%2)\n"; QString result = templ; QList<QPair<QString, qsreal> >::const_iterator i = list.constBegin(); QStringList set; for(; i != list.constEnd(); ++i) { QPair<QString, qsreal> t = *i; t.first = escape(t.first); set.append(QString(" ")); set.append("value.insert(\""); set.append(t.first); set.append(QString::fromAscii("\", ")); set.append(prepareToInsert<qsreal>(t.second)); set.append(QString::fromAscii(");\n")); } return result.arg(typeName<qsreal>(), set.join(QString())); } static QString generateCompareDef(const QString& comparisionType, const QList<QString> tags) { static const QString templ = "\n"\ "void tst_QScriptValue::%1_initData()\n"\ "{\n"\ " QTest::addColumn<QScriptValue>(\"other\");\n"\ " QTest::addColumn<bool>(\"expected\");\n"\ " initScriptValues();\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_makeData(const char *expr)\n"\ "{\n"\ " static QSet<QString> equals;\n"\ " if (equals.isEmpty()) {\n"\ "%2\n"\ " }\n"\ " QHash<QString, QScriptValue>::const_iterator it;\n"\ " for (it = m_values.constBegin(); it != m_values.constEnd(); ++it) {\n"\ " QString tag = QString::fromLatin1(\"%20 <=> %21\").arg(expr).arg(it.key());\n"\ " newRow(tag.toLatin1()) << it.value() << equals.contains(tag);\n"\ " }\n"\ "}\n"\ "\n"\ "void tst_QScriptValue::%1_test(const char *, const QScriptValue& value)\n"\ "{\n"\ " QFETCH(QScriptValue, other);\n"\ " QFETCH(bool, expected);\n"\ " QCOMPARE(value.%1(other), expected);\n"\ "}\n"\ "\n"\ "DEFINE_TEST_FUNCTION(%1)\n"; Q_ASSERT(comparisionType == "strictlyEquals" || comparisionType == "equals" || comparisionType == "lessThan" || comparisionType == "instanceOf"); QString result = templ; QStringList set; foreach(const QString& tmp, tags) { set.append(" equals.insert(\"" + escape(tmp) + "\");"); } return result.arg(comparisionType, set.join("\n")); } static QString generateInitDef(const QVector<QString>& allDataTags) { static const QString templ = "/****************************************************************************\n" "**\n" "** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).\n" "** All rights reserved.\n" "** Contact: Nokia Corporation (qt-info@nokia.com)\n" "**\n" "** This file is part of the test suite of the Qt Toolkit.\n" "**\n" "** $QT_BEGIN_LICENSE:LGPL$\n" "** No Commercial Usage\n" "** This file contains pre-release code and may not be distributed.\n" "** You may use this file in accordance with the terms and conditions\n" "** contained in the Technology Preview License Agreement accompanying\n" "** this package.\n" "**\n" "** GNU Lesser General Public License Usage\n" "** Alternatively, this file may be used under the terms of the GNU Lesser\n" "** General Public License version 2.1 as published by the Free Software\n" "** Foundation and appearing in the file LICENSE.LGPL included in the\n" "** packaging of this file. Please review the following information to\n" "** ensure the GNU Lesser General Public License version 2.1 requirements\n" "** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n" "**\n" "** In addition, as a special exception, Nokia gives you certain additional\n" "** rights. These rights are described in the Nokia Qt LGPL Exception\n" "** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.\n" "**\n" "** If you have questions regarding the use of this file, please contact\n" "** Nokia at qt-info@nokia.com.\n" "**\n" "**\n" "**\n" "**\n" "**\n" "**\n" "**\n" "**\n" "** $QT_END_LICENSE$\n" "**\n" "****************************************************************************/\n" "\n"\ "#include \"tst_qscriptvalue.h\"\n\n"\ "#define DEFINE_TEST_VALUE(expr) m_values.insert(QString::fromLatin1(#expr), expr)\n"\ "\n"\ "void tst_QScriptValue::initScriptValues()\n"\ "{\n"\ " m_values.clear();\n"\ " if (engine) \n"\ " delete engine;\n"\ " engine = new QScriptEngine;\n"\ "%1\n}\n\n"; QString result = templ; QStringList set; foreach(const QString tag, allDataTags) { set.append(" DEFINE_TEST_VALUE(" + tag + ");"); } return result.arg(set.join("\n")); } static void squashTags(QString dataTag, const QVector<bool>& results, QList<QString>& tags, QVector<QString> dataTags) { for(int i = 0; i < results.count(); ++i) { if (results.at(i)) tags.append(dataTag + " <=> " + dataTags[i]); } } QString TestGenerator::generateTest() { // All data tags keept in one place. QVector<QString> dataTags; // Data tags for values that return true in isXXX call QList<QString> isValidList; QList<QString> isBoolList; QList<QString> isBooleanList; QList<QString> isNumberList; QList<QString> isFunctionList; QList<QString> isNullList; QList<QString> isStringList; QList<QString> isUndefinedList; QList<QString> isVariantList; QList<QString> isQObjectList; QList<QString> isQMetaObjectList; QList<QString> isObjectList; QList<QString> isDateList; QList<QString> isRegExpList; QList<QString> isArrayList; QList<QString> isErrorList; // List of pairs data tag and value returned from toXXX call QList<QPair<QString, QString> > toStringList; QList<QPair<QString, qsreal> > toNumberList; QList<QPair<QString, bool> > toBoolList; QList<QPair<QString, bool> > toBooleanList; QList<QPair<QString, qsreal> > toIntegerList; QList<QPair<QString, qint32> > toInt32List; QList<QPair<QString, quint32> > toUInt32List; QList<QPair<QString, quint16> > toUInt16List; // List of complex tags returning true QList<QString> equalsList; QList<QString> strictlyEqualsList; QList<QString> lessThanList; QList<QString> instanceOfList; QList<QPair<QString, QString> > castStringList; QList<QPair<QString, qsreal> > castSRealList; QList<QPair<QString, bool> > castBoolList; QList<QPair<QString, qint32> > castInt32List; QList<QPair<QString, quint32> > castUInt32List; QList<QPair<QString, quint16> > castUInt16List; // Load. m_tempFile.seek(0); QDataStream in(&m_tempFile); in >> dataTags; Q_ASSERT(in.status() == in.Ok); while(!in.atEnd()) { bool isValidRes; bool isBoolRes; bool isBooleanRes; bool isNumberRes; bool isFunctionRes; bool isNullRes; bool isStringRes; bool isUndefinedRes; bool isVariantRes; bool isQObjectRes; bool isQMetaObjectRes; bool isObjectRes; bool isDateRes; bool isRegExpRes; bool isArrayRes; bool isErrorRes; QString toStringRes; qsreal toNumberRes; bool toBoolRes; bool toBooleanRes; qsreal toIntegerRes; qint32 toInt32Res; quint32 toUInt32Res; quint16 toUInt16Res; //toVariantRes; //toDateTimeRes; QVector<bool> equalsRes; QVector<bool> strictlyEqualsRes; QVector<bool> lessThanRes; QVector<bool> instanceOfRes; QString castStringRes; qsreal castSRealRes; bool castBoolRes; qint32 castInt32Res; quint32 castUInt32Res; quint16 castUInt16Res; QString dataTag; in >> dataTag; in >> isValidRes; in >> isBoolRes; in >> isBooleanRes; in >> isNumberRes; in >> isFunctionRes; in >> isNullRes; in >> isStringRes; in >> isUndefinedRes; in >> isVariantRes; in >> isQObjectRes; in >> isQMetaObjectRes; in >> isObjectRes; in >> isDateRes; in >> isRegExpRes; in >> isArrayRes; in >> isErrorRes; if (isValidRes) isValidList.append(dataTag); if (isBoolRes) isBoolList.append(dataTag); if (isBooleanRes) isBooleanList.append(dataTag); if (isNumberRes) isNumberList.append(dataTag); if (isFunctionRes) isFunctionList.append(dataTag); if (isNullRes) isNullList.append(dataTag); if (isStringRes) isStringList.append(dataTag); if (isUndefinedRes) isUndefinedList.append(dataTag); if (isVariantRes) isVariantList.append(dataTag); if (isQObjectRes) isQObjectList.append(dataTag); if (isQMetaObjectRes) isQMetaObjectList.append(dataTag); if (isObjectRes) isObjectList.append(dataTag); if (isDateRes) isDateList.append(dataTag); if (isRegExpRes) isRegExpList.append(dataTag); if (isArrayRes) isArrayList.append(dataTag); if (isErrorRes) isErrorList.append(dataTag); in >> toStringRes; in >> toNumberRes; in >> toBoolRes; in >> toBooleanRes; in >> toIntegerRes; in >> toInt32Res; in >> toUInt32Res; in >> toUInt16Res; //in >> toVariantRes; //in >> toDateTimeRes; toStringList.append(QPair<QString, QString>(dataTag, toStringRes)); toNumberList.append(QPair<QString, qsreal>(dataTag, toNumberRes)); toBoolList.append(QPair<QString, bool>(dataTag, toBoolRes)); toBooleanList.append(QPair<QString, bool>(dataTag, toBooleanRes)); toIntegerList.append(QPair<QString, qsreal>(dataTag, toIntegerRes)); toInt32List.append(QPair<QString, qint32>(dataTag, toInt32Res)); toUInt32List.append(QPair<QString, quint32>(dataTag, toUInt32Res)); toUInt16List.append(QPair<QString, quint16>(dataTag, toUInt16Res)); in >> equalsRes; in >> strictlyEqualsRes; in >> lessThanRes; in >> instanceOfRes; squashTags(dataTag, equalsRes, equalsList, dataTags); squashTags(dataTag, strictlyEqualsRes, strictlyEqualsList, dataTags); squashTags(dataTag, lessThanRes, lessThanList, dataTags); squashTags(dataTag, instanceOfRes, instanceOfList, dataTags); in >> castStringRes; in >> castSRealRes; in >> castBoolRes; in >> castInt32Res; in >> castUInt32Res; in >> castUInt16Res; castStringList.append(QPair<QString, QString>(dataTag, castStringRes)); castSRealList.append(QPair<QString, qsreal>(dataTag, castSRealRes)); castBoolList.append(QPair<QString, bool>(dataTag, castBoolRes)); castInt32List.append(QPair<QString, qint32>(dataTag, castInt32Res)); castUInt32List.append(QPair<QString, quint32>(dataTag, castUInt32Res)); castUInt16List.append(QPair<QString, quint16>(dataTag, castUInt16Res)); Q_ASSERT(in.status() == in.Ok); } Q_ASSERT(in.atEnd()); // Generate. QStringList result; result.append(generateInitDef(dataTags)); result.append(generateIsXXXDef("isValid", isValidList)); result.append(generateIsXXXDef("isBool", isBoolList)); result.append(generateIsXXXDef("isBoolean", isBooleanList)); result.append(generateIsXXXDef("isNumber", isNumberList)); result.append(generateIsXXXDef("isFunction", isFunctionList)); result.append(generateIsXXXDef("isNull", isNullList)); result.append(generateIsXXXDef("isString", isStringList)); result.append(generateIsXXXDef("isUndefined", isUndefinedList)); result.append(generateIsXXXDef("isVariant", isVariantList)); result.append(generateIsXXXDef("isQObject", isQObjectList)); result.append(generateIsXXXDef("isQMetaObject", isQMetaObjectList)); result.append(generateIsXXXDef("isObject", isObjectList)); result.append(generateIsXXXDef("isDate", isDateList)); result.append(generateIsXXXDef("isRegExp", isRegExpList)); result.append(generateIsXXXDef("isArray", isArrayList)); result.append(generateIsXXXDef("isError", isErrorList)); result.append(generateToXXXDef<QString>("toString", toStringList)); result.append(generateToXXXDef<qsreal>("toNumber", toNumberList)); result.append(generateToXXXDef<bool>("toBool", toBoolList)); result.append(generateToXXXDef<bool>("toBoolean", toBooleanList)); result.append(generateToXXXDef<qsreal>("toInteger", toIntegerList)); result.append(generateToXXXDef<qint32>("toInt32", toInt32List)); result.append(generateToXXXDef<quint32>("toUInt32", toUInt32List)); result.append(generateToXXXDef<quint16>("toUInt16", toUInt16List)); result.append(generateCompareDef("equals", equalsList)); result.append(generateCompareDef("strictlyEquals", strictlyEqualsList)); result.append(generateCompareDef("lessThan", lessThanList)); result.append(generateCompareDef("instanceOf", instanceOfList)); result.append(generateCastDef(castStringList)); result.append(generateCastDef(castSRealList)); result.append(generateCastDef(castBoolList)); result.append(generateCastDef(castInt32List)); result.append(generateCastDef(castUInt32List)); result.append(generateCastDef(castUInt16List)); return result.join("\n"); }