By using the CONFIG-=app_bundle the trace analyzer wont be build as a app package on mac anymore. It behaves exactly like on linux now.
216 lines
7.6 KiB
C++
216 lines
7.6 KiB
C++
/*
|
|
* Copyright (c) 2015, University of Kaiserslautern
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
|
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Authors:
|
|
* Janik Schlemminger
|
|
* Robert Gernhardt
|
|
* Matthias Jung
|
|
* Felipe S. Prado
|
|
*/
|
|
|
|
#include "pythoncaller.h"
|
|
#include <exception>
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <QFileInfo>
|
|
#include <QDebug>
|
|
#include <QApplication>
|
|
|
|
using namespace std;
|
|
|
|
PythonCaller::PythonCaller() :
|
|
testModuleName("tests"),
|
|
testFunctionName("runTests"),
|
|
metricModuleName("metrics"),
|
|
metricFunctionName("calculateMetrics"),
|
|
getMetricFunctionName("getMetrics"),
|
|
|
|
pathToScripts(QApplication::applicationDirPath().toStdString() + "/../../DRAMSys/analyzer/scripts/"),
|
|
plotsModuleName("plots"),
|
|
plotsFunctionName("generatePlots")
|
|
{
|
|
Py_Initialize();
|
|
PyObject *sysPath = PySys_GetObject((char*)"path");
|
|
PyObject *path = PyUnicode_FromString(this->pathToScripts.c_str());
|
|
PyList_Insert(sysPath, 0, path);
|
|
Py_DECREF(path);
|
|
|
|
qDebug() << "Test:" << testModuleName.c_str() << testFunctionName.c_str();
|
|
qDebug() << "Metric:" << metricModuleName.c_str() << metricFunctionName.c_str();
|
|
qDebug() << "Plot:" << plotsModuleName.c_str() << plotsFunctionName.c_str();
|
|
qDebug() << "Script: " << pathToScripts.c_str();
|
|
|
|
pRunTestsFunction = loadFunctionFromModule(testModuleName, testFunctionName);
|
|
pCalculateMetricsFunction = loadFunctionFromModule(metricModuleName, metricFunctionName);
|
|
pGenPlotsFunction = loadFunctionFromModule(plotsModuleName, plotsFunctionName);
|
|
pGetMetricsFunction = loadFunctionFromModule(metricModuleName, getMetricFunctionName);
|
|
}
|
|
|
|
|
|
//returns new reference to the function (see: http://edcjones.tripod.com/refcount.html for the difference between "new reference" and "borrowed reference")
|
|
PyObject* PythonCaller::loadFunctionFromModule(string moduleName,string functionName)
|
|
{
|
|
PyObject* pModuleName = PyUnicode_FromString(moduleName.c_str());
|
|
PyObject* pModule = PyImport_Import(pModuleName);
|
|
|
|
if(!pModule)
|
|
{
|
|
throw runtime_error(string("Could not load module "+ moduleName));
|
|
}
|
|
|
|
PyObject* pFunction = PyObject_GetAttrString(pModule, functionName.c_str());
|
|
|
|
if(!pFunction || !PyCallable_Check(pFunction))
|
|
{
|
|
throw runtime_error(string("Could not load test function " + functionName + "in module " + moduleName));
|
|
}
|
|
|
|
Py_DECREF(pModuleName);
|
|
Py_DECREF(pModule);
|
|
return pFunction;
|
|
}
|
|
|
|
PythonCaller::~PythonCaller()
|
|
{
|
|
Py_DECREF(pRunTestsFunction);
|
|
Py_DECREF(pCalculateMetricsFunction);
|
|
Py_DECREF(pGenPlotsFunction);
|
|
Py_DECREF(pGetMetricsFunction);
|
|
Py_Finalize();
|
|
}
|
|
|
|
PyObject* PythonCaller::callMetricsFunction(PyObject* function, QString argument, vector<long> list)
|
|
{
|
|
assert(PyCallable_Check(function));
|
|
|
|
PyObject* pArgs = PyTuple_New(2);
|
|
PyObject* pArgumentString = PyUnicode_FromString(argument.toStdString().c_str());
|
|
PyObject* pArgumentList = PyList_New(list.size());
|
|
for(size_t i = 0; i < list.size(); i++)
|
|
{
|
|
PyList_SetItem(pArgumentList, i, PyBool_FromLong(list[i]));
|
|
}
|
|
PyTuple_SetItem(pArgs, 0, pArgumentString);
|
|
PyTuple_SetItem(pArgs, 1, pArgumentList);
|
|
PyObject *pResult = PyObject_CallObject(function, pArgs);
|
|
Py_DECREF(pArgs);
|
|
|
|
if(!pResult)
|
|
{
|
|
PyErr_Print();
|
|
throw runtime_error(string("Error in calling " + testFunctionName + " in module " + testModuleName));
|
|
}
|
|
|
|
return pResult;
|
|
}
|
|
|
|
//returns a new reference to result of function call
|
|
PyObject* PythonCaller::callFunctionWithStringArgument(PyObject* function, QString argument)
|
|
{
|
|
assert(PyCallable_Check(function));
|
|
|
|
PyObject* pArgs = PyTuple_New(1);
|
|
PyObject* pArgument = PyUnicode_FromString(argument.toStdString().c_str());
|
|
PyTuple_SetItem(pArgs, 0, pArgument);
|
|
PyObject *pResult = PyObject_CallObject(function, pArgs);
|
|
Py_DECREF(pArgument);
|
|
|
|
if(!pResult)
|
|
{
|
|
PyErr_Print();
|
|
throw runtime_error(string("Error in calling " + testFunctionName + " in module " + testModuleName));
|
|
}
|
|
|
|
return pResult;
|
|
}
|
|
|
|
TraceTestResults PythonCaller::runTestsOnTrace(QString pathToTrace)
|
|
{
|
|
TraceTestResults traceTestResult(QFileInfo(pathToTrace).baseName());
|
|
PyObject *pResult = callFunctionWithStringArgument(pRunTestsFunction, pathToTrace);
|
|
|
|
for(Py_ssize_t i= 0; i < PyList_Size(pResult); ++i)
|
|
{
|
|
PyObject* currentTestResult = PyList_GetItem(pResult,i);
|
|
QString testName(PyUnicode_AsUTF8(PyTuple_GetItem(currentTestResult,0)));
|
|
bool testPassed = (Py_True == PyTuple_GetItem(currentTestResult,1));
|
|
QString message(PyUnicode_AsUTF8(PyTuple_GetItem(currentTestResult,2)));
|
|
|
|
traceTestResult.addTestResult(TestResult(testName,testPassed,message));
|
|
}
|
|
Py_DECREF(pResult);
|
|
return traceTestResult;
|
|
}
|
|
|
|
TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(QString pathToTrace, vector<long> list)
|
|
{
|
|
TraceCalculatedMetrics result(QFileInfo(pathToTrace).baseName());
|
|
PyObject *pResult = callMetricsFunction(pCalculateMetricsFunction, pathToTrace,list);
|
|
|
|
for(Py_ssize_t i= 0; i < PyList_Size(pResult); ++i)
|
|
{
|
|
PyObject* calculatedMetric = PyList_GetItem(pResult,i);
|
|
QString metricName(PyUnicode_AsUTF8(PyTuple_GetItem(calculatedMetric,0)));
|
|
double value = PyFloat_AsDouble(PyTuple_GetItem(calculatedMetric,1));
|
|
result.addCalculatedMetric(CalculatedMetric(metricName,value));
|
|
}
|
|
|
|
Py_DECREF(pResult);
|
|
return result;
|
|
}
|
|
|
|
vector<string> PythonCaller::getMetrics(QString pathToTrace)
|
|
{
|
|
vector<string> result;
|
|
PyObject *pResult = callFunctionWithStringArgument(pGetMetricsFunction, pathToTrace);
|
|
|
|
for(Py_ssize_t i= 0; i < PyList_Size(pResult); ++i)
|
|
{
|
|
PyObject* metric = PyList_GetItem(pResult,i);
|
|
QString metricName(PyUnicode_AsUTF8(metric));
|
|
result.push_back(metricName.toStdString().c_str());
|
|
}
|
|
|
|
Py_DECREF(pResult);
|
|
return result;
|
|
}
|
|
|
|
QString PythonCaller::generatePlotsOnTrace(QString pathToTrace)
|
|
{
|
|
assert(PyCallable_Check(pGenPlotsFunction));
|
|
|
|
PyObject* pResult = callFunctionWithStringArgument(pGenPlotsFunction, pathToTrace);
|
|
QString outputFiles (PyUnicode_AsUTF8(pResult));
|
|
Py_DECREF(pResult);
|
|
return outputFiles;
|
|
|
|
}
|