/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "abstracttestsuite.h"
#include <QtTest/QtTest>
#include <QtCore/qset.h>
#include <QtCore/QSysInfo>
#include <QtCore/qtextstream.h>
#include <private/qmetaobjectbuilder_p.h>

/*!
   AbstractTestSuite provides a way of building QtTest test objects
   dynamically. The use case is integration of JavaScript test suites
   into QtTest autotests.

   Subclasses add their tests functions with addTestFunction() in the
   constructor, and must reimplement runTestFunction(). Additionally,
   subclasses can reimplement initTestCase() and cleanupTestCase()
   (but make sure to call the base implementation).

   AbstractTestSuite uses configuration files for getting information
   about skipped tests (skip.txt) and expected test failures
   (expect_fail.txt). Subclasses must reimplement
   createSkipConfigFile() and createExpectFailConfigFile() for
   creating these files, and configData() for processing an entry of
   such a file.

   The config file format is as follows:
   - Lines starting with '#' are skipped.
   - Lines of the form [SYMBOL] means that the upcoming data
     should only be processed if the given SYMBOL is defined on
     this platform.
   - Any other line is split on ' | ' and handed off to the client.

   Subclasses must provide a default tests directory (where the
   subclass expects to find the script files to run as tests), and a
   default config file directory. Some environment variables can be
   used to affect where AbstractTestSuite will look for files:

   - QTSCRIPT_TEST_CONFIG_DIR: Overrides the default test config path.

   - QTSCRIPT_TEST_CONFIG_SUFFIX: Is appended to "skip" and
   "expect_fail" to create the test config name. This makes it easy to
   maintain skip- and expect_fail-files corresponding to different
   revisions of a test suite, and switch between them.

   - QTSCRIPT_TEST_DIR: Overrides the default test dir.

   AbstractTestSuite does _not_ define how the test dir itself is
   processed or how tests are run; this is left up to the subclass.

   If no config files are found, AbstractTestSuite will ask the
   subclass to create a default skip file. Also, the
   shouldGenerateExpectedFailures variable will be set to true. The
   subclass should check for this when a test fails, and add an entry
   to its set of expected failures. When all tests have been run,
   AbstractTestSuite will ask the subclass to create the expect_fail
   file based on the tests that failed. The next time the autotest is
   run, the created config files will be used.

   The reason for skipping a test is usually that it takes a very long
   time to complete (or even hangs completely), or it crashes. It's
   not possible for the test runner to know in advance which tests are
   problematic, which is why the entries to the skip file are
   typically added manually. When running tests for the first time, it
   can be useful to run the autotest with the -v1 command line option,
   so you can see the name of each test before it's run, and can add a
   skip entry if appropriate.
*/

class TestConfigClientInterface;
// For parsing information about skipped tests and expected failures.
class TestConfigParser
{
public:
    static void parse(const QString &path,
                      TestConfig::Mode mode,
                      TestConfigClientInterface *client);

private:
    static QString unescape(const QString &);
    static bool isKnownSymbol(const QString &);
    static bool isDefined(const QString &);

    static QSet<QString> knownSymbols;
    static QSet<QString> definedSymbols;
};

QSet<QString> TestConfigParser::knownSymbols;
QSet<QString> TestConfigParser::definedSymbols;

/**
   Parses the config file at the given \a path in the given \a mode.
   Handling of errors and data is delegated to the given \a client.
*/
void TestConfigParser::parse(const QString &path,
                             TestConfig::Mode mode,
                             TestConfigClientInterface *client)
{
    QFile file(path);
    if (!file.open(QIODevice::ReadOnly))
        return;
    QTextStream stream(&file);
    int lineNumber = 0;
    QString predicate;
    const QString separator = QString::fromLatin1(" | ");
    while (!stream.atEnd()) {
        ++lineNumber;
        QString line = stream.readLine();
        if (line.isEmpty())
            continue;
        if (line.startsWith('#')) // Comment
            continue;
        if (line.startsWith('[')) { // Predicate
            if (!line.endsWith(']')) {
                client->configError(path, "malformed predicate", lineNumber);
                return;
            }
            QString symbol = line.mid(1, line.size()-2);
            if (isKnownSymbol(symbol)) {
                predicate = symbol;
            } else {
                qWarning("symbol %s is not known -- add it to TestConfigParser!", qPrintable(symbol));
                predicate = QString();
            }
        } else {
            if (predicate.isEmpty() || isDefined(predicate)) {
                QStringList parts = line.split(separator, Qt::KeepEmptyParts);
                for (int i = 0; i < parts.size(); ++i)
                    parts[i] = unescape(parts[i]);
                client->configData(mode, parts);
            }
        }
    }
}

