2021-11-01 09:18:23 +08:00
|
|
|
#include "ojproblemcasesrunner.h"
|
|
|
|
#include "../utils.h"
|
|
|
|
#include "../settings.h"
|
|
|
|
#include "../systemconsts.h"
|
|
|
|
#include "../widgets/ojproblemsetmodel.h"
|
|
|
|
#include <QProcess>
|
|
|
|
|
|
|
|
OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
|
|
|
|
const QVector<POJProblemCase>& problemCases, QObject *parent):
|
|
|
|
Runner(filename,arguments,workDir,parent)
|
|
|
|
{
|
|
|
|
mProblemCases = problemCases;
|
|
|
|
}
|
|
|
|
|
|
|
|
OJProblemCasesRunner::OJProblemCasesRunner(const QString& filename, const QString& arguments, const QString& workDir,
|
|
|
|
POJProblemCase problemCase, QObject *parent):
|
|
|
|
Runner(filename,arguments,workDir,parent)
|
|
|
|
{
|
|
|
|
mProblemCases.append(problemCase);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OJProblemCasesRunner::runCase(int index,POJProblemCase problemCase)
|
|
|
|
{
|
2021-11-02 01:07:37 +08:00
|
|
|
emit caseStarted(problemCase->getId(),index, mProblemCases.count());
|
2021-11-01 20:44:08 +08:00
|
|
|
auto action = finally([this,&index, &problemCase]{
|
2021-11-02 01:07:37 +08:00
|
|
|
emit caseFinished(problemCase->getId(), index, mProblemCases.count());
|
2021-11-01 09:18:23 +08:00
|
|
|
});
|
|
|
|
QProcess process;
|
|
|
|
bool errorOccurred = false;
|
|
|
|
|
|
|
|
process.setProgram(mFilename);
|
|
|
|
process.setArguments(QProcess::splitCommand(mArguments));
|
|
|
|
process.setWorkingDirectory(mWorkDir);
|
|
|
|
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
|
|
|
QString path = env.value("PATH");
|
|
|
|
QStringList pathAdded;
|
|
|
|
if (pSettings->compilerSets().defaultSet()) {
|
|
|
|
foreach(const QString& dir, pSettings->compilerSets().defaultSet()->binDirs()) {
|
|
|
|
pathAdded.append(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pathAdded.append(pSettings->dirs().app());
|
|
|
|
if (!path.isEmpty()) {
|
|
|
|
path+= PATH_SEPARATOR + pathAdded.join(PATH_SEPARATOR);
|
|
|
|
} else {
|
|
|
|
path = pathAdded.join(PATH_SEPARATOR);
|
|
|
|
}
|
|
|
|
env.insert("PATH",path);
|
|
|
|
process.setProcessEnvironment(env);
|
|
|
|
process.setProcessChannelMode(QProcess::MergedChannels);
|
2021-12-16 10:46:38 +08:00
|
|
|
process.connect(
|
|
|
|
&process, &QProcess::errorOccurred,
|
|
|
|
[&](){
|
|
|
|
errorOccurred= true;
|
|
|
|
});
|
2021-11-01 09:18:23 +08:00
|
|
|
problemCase->output.clear();
|
2021-12-16 10:46:38 +08:00
|
|
|
process.start();
|
2021-11-01 09:18:23 +08:00
|
|
|
process.waitForStarted(5000);
|
|
|
|
if (process.state()==QProcess::Running) {
|
|
|
|
process.write(problemCase->input.toUtf8());
|
|
|
|
process.closeWriteChannel();
|
|
|
|
}
|
|
|
|
QByteArray readed;
|
2021-12-15 19:12:16 +08:00
|
|
|
QByteArray buffer;
|
|
|
|
QStringList outputLines;
|
2021-11-01 09:18:23 +08:00
|
|
|
while (true) {
|
2021-12-15 19:12:16 +08:00
|
|
|
process.waitForFinished(100);
|
|
|
|
readed = process.readAll();
|
|
|
|
buffer += readed;
|
2021-11-01 09:18:23 +08:00
|
|
|
if (process.state()!=QProcess::Running) {
|
|
|
|
break;
|
|
|
|
}
|
2021-11-02 09:29:35 +08:00
|
|
|
if (mStop) {
|
2021-11-01 09:18:23 +08:00
|
|
|
process.closeReadChannel(QProcess::StandardOutput);
|
|
|
|
process.closeReadChannel(QProcess::StandardError);
|
|
|
|
process.closeWriteChannel();
|
|
|
|
process.terminate();
|
|
|
|
process.kill();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (errorOccurred)
|
|
|
|
break;
|
2021-12-15 19:12:16 +08:00
|
|
|
QList<QByteArray> lines = splitByteArrayToLines(buffer);
|
2021-12-16 10:46:38 +08:00
|
|
|
// qDebug()<<"----do buffer----";
|
|
|
|
// qDebug()<<readed;
|
|
|
|
// qDebug()<<buffer;
|
|
|
|
// qDebug()<<lines.count();
|
2021-12-15 19:12:16 +08:00
|
|
|
if (lines.count()>=2) {
|
|
|
|
for (int i=0;i<lines.count()-1;i++) {
|
|
|
|
QString line = QString::fromLocal8Bit(lines[i]);
|
|
|
|
emit newOutputLineGetted(problemCase->getId(),line);
|
|
|
|
outputLines.append(line);
|
|
|
|
}
|
|
|
|
buffer = lines.last();
|
|
|
|
while (buffer.endsWith('\0')) {
|
|
|
|
buffer.remove(buffer.length()-1,1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buffer += process.readAll();
|
|
|
|
QList<QByteArray> lines = splitByteArrayToLines(buffer);
|
|
|
|
for (int i=0;i<lines.count();i++) {
|
|
|
|
QString line = QString::fromLocal8Bit(lines[i]);
|
|
|
|
emit newOutputLineGetted(problemCase->getId(),line);
|
|
|
|
outputLines.append(line);
|
2021-11-01 09:18:23 +08:00
|
|
|
}
|
|
|
|
if (errorOccurred) {
|
|
|
|
//qDebug()<<"process error:"<<process.error();
|
|
|
|
switch (process.error()) {
|
|
|
|
case QProcess::FailedToStart:
|
|
|
|
emit runErrorOccurred(tr("The runner process '%1' failed to start.").arg(mFilename));
|
|
|
|
break;
|
|
|
|
// case QProcess::Crashed:
|
|
|
|
// if (!mStop)
|
|
|
|
// emit runErrorOccurred(tr("The runner process crashed after starting successfully."));
|
|
|
|
// break;
|
|
|
|
case QProcess::Timedout:
|
|
|
|
emit runErrorOccurred(tr("The last waitFor...() function timed out."));
|
|
|
|
break;
|
|
|
|
case QProcess::WriteError:
|
|
|
|
emit runErrorOccurred(tr("An error occurred when attempting to write to the runner process."));
|
|
|
|
break;
|
|
|
|
case QProcess::ReadError:
|
|
|
|
emit runErrorOccurred(tr("An error occurred when attempting to read from the runner process."));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-12-15 19:12:16 +08:00
|
|
|
problemCase->output = linesToText(outputLines);
|
2021-11-01 09:18:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void OJProblemCasesRunner::run()
|
|
|
|
{
|
|
|
|
emit started();
|
|
|
|
auto action = finally([this]{
|
|
|
|
emit terminated();
|
|
|
|
});
|
2021-12-16 10:46:38 +08:00
|
|
|
for (int i=0; i < mProblemCases.size(); i++) {
|
2021-11-01 09:18:23 +08:00
|
|
|
if (mStop)
|
|
|
|
break;
|
2021-12-16 10:46:38 +08:00
|
|
|
POJProblemCase problemCase = mProblemCases[i];
|
2021-11-01 09:18:23 +08:00
|
|
|
runCase(i,problemCase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|