mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Added a regression test system to ResInsight.
Based on image comparison. Command line invocation. p4#: 20433
This commit is contained in:
parent
baeba974bf
commit
0c437a0121
@ -53,6 +53,8 @@
|
||||
#include "cafUiProcess.h"
|
||||
|
||||
#include "RimUiTreeModelPdm.h"
|
||||
#include "RiaImageCompareReporter.h"
|
||||
#include "RiaImageFileCompare.h"
|
||||
|
||||
namespace caf
|
||||
{
|
||||
@ -66,6 +68,18 @@ void AppEnum< RIApplication::RINavigationPolicy >::setUp()
|
||||
}
|
||||
|
||||
|
||||
namespace RegTestData
|
||||
{
|
||||
const QString generatedFolderName = "RegTestGeneratedImages";
|
||||
const QString diffFolderName = "RegTestDiffImages";
|
||||
const QString baseFolderName = "RegTestBaseImages";
|
||||
const QString testProjectName = "RegressionTest.rip";
|
||||
const QString testFolderFilter = "TestCase*";
|
||||
const QString imageCompareExeName = "compare";
|
||||
const QString reportFileName = "ResInsightRegressionTestReport.html";
|
||||
};
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
///
|
||||
/// \class RIApplication
|
||||
@ -214,6 +228,7 @@ bool RIApplication::loadProject(const QString& projectFileName)
|
||||
|
||||
m_project->fileName = projectFileName;
|
||||
m_project->readFile();
|
||||
m_project->fileName = projectFileName; // Make sure we overwrite the old filename read from the project file
|
||||
|
||||
if (m_project->projectFileVersionString().isEmpty())
|
||||
{
|
||||
@ -602,12 +617,23 @@ bool RIApplication::parseArguments()
|
||||
bool openLatestProject = false;
|
||||
QString projectFilename;
|
||||
QStringList caseNames;
|
||||
QString regressionTestPath;
|
||||
|
||||
enum ArgumentParsingType
|
||||
{
|
||||
PARSE_PROJECT_FILE_NAME,
|
||||
PARSE_CASE_NAMES,
|
||||
PARSE_START_DIR,
|
||||
PARSE_REGRESSION_TEST_PATH,
|
||||
PARSING_NONE
|
||||
};
|
||||
|
||||
ArgumentParsingType argumentParsingType = PARSING_NONE;
|
||||
|
||||
bool isParsingProjectFile = false;
|
||||
bool isParsingCaseNames = false;
|
||||
bool isParsingStartDir = false;
|
||||
bool showHelp = false;
|
||||
bool isSaveSnapshotsForAllViews = false;
|
||||
bool isRunRegressionTest = false;
|
||||
bool isUpdateRegressionTest = false;
|
||||
|
||||
int i;
|
||||
for (i = 1; i < arguments.size(); i++)
|
||||
@ -628,25 +654,19 @@ bool RIApplication::parseArguments()
|
||||
}
|
||||
else if (arg.toLower() == "-project")
|
||||
{
|
||||
isParsingCaseNames = false;
|
||||
isParsingProjectFile = true;
|
||||
isParsingStartDir = false;
|
||||
argumentParsingType = PARSE_PROJECT_FILE_NAME;
|
||||
|
||||
foundKnownOption = true;
|
||||
}
|
||||
else if (arg.toLower() == "-case")
|
||||
{
|
||||
isParsingCaseNames = true;
|
||||
isParsingProjectFile = false;
|
||||
isParsingStartDir = false;
|
||||
argumentParsingType = PARSE_CASE_NAMES;
|
||||
|
||||
foundKnownOption = true;
|
||||
}
|
||||
else if (arg.toLower() == "-startdir")
|
||||
{
|
||||
isParsingCaseNames = false;
|
||||
isParsingProjectFile = false;
|
||||
isParsingStartDir = true;
|
||||
argumentParsingType = PARSE_START_DIR;
|
||||
|
||||
foundKnownOption = true;
|
||||
}
|
||||
@ -656,22 +676,48 @@ bool RIApplication::parseArguments()
|
||||
|
||||
foundKnownOption = true;
|
||||
}
|
||||
else if (arg.toLower() == "-regressiontest")
|
||||
{
|
||||
isRunRegressionTest = true;
|
||||
|
||||
argumentParsingType = PARSE_REGRESSION_TEST_PATH;
|
||||
|
||||
foundKnownOption = true;
|
||||
}
|
||||
else if (arg.toLower() == "-updateregressiontestbase")
|
||||
{
|
||||
isUpdateRegressionTest = true;
|
||||
|
||||
argumentParsingType = PARSE_REGRESSION_TEST_PATH;
|
||||
|
||||
foundKnownOption = true;
|
||||
}
|
||||
|
||||
if (!foundKnownOption)
|
||||
{
|
||||
if (isParsingProjectFile && QFile::exists(arg))
|
||||
switch (argumentParsingType)
|
||||
{
|
||||
projectFilename = arg;
|
||||
}
|
||||
case PARSE_PROJECT_FILE_NAME:
|
||||
if (QFile::exists(arg))
|
||||
{
|
||||
projectFilename = arg;
|
||||
}
|
||||
break;
|
||||
case PARSE_CASE_NAMES:
|
||||
{
|
||||
caseNames.append(arg);
|
||||
}
|
||||
break;
|
||||
|
||||
if (isParsingCaseNames)
|
||||
{
|
||||
caseNames.append(arg);
|
||||
}
|
||||
|
||||
if (isParsingStartDir)
|
||||
{
|
||||
m_startupDefaultDirectory = arg;
|
||||
case PARSE_START_DIR:
|
||||
{
|
||||
m_startupDefaultDirectory = arg;
|
||||
}
|
||||
break;
|
||||
case PARSE_REGRESSION_TEST_PATH:
|
||||
{
|
||||
regressionTestPath = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -682,19 +728,33 @@ bool RIApplication::parseArguments()
|
||||
helpText += "Copyright Statoil ASA, Ceetron AS 2011, 2012\n\n";
|
||||
|
||||
helpText +=
|
||||
"\nParameter Description\n"
|
||||
"\nParameter Description\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
"-last Open last used project\n"
|
||||
"-project <filename> Open project file <filename>\n"
|
||||
"-case <casename> Open Eclipse case <casename>\n"
|
||||
" (do not include .GRID/.EGRID)\n"
|
||||
"-startdir The default directory for open/save commands\n"
|
||||
"-last Open last used project\n"
|
||||
"\n"
|
||||
"-savesnapshots Save snapshot of all views to 'snapshots' folder in project file folder\n"
|
||||
" Application closes after snapshots are written to file\n"
|
||||
"-project <filename> Open project file <filename>\n"
|
||||
"\n"
|
||||
"-help \n"
|
||||
"-? Displays help text\n"
|
||||
"-case <casename> Open Eclipse case <casename>\n"
|
||||
" (do not include .GRID/.EGRID)\n"
|
||||
"\n"
|
||||
"-startdir The default directory for open/save commands\n"
|
||||
"\n"
|
||||
"-savesnapshots Save snapshot of all views to 'snapshots' folder in project file folder\n"
|
||||
" Application closes after snapshots are written to file\n"
|
||||
"\n"
|
||||
"-regressiontest <folder> Run a regression test on all sub-folders of the given folder: \n"
|
||||
" RegressionTest.rip files in the sub-folders will be opened and \n"
|
||||
" snapshots of all the views is written to the sub-sub-folder RegTestGeneratedImages. \n"
|
||||
" Then difference images is generated in the sub-sub-folder RegTestDiffImages based \n"
|
||||
" on the images in sub-sub-folder RegTestBaseImages.\n"
|
||||
" The results are presented in ResInsightRegressionTestReport.html that is\n"
|
||||
" written in the given folder.\n"
|
||||
"\n"
|
||||
"-updateregressiontestbase <folder> For all sub-folders of the given folder: \n"
|
||||
" Copy the images in the sub-sub-folder RegTestGeneratedImages to the sub-sub-folder\n"
|
||||
" RegTestBaseImages after deleting RegTestBaseImages completely.\n"
|
||||
"\n"
|
||||
"-help, -? Displays help text\n"
|
||||
"-----------------------------------------------------------------";
|
||||
|
||||
fprintf(stdout, "%s\n", helpText.toAscii().data());
|
||||
@ -703,6 +763,20 @@ bool RIApplication::parseArguments()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isRunRegressionTest)
|
||||
{
|
||||
runRegressionTest(regressionTestPath);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isUpdateRegressionTest)
|
||||
{
|
||||
updateRegressionTest(regressionTestPath);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (openLatestProject)
|
||||
{
|
||||
loadLastUsedProject();
|
||||
@ -737,12 +811,13 @@ bool RIApplication::parseArguments()
|
||||
|
||||
if (m_project.notNull() && !m_project->fileName().isEmpty() && isSaveSnapshotsForAllViews)
|
||||
{
|
||||
saveSnapshotForAllViews();
|
||||
saveSnapshotForAllViews("snapshots");
|
||||
|
||||
// Returning false will exit the application
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1031,7 +1106,7 @@ void RIApplication::copySnapshotToClipboard()
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RIApplication::saveSnapshotForAllViews()
|
||||
void RIApplication::saveSnapshotForAllViews(const QString& snapshotFolderName)
|
||||
{
|
||||
RIMainWindow* mainWnd = RIMainWindow::instance();
|
||||
if (!mainWnd) return;
|
||||
@ -1042,8 +1117,7 @@ void RIApplication::saveSnapshotForAllViews()
|
||||
|
||||
QFileInfo fi(m_project->fileName());
|
||||
QDir projectDir(fi.absolutePath());
|
||||
|
||||
QString snapshotFolderName = "snapshots";
|
||||
|
||||
if (!projectDir.exists(snapshotFolderName))
|
||||
{
|
||||
if (!projectDir.mkdir(snapshotFolderName)) return;
|
||||
@ -1073,9 +1147,141 @@ void RIApplication::saveSnapshotForAllViews()
|
||||
|
||||
QString fileName = ri->caseName() + "-" + riv->name();
|
||||
|
||||
QString absoluteFileName = caf::Utils::constructFullFileName(snapshotPath, fileName, ".PNG");
|
||||
QString absoluteFileName = caf::Utils::constructFullFileName(snapshotPath, fileName, ".png");
|
||||
saveSnapshotAs(absoluteFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void removeDirectoryWithContent(QDir dirToDelete )
|
||||
{
|
||||
QStringList files = dirToDelete.entryList();
|
||||
for (int fIdx = 0; fIdx < files.size(); ++fIdx)
|
||||
{
|
||||
dirToDelete.remove(files[fIdx]);
|
||||
}
|
||||
dirToDelete.rmdir(".");
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RIApplication::runRegressionTest(const QString& testRootPath)
|
||||
{
|
||||
QString generatedFolderName = RegTestData::generatedFolderName;
|
||||
QString diffFolderName = RegTestData::diffFolderName;
|
||||
QString baseFolderName = RegTestData::baseFolderName;
|
||||
QString regTestProjectName = RegTestData::testProjectName;
|
||||
QString regTestFolderFilter = RegTestData::testFolderFilter;
|
||||
|
||||
// Find all sub folders
|
||||
|
||||
QDir testDir(testRootPath); // If string is empty it will end up as cwd
|
||||
testDir.setFilter(QDir::Dirs);
|
||||
QStringList dirNameFilter;
|
||||
dirNameFilter.append(regTestFolderFilter);
|
||||
testDir.setNameFilters(dirNameFilter);
|
||||
|
||||
QFileInfoList folderList = testDir.entryInfoList();
|
||||
|
||||
// delete diff and generated images
|
||||
|
||||
|
||||
for (int i = 0; i < folderList.size(); ++i)
|
||||
{
|
||||
QDir testCaseFolder(folderList[i].filePath());
|
||||
|
||||
QDir genDir(testCaseFolder.filePath(generatedFolderName));
|
||||
removeDirectoryWithContent(genDir);
|
||||
|
||||
QDir diffDir(testCaseFolder.filePath(diffFolderName));
|
||||
removeDirectoryWithContent(diffDir);
|
||||
|
||||
QDir baseDir(testCaseFolder.filePath(baseFolderName));
|
||||
}
|
||||
|
||||
// Generate html report
|
||||
|
||||
RiaImageCompareReporter imageCompareReporter;
|
||||
|
||||
for (int dirIdx = 0; dirIdx < folderList.size(); ++dirIdx)
|
||||
{
|
||||
QDir testCaseFolder(folderList[dirIdx].filePath());
|
||||
|
||||
QString testFolderName = testCaseFolder.dirName();
|
||||
QString reportBaseFolderName = testCaseFolder.filePath(baseFolderName);
|
||||
QString reportGeneratedFolderName = testCaseFolder.filePath(generatedFolderName);
|
||||
QString reportDiffFolderName = testCaseFolder.filePath(diffFolderName);
|
||||
|
||||
imageCompareReporter.addImageDirectoryComparisonSet(testFolderName.toStdString(), reportBaseFolderName.toStdString(), reportGeneratedFolderName.toStdString(), reportDiffFolderName.toStdString());
|
||||
}
|
||||
|
||||
imageCompareReporter.generateHTMLReport(testDir.filePath(RegTestData::reportFileName).toStdString());
|
||||
|
||||
// Generate diff images
|
||||
|
||||
for (int dirIdx = 0; dirIdx < folderList.size(); ++dirIdx)
|
||||
{
|
||||
QDir testCaseFolder(folderList[dirIdx].filePath());
|
||||
if (testCaseFolder.exists(regTestProjectName))
|
||||
{
|
||||
loadProject(testCaseFolder.filePath(regTestProjectName));
|
||||
saveSnapshotForAllViews(generatedFolderName);
|
||||
|
||||
QDir baseDir(testCaseFolder.filePath(baseFolderName));
|
||||
QDir genDir(testCaseFolder.filePath(generatedFolderName));
|
||||
QDir diffDir(testCaseFolder.filePath(diffFolderName));
|
||||
if (!diffDir.exists()) testCaseFolder.mkdir(diffFolderName);
|
||||
baseDir.setFilter(QDir::Files);
|
||||
QStringList baseImageFileNames = baseDir.entryList();
|
||||
|
||||
for (int fIdx = 0; fIdx < baseImageFileNames.size(); ++fIdx)
|
||||
{
|
||||
QString fileName = baseImageFileNames[fIdx];
|
||||
RiaImageFileCompare imgComparator(RegTestData::imageCompareExeName);
|
||||
bool ok = imgComparator.runComparison(genDir.filePath(fileName), baseDir.filePath(fileName), diffDir.filePath(fileName));
|
||||
if (!ok)
|
||||
{
|
||||
qDebug() << "Error comparing :" << imgComparator.errorMessage() << "\n" << imgComparator.errorDetails();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RIApplication::updateRegressionTest(const QString& testRootPath)
|
||||
{
|
||||
// Find all sub folders
|
||||
|
||||
QDir testDir(testRootPath); // If string is empty it will end up as cwd
|
||||
testDir.setFilter(QDir::Dirs);
|
||||
QStringList dirNameFilter;
|
||||
dirNameFilter.append(RegTestData::testFolderFilter);
|
||||
testDir.setNameFilters(dirNameFilter);
|
||||
|
||||
QFileInfoList folderList = testDir.entryInfoList();
|
||||
|
||||
for (int i = 0; i < folderList.size(); ++i)
|
||||
{
|
||||
QDir testCaseFolder(folderList[i].filePath());
|
||||
|
||||
QDir baseDir(testCaseFolder.filePath(RegTestData::baseFolderName));
|
||||
removeDirectoryWithContent(baseDir);
|
||||
testCaseFolder.mkdir(RegTestData::baseFolderName);
|
||||
|
||||
QDir genDir(testCaseFolder.filePath(RegTestData::generatedFolderName));
|
||||
|
||||
QStringList imageFileNames = genDir.entryList();
|
||||
|
||||
for (int fIdx = 0; fIdx < imageFileNames.size(); ++fIdx)
|
||||
{
|
||||
QString fileName = imageFileNames[fIdx];
|
||||
QFile::copy(genDir.filePath(fileName), baseDir.filePath(fileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,9 @@ public:
|
||||
void copySnapshotToClipboard();
|
||||
void saveSnapshotPromtpForFilename();
|
||||
void saveSnapshotAs(const QString& fileName);
|
||||
void saveSnapshotForAllViews();
|
||||
void saveSnapshotForAllViews(const QString& snapshotFolderName);
|
||||
void runRegressionTest(const QString& testRootPath);
|
||||
void updateRegressionTest(const QString& testRootPath );
|
||||
|
||||
void processNonGuiEvents();
|
||||
|
||||
@ -126,7 +128,7 @@ private:
|
||||
|
||||
private slots:
|
||||
void slotWorkerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
caf::PdmPointer<RimReservoirView> m_activeReservoirView;
|
||||
|
135
ApplicationCode/Application/RiaImageCompareReporter.cpp
Normal file
135
ApplicationCode/Application/RiaImageCompareReporter.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RiaImageCompareReporter.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <QDir>
|
||||
|
||||
RiaImageCompareReporter::RiaImageCompareReporter(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RiaImageCompareReporter::~RiaImageCompareReporter(void)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaImageCompareReporter::addImageDirectoryComparisonSet(const std::string& title, const std::string& baseImageDir, const std::string& newImagesDir, const std::string& diffImagesDir)
|
||||
{
|
||||
m_directorySets.push_back(DirSet(title, baseImageDir, newImagesDir, diffImagesDir));
|
||||
}
|
||||
|
||||
std::string removeCommonStart(const std::string& mask, const std::string& filename)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < mask.size() && i < filename.size(); ++i)
|
||||
{
|
||||
if (mask[i] != filename[i]) break;
|
||||
}
|
||||
|
||||
return filename.substr(i);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaImageCompareReporter::generateHTMLReport(const std::string& fileName)
|
||||
{
|
||||
if (m_directorySets.size() == 0) return;
|
||||
|
||||
std::ofstream output(fileName);
|
||||
if (!output)
|
||||
{
|
||||
std::cout << "Trouble opening test report file: " << fileName;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string html;
|
||||
|
||||
html += "<html>\n";
|
||||
html += "<head>\n";
|
||||
html += "<title>Regression-Test Report</title>\n";
|
||||
html += "</head>\n";
|
||||
html += "\n";
|
||||
html += "<body>\n";
|
||||
html += "\n";
|
||||
|
||||
for (size_t dsIdx = 0; dsIdx < m_directorySets.size(); ++dsIdx)
|
||||
{
|
||||
std::vector<std::string> baseImageNames = getPngFilesInDirectory(m_directorySets[dsIdx].m_baseImageDir);
|
||||
|
||||
html += "<table>\n";
|
||||
html += " <tr>\n";
|
||||
html += " <td colspan=\"3\" bgcolor=\"darkblue\" height=\"40\"> <b><font color=\"white\" size=\"3\"> " + m_directorySets[dsIdx].m_title + " </font></b> </td>\n";
|
||||
html += " </tr>\n";
|
||||
|
||||
std::string baseImageFolder = removeCommonStart(fileName, m_directorySets[dsIdx].m_baseImageDir );
|
||||
std::string genImageFolder = removeCommonStart(fileName, m_directorySets[dsIdx].m_newImagesDir );
|
||||
std::string diffImageFolder = removeCommonStart(fileName, m_directorySets[dsIdx].m_diffImagesDir);
|
||||
|
||||
for (size_t fIdx = 0; fIdx < baseImageNames.size(); ++fIdx)
|
||||
{
|
||||
html += " <tr>\n";
|
||||
html += " <td colspan=\"3\" bgcolor=\"lightgray\"> " + baseImageNames[fIdx] + "</td>\n";
|
||||
html += " </tr>\n";
|
||||
|
||||
html += " <tr>\n";
|
||||
html += " <td> <img src=\"" + baseImageFolder + "/" + baseImageNames[fIdx] + "\" width=\"100%\" alt=\"" + baseImageFolder + "/" + baseImageNames[fIdx] + "\" > </td>\n";
|
||||
html += " <td> <img src=\"" + genImageFolder + "/" + baseImageNames[fIdx] + "\" width=\"100%\" alt=\"" + genImageFolder + "/" + baseImageNames[fIdx] + "\" > </td>\n";
|
||||
html += " <td> <img src=\"" + diffImageFolder + "/" + baseImageNames[fIdx] + "\" width=\"100%\" alt=\"" + diffImageFolder + "/" + baseImageNames[fIdx] + "\" > </td>\n";
|
||||
html += " </tr>\n";
|
||||
|
||||
// A little air between images
|
||||
html += " <tr> <td height=\"10\"> </td> </tr>\n";
|
||||
}
|
||||
|
||||
html += "</table>\n";
|
||||
|
||||
html += "\n";
|
||||
}
|
||||
|
||||
output << html;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Retuns the names of the *.png files in a directory. The names are without path, but with extention
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
std::vector<std::string> RiaImageCompareReporter::getPngFilesInDirectory(const std::string& searchPath)
|
||||
{
|
||||
QDir searchDir(QString::fromStdString(searchPath));
|
||||
|
||||
searchDir.setFilter(QDir::Files);
|
||||
//QStringList filter;
|
||||
//filter.append("*.png");
|
||||
//searchDir.setNameFilters(filter);
|
||||
|
||||
QStringList imageFiles = searchDir.entryList();
|
||||
|
||||
std::vector<std::string> fileNames;
|
||||
for (int i = 0; i < imageFiles.size(); ++i)
|
||||
{
|
||||
fileNames.push_back(imageFiles[i].toStdString());
|
||||
}
|
||||
|
||||
return fileNames;
|
||||
}
|
54
ApplicationCode/Application/RiaImageCompareReporter.h
Normal file
54
ApplicationCode/Application/RiaImageCompareReporter.h
Normal file
@ -0,0 +1,54 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RiaImageCompareReporter
|
||||
{
|
||||
public:
|
||||
RiaImageCompareReporter();
|
||||
virtual ~RiaImageCompareReporter();
|
||||
|
||||
void addImageDirectoryComparisonSet(const std::string& title, const std::string& baseImageDir, const std::string& newImagesDir, const std::string& diffImagesDir );
|
||||
void generateHTMLReport(const std::string& filenName);
|
||||
|
||||
|
||||
private:
|
||||
static std::vector<std::string> getPngFilesInDirectory(const std::string& searchPath);
|
||||
|
||||
struct DirSet
|
||||
{
|
||||
DirSet(const std::string& title, const std::string& baseImageDir, const std::string& newImagesDir, const std::string& diffImagesDir )
|
||||
: m_title(title),
|
||||
m_baseImageDir(baseImageDir),
|
||||
m_newImagesDir(newImagesDir),
|
||||
m_diffImagesDir(diffImagesDir)
|
||||
{}
|
||||
|
||||
std::string m_title;
|
||||
std::string m_baseImageDir;
|
||||
std::string m_newImagesDir;
|
||||
std::string m_diffImagesDir;
|
||||
};
|
||||
|
||||
std::vector<DirSet> m_directorySets;
|
||||
};
|
||||
|
150
ApplicationCode/Application/RiaImageFileCompare.cpp
Normal file
150
ApplicationCode/Application/RiaImageFileCompare.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RiaImageFileCompare.h"
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaImageFileCompare::RiaImageFileCompare(QString compareExecutable)
|
||||
: m_compareExecutable(compareExecutable)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaImageFileCompare::~RiaImageFileCompare()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiaImageFileCompare::reset()
|
||||
{
|
||||
m_imagesEqual = false;
|
||||
m_lastError = IC_NO_ERROR;
|
||||
m_errorMsg = "";
|
||||
m_errorDetails = "";
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RiaImageFileCompare::runComparison(QString imgFileName, QString refFileName, QString diffFileName)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (m_compareExecutable.isEmpty())
|
||||
{
|
||||
m_lastError = SEVERE_ERROR;
|
||||
m_errorMsg = "Cannot compare images, no compare executable set";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//QString args = QString("-fuzz 2% -lowlight-color white -metric ae \"%1\" \"%2\" \"%3\"").arg(imgFileName).arg(refFileName).arg((diffFileName));
|
||||
QString args = QString("-lowlight-color white -metric ae \"%1\" \"%2\" \"%3\"").arg(imgFileName).arg(refFileName).arg((diffFileName));
|
||||
QString completeCommand = QString("\"%1\" %2").arg(m_compareExecutable).arg(args);
|
||||
|
||||
// Launch process and wait
|
||||
QProcess proc;
|
||||
proc.start(completeCommand);
|
||||
proc.waitForFinished(30000);
|
||||
|
||||
QProcess::ProcessError procError = proc.error();
|
||||
if (procError != QProcess::UnknownError)
|
||||
{
|
||||
m_lastError = SEVERE_ERROR;
|
||||
m_errorMsg = "Error running compare tool process";
|
||||
m_errorDetails = completeCommand;
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray stdErr = proc.readAllStandardError();
|
||||
int procExitCode = proc.exitCode();
|
||||
if (procExitCode == 0)
|
||||
{
|
||||
// Strip out whitespace and look for 0 (as in zero pixel differences)
|
||||
stdErr = stdErr.simplified();
|
||||
if (!stdErr.isEmpty() && stdErr[0] == '0')
|
||||
{
|
||||
m_imagesEqual = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Report non-severe error
|
||||
m_lastError = IC_ERROR;
|
||||
m_errorMsg = "Error running compare tool process";
|
||||
m_errorDetails = stdErr;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
bool RiaImageFileCompare::imagesEqual() const
|
||||
{
|
||||
return m_imagesEqual;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
RiaImageFileCompare::ErrorType RiaImageFileCompare::error() const
|
||||
{
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RiaImageFileCompare::errorMessage() const
|
||||
{
|
||||
return m_errorMsg;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RiaImageFileCompare::errorDetails() const
|
||||
{
|
||||
return m_errorDetails;
|
||||
}
|
60
ApplicationCode/Application/RiaImageFileCompare.h
Normal file
60
ApplicationCode/Application/RiaImageFileCompare.h
Normal file
@ -0,0 +1,60 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2011-2012 Statoil ASA, Ceetron AS
|
||||
//
|
||||
// ResInsight is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE.
|
||||
//
|
||||
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
||||
// for more details.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
//==================================================================================================
|
||||
//
|
||||
// Compare two images (currently using ImageMagick in an external process)
|
||||
//
|
||||
//==================================================================================================
|
||||
class RiaImageFileCompare
|
||||
{
|
||||
public:
|
||||
enum ErrorType
|
||||
{
|
||||
IC_NO_ERROR, // No error occurred
|
||||
IC_ERROR, // An error occurred
|
||||
SEVERE_ERROR // Severe error occurred, it is likely that another call to compare() will also fail
|
||||
};
|
||||
|
||||
public:
|
||||
RiaImageFileCompare(QString compareExecutable);
|
||||
~RiaImageFileCompare();
|
||||
|
||||
bool runComparison(QString imgFileName, QString refFileName, QString diffFileName);
|
||||
bool imagesEqual() const;
|
||||
ErrorType error() const;
|
||||
QString errorMessage() const;
|
||||
QString errorDetails() const;
|
||||
|
||||
private:
|
||||
void reset();
|
||||
|
||||
private:
|
||||
QString m_compareExecutable; // The executable for the ImageMagick compare tool
|
||||
bool m_imagesEqual; // Result of last comparison
|
||||
ErrorType m_lastError; // Error for last execution
|
||||
QString m_errorMsg;
|
||||
QString m_errorDetails;
|
||||
};
|
||||
|
||||
|
||||
|
@ -34,6 +34,8 @@ list( APPEND CPP_SOURCES
|
||||
list( APPEND CPP_SOURCES
|
||||
Application/RIApplication.cpp
|
||||
Application/RIPreferences.cpp
|
||||
Application/RiaImageFileCompare.cpp
|
||||
Application/RiaImageCompareReporter.cpp
|
||||
)
|
||||
|
||||
list( APPEND CPP_SOURCES
|
||||
@ -160,6 +162,9 @@ list( REMOVE_ITEM RAW_SOURCES ModelVisualization/RivCellEdgeEffectGenerator.cpp)
|
||||
list( REMOVE_ITEM RAW_SOURCES ModelVisualization/RivPipeGeometryGenerator.cpp)
|
||||
list( REMOVE_ITEM RAW_SOURCES ModelVisualization/RivWellPipesPartMgr.cpp)
|
||||
list( REMOVE_ITEM RAW_SOURCES ModelVisualization/RivWellHeadPartMgr.cpp)
|
||||
list( REMOVE_ITEM RAW_SOURCES Application/RiaImageFileCompare.cpp)
|
||||
list( REMOVE_ITEM RAW_SOURCES Application/RiaImageCompareReporter.cpp)
|
||||
|
||||
|
||||
|
||||
list( REMOVE_ITEM RAW_SOURCES
|
||||
|
@ -1234,5 +1234,5 @@ void RIMainWindow::slotSnapshotAllViewsToFile()
|
||||
{
|
||||
RIApplication* app = RIApplication::instance();
|
||||
|
||||
app->saveSnapshotForAllViews();
|
||||
app->saveSnapshotForAllViews("snapshots");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user