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
|
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TEST262RUNNER_H
#define TEST262RUNNER_H
#include <qeventloop.h>
#include <qmap.h>
#include <qmutex.h>
#include <qprocess.h>
#include <qqueue.h>
#include <qset.h>
#include <qthreadpool.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
struct ExecutionEngine;
void initD262(ExecutionEngine *e);
}
struct TestCase {
TestCase() = default;
TestCase(const QString &test)
: test(test) {}
enum State { Skipped, Passes, Fails, Crashes };
struct Result
{
State state;
QString errorMessage;
Result(State state, QString errorMessage = "")
: state(state), errorMessage(errorMessage) { }
void negateResult()
{
switch (state) {
case TestCase::Passes:
state = TestCase::Fails;
break;
case TestCase::Fails:
state = TestCase::Passes;
break;
case TestCase::Skipped:
case TestCase::Crashes:
break;
}
}
};
Result strictExpectation = Result(Passes);
Result sloppyExpectation = Result(Passes);
Result strictResult = Result(Skipped);
Result sloppyResult = Result(Skipped);
bool skipTestCase = false;
bool stillNeedStrictRun = false;
QString test;
};
struct TestData : TestCase {
TestData() = default;
TestData(const TestCase &testCase)
: TestCase(testCase) {}
// flags
bool negative = false;
bool runInStrictMode = true;
bool runInSloppyMode = true;
bool runAsModuleCode = false;
bool async = false;
bool isExcluded = false;
QList<QByteArray> includes;
QByteArray harness;
QByteArray content;
};
class SingleTest;
class Test262Runner : public QObject
{
Q_OBJECT
public:
Test262Runner(const QString &command, const QString &testDir, const QString &expectationsFile);
~Test262Runner();
enum Mode {
Sloppy = 0,
Strict = 1
};
enum Flags {
Verbose = 0x1,
Parallel = 0x2,
ForceBytecode = 0x4,
ForceJIT = 0x8,
WithTestExpectations = 0x10,
UpdateTestExpectations = 0x20,
WriteTestExpectations = 0x40,
};
void setFlags(int f) { flags = f; }
void setFilter(const QString &f) { filter = f; }
void cat();
bool run();
bool report();
QString testDirectory() const { return testDir; }
static void executeTest(QV4::ExecutionEngine &vm, const QString &testData,
const QString &testCasePath = QString(),
const QString &harnessForModules = QString(),
bool runAsModule = false);
private:
friend class SingleTest;
bool loadTests();
void loadTestExpectations();
void updateTestExpectations();
void writeTestExpectations();
void runWithThreadPool();
void runAsExternalTests();
void createProcesses();
void assignTaskOrTerminate(int processIndex);
void assignSloppy(int processIndex);
void assignStrict(int processIndex);
void sendDone(int processIndex);
QString readUntilNull(QProcess &p);
TestData getTestData(const TestCase &testCase);
void parseYaml(const QByteArray &content, TestData *data);
QByteArray harness(const QByteArray &name);
void addResult(TestCase result);
QString command;
QString testDir;
QString expectationsFile;
int flags = 0;
QString filter;
QMap<QString, TestCase> testCases;
QHash<QByteArray, QByteArray> harnessFiles;
QThreadPool *threadPool = nullptr;
QMutex mutex;
QEventLoop loop;
std::vector<std::unique_ptr<QProcess>> processes;
int runningCount = 0;
QQueue<TestData> tasks;
QHash<int, TestData> currentTasks;
};
QT_END_NAMESPACE
#endif
|