aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@404: * Software engineering by Intevation GmbH aheinecke@404: * aheinecke@404: * This file is Free Software under the GNU GPL (v>=2) aheinecke@404: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@404: * See LICENSE.txt for details. aheinecke@404: */ aheinecke@100: #include "cinstprocesstest.h" aheinecke@100: #include "certificatelist.h" aheinecke@100: #include "errorcodes.h" aheinecke@298: #include "common.h" aheinecke@100: aheinecke@100: #include aheinecke@100: #include aheinecke@100: #include aheinecke@100: #include aheinecke@100: aheinecke@313: #include aheinecke@313: aheinecke@294: #define CINST_PATH_CANDIDATES "../../cinst/cinst" << \ aheinecke@294: "cinst" << "../../cinst/cinst.exe" << "cinst.exe"; aheinecke@100: aheinecke@294: QProcess *CinstProcessTest::startCinstProcess(const QStringList& args) { aheinecke@294: QStringList cinstCandidates; aheinecke@294: cinstCandidates << CINST_PATH_CANDIDATES; aheinecke@294: QString processPath; aheinecke@294: foreach (const QString& candidate, cinstCandidates) { aheinecke@294: QFileInfo fi(candidate); aheinecke@294: if (fi.isExecutable()) { aheinecke@294: processPath = candidate; aheinecke@294: break; aheinecke@294: } aheinecke@294: } aheinecke@294: andre@1060: QStringList newArgs = args; andre@1060: newArgs << "--debug"; andre@1060: aheinecke@100: QProcess *installerProcess = new QProcess(); andre@1060: installerProcess->setArguments(newArgs); aheinecke@294: installerProcess->setProgram(processPath); aheinecke@100: installerProcess->start(); aheinecke@100: installerProcess->waitForStarted(); aheinecke@100: return installerProcess; aheinecke@100: } aheinecke@100: aheinecke@151: #define VERIFY_PROC_DEBUG(x) \ aheinecke@151: if (! x ) { \ aheinecke@151: qDebug() << "Stdout:" << proc->readAllStandardOutput(); \ aheinecke@151: qDebug() << "Stderr:" << proc->readAllStandardError(); \ aheinecke@151: qDebug() << "Exit code: " << proc->exitCode(); \ andre@305: qDebug() << "Exit status: " << proc->exitStatus(); \ aheinecke@151: } \ aheinecke@151: QVERIFY(x) aheinecke@151: aheinecke@100: void finishVerify(QProcess *proc, int exitCode) { aheinecke@100: proc->closeWriteChannel(); aheinecke@100: proc->waitForFinished(); aheinecke@151: VERIFY_PROC_DEBUG(proc->exitStatus() == QProcess::NormalExit); aheinecke@151: VERIFY_PROC_DEBUG(proc->exitCode() == exitCode); aheinecke@100: delete proc; aheinecke@100: } aheinecke@100: aheinecke@100: void CinstProcessTest::testValidInput() { aheinecke@295: QStringList args; aheinecke@295: args << "list=" + validListFile.fileName(); aheinecke@100: aheinecke@295: QTemporaryFile instructions; aheinecke@295: instructions.open(); aheinecke@295: foreach (const Certificate &cert, validList.getCertificates()) { aheinecke@295: instructions.write(cert.base64Line().toLatin1()); aheinecke@295: instructions.write("\n"); aheinecke@295: } aheinecke@295: instructions.close(); aheinecke@100: aheinecke@439: args << "choices=" + instructions.fileName(); aheinecke@100: aheinecke@295: QProcess* installerProcess = startCinstProcess(args); aheinecke@159: finishVerify(installerProcess, ERR_NO_ERROR); aheinecke@100: } aheinecke@100: aheinecke@100: void CinstProcessTest::initTestCase() { aheinecke@295: QFile valid(":/list-valid-signed.txt"); aheinecke@295: valid.open(QIODevice::ReadOnly); aheinecke@295: validListFile.open(); aheinecke@295: validListFile.write(valid.readAll()); aheinecke@295: valid.close(); aheinecke@295: validListFile.close(); aheinecke@295: validList = CertificateList(validListFile.fileName().toLocal8Bit().data()); aheinecke@295: aheinecke@295: QVERIFY(validList.isValid()); aheinecke@295: aheinecke@295: QFile invalid(":/list-invalid-signed.txt"); aheinecke@295: invalid.open(QIODevice::ReadOnly); aheinecke@295: invalidListFile.open(); aheinecke@295: invalidListFile.write(invalid.readAll()); aheinecke@295: invalid.close(); aheinecke@295: invalidListFile.close(); aheinecke@295: invalidList = CertificateList(invalidListFile.fileName().toLocal8Bit().data()); aheinecke@295: aheinecke@295: QVERIFY(!invalidList.isValid()); aheinecke@295: aheinecke@295: QFile other(":/list-valid-other-signature.txt"); aheinecke@295: other.open(QIODevice::ReadOnly); aheinecke@295: otherListFile.open(); aheinecke@295: otherListFile.write(other.readAll()); aheinecke@295: other.close(); aheinecke@295: otherListFile.close(); aheinecke@295: otherList = CertificateList(otherListFile.fileName().toLocal8Bit().data()); aheinecke@295: aheinecke@295: QVERIFY(!otherList.isValid()); andre@306: andre@904: /* Set HOME or APPDATA so that nss stores are not touched andre@306: * see nsstest for the real test of that code */ andre@306: #ifdef WIN32 aheinecke@313: { aheinecke@314: char buf[fakeHome.path().toLocal8Bit().size() + 9]; aheinecke@314: snprintf(buf, fakeHome.path().toLocal8Bit().size() + 9, aheinecke@314: "APPDATA=%s",fakeHome.path().toLocal8Bit().constData()); aheinecke@313: QVERIFY(_putenv (buf) != -1); aheinecke@313: } andre@306: #else andre@306: QVERIFY(!setenv ("HOME", fakeHome.path().toLocal8Bit().constData(), 1)); andre@306: #endif aheinecke@100: } aheinecke@100: aheinecke@100: void CinstProcessTest::testNoList() { aheinecke@100: /* No list */ aheinecke@296: QTemporaryFile emptyFile; aheinecke@296: emptyFile.open(); aheinecke@296: emptyFile.close(); aheinecke@100: aheinecke@296: QStringList args; aheinecke@296: args << "list=" + emptyFile.fileName(); aheinecke@296: aheinecke@296: QTemporaryFile instructions; aheinecke@296: instructions.open(); aheinecke@249: foreach (const Certificate &cert, validList.getCertificates()) { aheinecke@296: instructions.write(cert.base64Line().toLatin1()); aheinecke@296: instructions.write("\n"); aheinecke@100: } aheinecke@296: instructions.close(); aheinecke@296: aheinecke@439: args << "choices=" + instructions.fileName(); aheinecke@296: aheinecke@296: QProcess* installerProcess = startCinstProcess(args); aheinecke@100: finishVerify(installerProcess, ERR_INVALID_INPUT_NO_LIST); aheinecke@100: } aheinecke@100: aheinecke@100: void CinstProcessTest::testGarbageInput() { aheinecke@298: QStringList args; aheinecke@100: aheinecke@298: QString garbage = getRandomDataFile(21*1024*1024); aheinecke@298: args << "list=" + garbage; aheinecke@298: aheinecke@298: QTemporaryFile instructions; aheinecke@298: instructions.open(); aheinecke@298: foreach (const Certificate &cert, validList.getCertificates()) { aheinecke@298: instructions.write(cert.base64Line().toLatin1()); aheinecke@298: instructions.write("\n"); aheinecke@298: } aheinecke@298: instructions.close(); aheinecke@298: aheinecke@439: args << "choices=" + instructions.fileName(); aheinecke@298: aheinecke@298: QProcess* installerProcess = startCinstProcess(args); aheinecke@298: /* If the following failed there may be leftovers in /tmp */ aheinecke@298: finishVerify(installerProcess, ERR_INVALID_INPUT_NO_LIST); aheinecke@298: QVERIFY(QFile::remove(garbage)); aheinecke@100: } aheinecke@100: aheinecke@100: void CinstProcessTest::testNoInput() { aheinecke@298: QStringList args; aheinecke@298: args << "list=foobazbuf"; aheinecke@439: args << "choices=bazbuffoo"; aheinecke@298: QProcess* installerProcess; aheinecke@298: installerProcess = startCinstProcess(args); aheinecke@100: finishVerify(installerProcess, ERR_INVALID_INPUT_NO_LIST); aheinecke@100: } aheinecke@100: aheinecke@100: aheinecke@100: void CinstProcessTest::testNoInstructions() { aheinecke@100: /* No instructions */ aheinecke@298: QTemporaryFile emptyFile; aheinecke@298: emptyFile.open(); aheinecke@298: emptyFile.close(); aheinecke@100: aheinecke@298: QStringList args; aheinecke@298: args << "list=" + validListFile.fileName(); aheinecke@439: args << "choices=" + emptyFile.fileName(); aheinecke@298: aheinecke@298: QProcess* installerProcess = startCinstProcess(args); aheinecke@100: finishVerify(installerProcess, ERR_NO_INSTRUCTIONS); aheinecke@100: } aheinecke@100: aheinecke@100: void CinstProcessTest::testInvalidInstruction() { aheinecke@298: QStringList args; aheinecke@298: args << "list=" + validListFile.fileName(); aheinecke@100: aheinecke@298: QTemporaryFile instructions; aheinecke@298: instructions.open(); aheinecke@298: foreach (const Certificate &cert, validList.getCertificates()) { aheinecke@298: instructions.write(cert.base64Line().toLatin1()); aheinecke@298: instructions.write("\n"); aheinecke@298: } aheinecke@298: instructions.write("I:ABCDEF\n"); aheinecke@298: instructions.close(); aheinecke@100: aheinecke@439: args << "choices=" + instructions.fileName(); aheinecke@298: aheinecke@298: QProcess* installerProcess = startCinstProcess(args); aheinecke@100: aheinecke@100: finishVerify(installerProcess, ERR_INVALID_INSTRUCTIONS); aheinecke@100: } aheinecke@100: aheinecke@151: void CinstProcessTest::testUninstall() { aheinecke@298: QStringList args; aheinecke@298: args << "list=" + validListFile.fileName(); aheinecke@439: args << "choices=uninstall"; aheinecke@151: aheinecke@298: QProcess* installerProcess = startCinstProcess(args); aheinecke@151: aheinecke@159: finishVerify(installerProcess, ERR_NO_ERROR); aheinecke@151: } aheinecke@151: aheinecke@100: QTEST_GUILESS_MAIN (CinstProcessTest);