QString TestConfigParser::unescape(const QString &str)
{
    return QString(str).replace("\\n", "\n");
}

bool TestConfigParser::isKnownSymbol(const QString &symbol)
{
    if (knownSymbols.isEmpty()) {
        knownSymbols
            // If you add a symbol here, add a case for it in
            // isDefined() as well.
            << "Q_OS_LINUX"
            << "Q_OS_SOLARIS"
            << "Q_OS_WINCE"
            << "Q_OS_SYMBIAN"
            << "Q_OS_MAC"
            << "Q_OS_WIN"
            << "Q_CC_MSVC"
            << "Q_CC_MSVC32"
            << "Q_CC_MSVC64"
            << "Q_CC_MINGW"
            << "Q_CC_MINGW32"
            << "Q_CC_MINGW64"
            << "Q_CC_INTEL"
            << "Q_CC_INTEL32"
            << "Q_CC_INTEL64"
            ;
    }
    return knownSymbols.contains(symbol);
}

bool TestConfigParser::isDefined(const QString &symbol)
{
    if (definedSymbols.isEmpty()) {
        definedSymbols
#ifdef Q_OS_LINUX
            << "Q_OS_LINUX"
#endif
#ifdef Q_OS_SOLARIS
            << "Q_OS_SOLARIS"
#endif
#ifdef Q_OS_WINCE
            << "Q_OS_WINCE"
#endif
#ifdef Q_OS_SYMBIAN
            << "Q_OS_SYMBIAN"
#endif
#ifdef Q_OS_MAC
            << "Q_OS_MAC"
#endif
#ifdef Q_OS_WIN
            << "Q_OS_WIN"
#endif
#ifdef Q_CC_MSVC
            << "Q_CC_MSVC"
            << (QStringLiteral("Q_CC_MSVC") + QString::number(QSysInfo::WordSize))
#endif
#ifdef Q_CC_MINGW
            << "Q_CC_MINGW"
            << (QStringLiteral("Q_CC_MINGW") + QString::number(QSysInfo::WordSize))
#endif
#ifdef Q_CC_INTEL
            << "Q_CC_INTEL"
            << (QStringLiteral("Q_CC_INTEL") + QString::number(QSysInfo::WordSize))
#endif
            ;
    }
    return definedSymbols.contains(symbol);
}


const QMetaObject *AbstractTestSuite::metaObject() const
{
    return dynamicMetaObject;
}

void *AbstractTestSuite::qt_metacast(const char *_clname)
{
    if (!_clname) return 0;
    if (!strcmp(_clname, dynamicMetaObject->className()))
        return static_cast<void*>(const_cast<AbstractTestSuite*>(this));
    return QObject::qt_metacast(_clname);
}

void AbstractTestSuite::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    Q_UNUSED(_a);
    if (_c == QMetaObject::InvokeMetaMethod) {
        AbstractTestSuite *_t = static_cast<AbstractTestSuite *>(_o);
        switch (_id) {
        case 0:
            _t->initTestCase();
            break;
        case 1:
            _t->cleanupTestCase();
            break;
        default:
            // If another method is added above, this offset must be adjusted.
            _t->runTestFunction(_id - 2);
        }
    }
}

int AbstractTestSuite::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QObject::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        Q_ASSERT(dynamicMetaObject->cast(this));
        int ownMethodCount = dynamicMetaObject->methodCount() - dynamicMetaObject->methodOffset();
        if (_id < ownMethodCount)
            qt_static_metacall(this, _c, _id, _a);
        _id -= ownMethodCount;
    }
    return _id;
}

void AbstractTestSuite::addPrivateSlot(const QByteArray &signature)
{
    QMetaMethodBuilder slot = metaBuilder->addSlot(signature);
    slot.setAccess(QMetaMethod::Private);
}

