//// TestRunner.cpp//// Created by Nissim Hadar on 23 Jan 2019.// Copyright 2013 High Fidelity, Inc.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//#include "TestRunner.h"#include <QFileDialog>#include "Nitpick.h"extern Nitpick* nitpick;TestRunner::TestRunner( QLabel* workingFolderLabel, QLabel* statusLabel, QCheckBox* usePreviousInstallationCheckBox, QCheckBox* runLatest, QLineEdit* url, QCheckBox* runFullSuite, QLineEdit* scriptURL) { _workingFolderLabel = workingFolderLabel; _statusLabel = statusLabel; _usePreviousInstallationCheckBox = usePreviousInstallationCheckBox; _runLatest = runLatest; _url = url; _runFullSuite = runFullSuite; _scriptURL = scriptURL; _downloader = new Downloader();}void TestRunner::setWorkingFolder(QLabel* workingFolderLabel) { // Everything will be written to this folder QString previousSelection = _workingFolder; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } _workingFolder = QFileDialog::getExistingDirectory(nullptr, "Please select a working folder for temporary files", parent, QFileDialog::ShowDirsOnly); // If user canceled then restore previous selection and return if (_workingFolder == "") { _workingFolder = previousSelection; return; } workingFolderLabel->setText(QDir::toNativeSeparators(_workingFolder)); // This file is used for debug purposes. _logFile.setFileName(_workingFolder + "/log.txt");}void TestRunner::downloadBuildXml(void* caller) { // Download the latest High Fidelity build XML. // Note that this is not needed for PR builds (or whenever `Run Latest` is unchecked) // It is still downloaded, to simplify the flow buildXMLDownloaded = false; QStringList urls; QStringList filenames; urls << DEV_BUILD_XML_URL; filenames << DEV_BUILD_XML_FILENAME; _downloader->downloadFiles(urls, _workingFolder, filenames, caller);}void TestRunner::parseBuildInformation() { try { QDomDocument domDocument; QString filename{ _workingFolder + "/" + DEV_BUILD_XML_FILENAME }; QFile file(filename); if (!file.open(QIODevice::ReadOnly) || !domDocument.setContent(&file)) { throw QString("Could not open " + filename); } QString platformOfInterest;#ifdef Q_OS_WIN platformOfInterest = "windows";#elif defined(Q_OS_MAC) platformOfInterest = "mac";#endif QDomElement element = domDocument.documentElement(); // Verify first element is "projects" if (element.tagName() != "projects") { throw("File seems to be in wrong format"); } element = element.firstChild().toElement(); if (element.tagName() != "project") { throw("File seems to be in wrong format"); } if (element.attribute("name") != "interface") { throw("File is not from 'interface' build"); } // Now loop over the platforms, looking for ours bool platformFound{ false }; element = element.firstChild().toElement(); while (!element.isNull()) { if (element.attribute("name") == platformOfInterest) { platformFound = true; break; } element = element.nextSibling().toElement(); } if (!platformFound) { throw("File seems to be in wrong format - platform " + platformOfInterest + " not found"); } element = element.firstChild().toElement(); if (element.tagName() != "build") { throw("File seems to be in wrong format"); } // Next element should be the version element = element.firstChild().toElement(); if (element.tagName() != "version") { throw("File seems to be in wrong format"); } // Add the build number to the end of the filename _buildInformation.build = element.text(); // First sibling should be stable_version element = element.nextSibling().toElement(); if (element.tagName() != "stable_version") { throw("File seems to be in wrong format"); } // Next sibling should be url element = element.nextSibling().toElement(); if (element.tagName() != "url") { throw("File seems to be in wrong format"); } _buildInformation.url = element.text(); } catch (QString errorMessage) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), errorMessage); exit(-1); } catch (...) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "unknown error"); exit(-1); }}QString TestRunner::getInstallerNameFromURL(const QString& url) { // An example URL: https://deployment.highfidelity.com/jobs/pr-build/label%3Dwindows/13023/HighFidelity-Beta-Interface-PR14006-be76c43.exe // On Mac, replace `exe` with `dmg` try { QStringList urlParts = url.split("/"); return urlParts[urlParts.size() - 1]; } catch (QString errorMessage) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), errorMessage); exit(-1); } catch (...) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "unknown error"); exit(-1); }}void TestRunner::appendLog(const QString& message) { if (!_logFile.open(QIODevice::Append | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not open the log file"); exit(-1); } _logFile.write(message.toStdString().c_str()); _logFile.write("\n"); _logFile.close(); nitpick->appendLogWindow(message);}void Worker::setCommandLine(const QString& commandLine) { _commandLine = commandLine;}int Worker::runCommand() { int result = system(_commandLine.toStdString().c_str()); emit commandComplete(); return result;}
//
// TestRunner.cpp
//
// Created by Nissim Hadar on 23 Jan 2019.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "TestRunner.h"
#include <QFileDialog>
#include "Nitpick.h"
extern Nitpick* nitpick;
TestRunner::TestRunner(
QLabel* workingFolderLabel,
QLabel* statusLabel,
QCheckBox* usePreviousInstallationCheckBox,
QCheckBox* runLatest,
QLineEdit* url,
QCheckBox* runFullSuite,
QLineEdit* scriptURL
) {
_workingFolderLabel = workingFolderLabel;
_statusLabel = statusLabel;
_usePreviousInstallationCheckBox = usePreviousInstallationCheckBox;
_runLatest = runLatest;
_url = url;
_runFullSuite = runFullSuite;
_scriptURL = scriptURL;
_downloader = new Downloader();
}
void TestRunner::setWorkingFolder(QLabel* workingFolderLabel) {
// Everything will be written to this folder
QString previousSelection = _workingFolder;
QString parent = previousSelection.left(previousSelection.lastIndexOf('/'));
if (!parent.isNull() && parent.right(1) != "/") {
parent += "/";
}
_workingFolder = QFileDialog::getExistingDirectory(nullptr, "Please select a working folder for temporary files", parent,
QFileDialog::ShowDirsOnly);
// If user canceled then restore previous selection and return
if (_workingFolder == "") {
_workingFolder = previousSelection;
return;
}
workingFolderLabel->setText(QDir::toNativeSeparators(_workingFolder));
// This file is used for debug purposes.
_logFile.setFileName(_workingFolder + "/log.txt");
}
void TestRunner::downloadBuildXml(void* caller) {
// Download the latest High Fidelity build XML.
// Note that this is not needed for PR builds (or whenever `Run Latest` is unchecked)
// It is still downloaded, to simplify the flow
buildXMLDownloaded = false;
QStringList urls;
QStringList filenames;
urls << DEV_BUILD_XML_URL;
filenames << DEV_BUILD_XML_FILENAME;
_downloader->downloadFiles(urls, _workingFolder, filenames, caller);
}
void TestRunner::parseBuildInformation() {
try {
QDomDocument domDocument;
QString filename{ _workingFolder + "/" + DEV_BUILD_XML_FILENAME };
QFile file(filename);
if (!file.open(QIODevice::ReadOnly) || !domDocument.setContent(&file)) {
throw QString("Could not open " + filename);
}
QString platformOfInterest;
#ifdef Q_OS_WIN
platformOfInterest = "windows";
#elif defined(Q_OS_MAC)
platformOfInterest = "mac";
#endif
QDomElement element = domDocument.documentElement();
// Verify first element is "projects"
if (element.tagName() != "projects") {
throw("File seems to be in wrong format");
}
element = element.firstChild().toElement();
if (element.tagName() != "project") {
throw("File seems to be in wrong format");
}
if (element.attribute("name") != "interface") {
throw("File is not from 'interface' build");
}
// Now loop over the platforms, looking for ours
bool platformFound{ false };
element = element.firstChild().toElement();
while (!element.isNull()) {
if (element.attribute("name") == platformOfInterest) {
platformFound = true;
break;
}
element = element.nextSibling().toElement();
}
if (!platformFound) {
throw("File seems to be in wrong format - platform " + platformOfInterest + " not found");
}
element = element.firstChild().toElement();
if (element.tagName() != "build") {
throw("File seems to be in wrong format");
}
// Next element should be the version
element = element.firstChild().toElement();
if (element.tagName() != "version") {
throw("File seems to be in wrong format");
}
// Add the build number to the end of the filename
_buildInformation.build = element.text();
// First sibling should be stable_version
element = element.nextSibling().toElement();
if (element.tagName() != "stable_version") {
throw("File seems to be in wrong format");
}
// Next sibling should be url
element = element.nextSibling().toElement();
if (element.tagName() != "url") {
throw("File seems to be in wrong format");
}
_buildInformation.url = element.text();
}
catch (QString errorMessage) {
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), errorMessage);
exit(-1);
}
catch (...) {
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "unknown error");
exit(-1);
}
}
QString TestRunner::getInstallerNameFromURL(const QString& url) {
// An example URL: https://deployment.highfidelity.com/jobs/pr-build/label%3Dwindows/13023/HighFidelity-Beta-Interface-PR14006-be76c43.exe
// On Mac, replace `exe` with `dmg`
try {
QStringList urlParts = url.split("/");
return urlParts[urlParts.size() - 1];
}
catch (QString errorMessage) {
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), errorMessage);
exit(-1);
}
catch (...) {
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "unknown error");
exit(-1);
}
}
void TestRunner::appendLog(const QString& message) {
if (!_logFile.open(QIODevice::Append | QIODevice::Text)) {
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__),
"Could not open the log file");
exit(-1);
}
_logFile.write(message.toStdString().c_str());
_logFile.write("\n");
_logFile.close();
nitpick->appendLogWindow(message);
}
void Worker::setCommandLine(const QString& commandLine) {
_commandLine = commandLine;
}
int Worker::runCommand() {
int result = system(_commandLine.toStdString().c_str());
emit commandComplete();
return result;
}