AbstractTestSuite::AbstractTestSuite(const QByteArray &className,
                                     const QString &defaultTestsPath,
                                     const QString &defaultConfigPath)
    : shouldGenerateExpectedFailures(false),
      dynamicMetaObject(0),
      metaBuilder(new QMetaObjectBuilder)
{
    metaBuilder->setSuperClass(&QObject::staticMetaObject);
    metaBuilder->setClassName(className);
    metaBuilder->setStaticMetacallFunction(qt_static_metacall);

    QString testConfigPath = qgetenv("QTSCRIPT_TEST_CONFIG_DIR");
    if (testConfigPath.isEmpty())
        testConfigPath = defaultConfigPath;
    QString configSuffix = qgetenv("QTSCRIPT_TEST_CONFIG_SUFFIX");
    skipConfigPath = QString::fromLatin1("%0/skip%1.txt")
                     .arg(testConfigPath).arg(configSuffix);
    expectFailConfigPath = QString::fromLatin1("%0/expect_fail%1.txt")
                           .arg(testConfigPath).arg(configSuffix);

    QString testsPath = qgetenv("QTSCRIPT_TEST_DIR");
    if (testsPath.isEmpty())
        testsPath = defaultTestsPath;
    testsDir = QDir(testsPath);

    addTestFunction("initTestCase");
    addTestFunction("cleanupTestCase");

    // Subclass constructors should add their custom test functions to
    // the meta-object and call finalizeMetaObject().
}

AbstractTestSuite::~AbstractTestSuite()
{
    free(dynamicMetaObject);
}

void AbstractTestSuite::addTestFunction(const QString &name,
                                        DataFunctionCreation dfc)
{
    if (dfc == CreateDataFunction) {
        QString dataSignature = QString::fromLatin1("%0_data()").arg(name);
        addPrivateSlot(dataSignature.toLatin1());
    }
    QString signature = QString::fromLatin1("%0()").arg(name);
    addPrivateSlot(signature.toLatin1());
}

void AbstractTestSuite::finalizeMetaObject()
{
    dynamicMetaObject = metaBuilder->toMetaObject();
}

void AbstractTestSuite::initTestCase()
{
    if (!testsDir.exists()) {
        QString message = QString::fromLatin1("tests directory (%0) doesn't exist.")
                          .arg(testsDir.path());
        QFAIL(qPrintable(message));
        return;
    }

    if (QFileInfo(skipConfigPath).exists())
        TestConfigParser::parse(skipConfigPath, TestConfig::Skip, this);
    else
        createSkipConfigFile();

    if (QFileInfo(expectFailConfigPath).exists())
        TestConfigParser::parse(expectFailConfigPath, TestConfig::ExpectFail, this);
    else
        shouldGenerateExpectedFailures = true;
}

void AbstractTestSuite::cleanupTestCase()
{
    if (shouldGenerateExpectedFailures)
        createExpectFailConfigFile();
}

void AbstractTestSuite::configError(const QString &path, const QString &message, int lineNumber)
{
    QString output;
    output.append(path);
    if (lineNumber != -1)
        output.append(":").append(QString::number(lineNumber));
    output.append(": ").append(message);
    QFAIL(qPrintable(output));
}

void AbstractTestSuite::createSkipConfigFile()
{
    QFile file(skipConfigPath);
    if (!file.open(QIODevice::WriteOnly))
        return;
    QWARN(qPrintable(QString::fromLatin1("creating %0").arg(skipConfigPath)));
    QTextStream stream(&file);

    writeSkipConfigFile(stream);

    file.close();
}

void AbstractTestSuite::createExpectFailConfigFile()
{
    QFile file(expectFailConfigPath);
    if (!file.open(QFile::WriteOnly))
        return;
    QWARN(qPrintable(QString::fromLatin1("creating %0").arg(expectFailConfigPath)));
    QTextStream stream(&file);

    writeExpectFailConfigFile(stream);

    file.close();
}

/*!
  Convenience function for reading all contents of a file.
 */
QString AbstractTestSuite::readFile(const QString &filename)
{
    QFile file(filename);
    if (!file.open(QFile::ReadOnly))
        return QString();
    QTextStream stream(&file);
    stream.setCodec("UTF-8");
    return stream.readAll();
}

/*!
  Escapes characters in the string \a str so it's suitable for writing
  to a config file.
 */
QString AbstractTestSuite::escape(const QString &str)
{
    return QString(str).replace("\n", "\\n");
}
