1. parser binary data get info about structure from elf and test_case.json. 2. Rewrite runCase. All works
This commit is contained in:
@@ -2,20 +2,30 @@
|
|||||||
"groups": {
|
"groups": {
|
||||||
"smoke": [
|
"smoke": [
|
||||||
"test_UART_cmdSetDataInterface.json",
|
"test_UART_cmdSetDataInterface.json",
|
||||||
|
"test_readSnapshot_HK.json",
|
||||||
"test_set_micron_MT29F16G08AJADAWP.json",
|
"test_set_micron_MT29F16G08AJADAWP.json",
|
||||||
"test_get_badBlockMap_fromNAND.json"
|
"test_readSnapshot_HK.json",
|
||||||
|
"test_get_badBlockMap_fromNAND.json",
|
||||||
|
"test_readSnapshot_HK.json"
|
||||||
],
|
],
|
||||||
|
|
||||||
"full": [
|
"full": [
|
||||||
"test_UART_cmdSetDataInterface.json",
|
"test_UART_cmdSetDataInterface.json",
|
||||||
|
"test_readSnapshot_HK.json",
|
||||||
"test_set_micron_MT29F16G08AJADAWP.json",
|
"test_set_micron_MT29F16G08AJADAWP.json",
|
||||||
|
"test_readSnapshot_HK.json",
|
||||||
"test_get_badBlockMap_fromNAND.json",
|
"test_get_badBlockMap_fromNAND.json",
|
||||||
|
"test_readSnapshot_HK.json",
|
||||||
"test_start_March_FTE_by_blocks.json",
|
"test_start_March_FTE_by_blocks.json",
|
||||||
|
"test_readSnapshot_HK.json",
|
||||||
"test_randomDataTest_100_110.json",
|
"test_randomDataTest_100_110.json",
|
||||||
|
"test_readSnapshot_HK.json",
|
||||||
"test_endurance_50_60_marchFTE_5.json",
|
"test_endurance_50_60_marchFTE_5.json",
|
||||||
"test_abort.json",
|
"test_abort.json",
|
||||||
|
"test_readSnapshot_HK.json",
|
||||||
"test_start_March_FTE_all_targ0_repeat2.json",
|
"test_start_March_FTE_all_targ0_repeat2.json",
|
||||||
"test_abort.json"
|
"test_abort.json",
|
||||||
|
"test_readSnapshot_HK.json"
|
||||||
],
|
],
|
||||||
|
|
||||||
"abort": [
|
"abort": [
|
||||||
|
|||||||
@@ -30,27 +30,6 @@ private:
|
|||||||
QString filePath;
|
QString filePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//class ErrOpenFile: public exception
|
|
||||||
//{
|
|
||||||
//public:
|
|
||||||
// ErrOpenFile(QString fname, QString errMsg)
|
|
||||||
// {
|
|
||||||
// this->fname = fname;
|
|
||||||
// this->intro = "ошибка чтения файла";
|
|
||||||
// this->errMsg = errMsg;
|
|
||||||
// }
|
|
||||||
// QString getFname() { return fname; }
|
|
||||||
// QString getIntro() { return intro; }
|
|
||||||
// QString getErrMsg() { return errMsg; }
|
|
||||||
// virtual ~ErrOpenFile() throw() {}
|
|
||||||
|
|
||||||
//private:
|
|
||||||
// QString fname;
|
|
||||||
// QString intro;
|
|
||||||
// QString errMsg;
|
|
||||||
//};
|
|
||||||
|
|
||||||
class ErrInJsonSet: public exception
|
class ErrInJsonSet: public exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -59,7 +38,7 @@ public:
|
|||||||
this->fname = fname;
|
this->fname = fname;
|
||||||
this->jsonObjectsList = jsonObjectsList;
|
this->jsonObjectsList = jsonObjectsList;
|
||||||
this->param = param;
|
this->param = param;
|
||||||
this->intro = "ошибка чтения файла настроек";
|
this->intro = "error reading json file";
|
||||||
this->errMsg = errMsg;
|
this->errMsg = errMsg;
|
||||||
this->errFromJsonFlag = false;
|
this->errFromJsonFlag = false;
|
||||||
}
|
}
|
||||||
@@ -67,7 +46,7 @@ public:
|
|||||||
{
|
{
|
||||||
this->fname = fname;
|
this->fname = fname;
|
||||||
this->errFromJsonFlag = true;
|
this->errFromJsonFlag = true;
|
||||||
this->intro = "ошибка чтения файла настроек";
|
this->intro = "error reading json file";
|
||||||
this->errFromJson = errFromJson;
|
this->errFromJson = errFromJson;
|
||||||
}
|
}
|
||||||
QString getFname() { return fname; }
|
QString getFname() { return fname; }
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ void JsonProcessor::openJsonFile(QString jsonPath, QJsonObject &jsonObj)
|
|||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ throw(ErrOpenFile(jsonPath, "файл не найден")); }
|
{ throw(ErrOpenFile(jsonPath, "file not found")); }
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonError);
|
QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonError);
|
||||||
@@ -32,7 +32,7 @@ void JsonProcessor::openJsonFile(QString jsonPath, QJsonObject &jsonObj)
|
|||||||
if (doc.isObject())
|
if (doc.isObject())
|
||||||
{ jsonObj = doc.object(); }
|
{ jsonObj = doc.object(); }
|
||||||
else
|
else
|
||||||
{ throw(ErrInJsonSet(jsonPath, "неверный формат json: " + jsonPath)); }
|
{ throw(ErrInJsonSet(jsonPath, "incorrect json format: " + jsonPath)); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ void JsonProcessor::saveJsonDataInFile(QString jsonPath, QJsonObject jsonObj)
|
|||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ throw(ErrOpenFile(jsonPath, "файл не найден")); }
|
{ throw(ErrOpenFile(jsonPath, "file not found")); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* common functions */
|
/* common functions */
|
||||||
@@ -61,7 +61,11 @@ void JsonProcessor::jsonConvertStruct(QString jsonObjName, QJsonObject obj,
|
|||||||
QJsonArray *param = new QJsonArray;
|
QJsonArray *param = new QJsonArray;
|
||||||
*param = obj[jsonParamName].toArray();
|
*param = obj[jsonParamName].toArray();
|
||||||
if (param->size() != arrSize)
|
if (param->size() != arrSize)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, jsonParamName, "параметр отсутствует или кол-во элементов в параметре должно быть равно " + QString::number(arrSize))); }
|
{
|
||||||
|
throw(ErrInJsonSet(jsonPath, jsonObjName, jsonParamName,
|
||||||
|
"parameter is missing or elements count in parameter must be equal " +
|
||||||
|
QString::number(arrSize)));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < arrSize; i++)
|
for (int i = 0; i < arrSize; i++)
|
||||||
@@ -95,7 +99,7 @@ void JsonProcessor::jsonConvertStruct(QString jsonObjName, QJsonObject obj,
|
|||||||
QJsonArray param = obj[jsonParamName].toArray();
|
QJsonArray param = obj[jsonParamName].toArray();
|
||||||
if (param.size() != arrSize)
|
if (param.size() != arrSize)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, jsonParamName,
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, jsonParamName,
|
||||||
"параметр отсутствует или кол-во элементов в параметре должно быть равно " + QString::number(arrSize))); }
|
"parameter is missing or elements count in parameter must be equal " + QString::number(arrSize))); }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < arrSize; i++)
|
for (int i = 0; i < arrSize; i++)
|
||||||
@@ -109,7 +113,7 @@ void JsonProcessor::jsonConvertStruct(QString jsonObjName, QJsonObject obj,
|
|||||||
QJsonArray param = obj[jsonParamName].toArray();
|
QJsonArray param = obj[jsonParamName].toArray();
|
||||||
if (param.size() != arrSize)
|
if (param.size() != arrSize)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, jsonParamName,
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, jsonParamName,
|
||||||
"параметр отсутствует или кол-во элементов в параметре должно быть равно " + QString::number(arrSize))); }
|
"parameter is missing or elements count in parameter must be equal " + QString::number(arrSize))); }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < arrSize; i++)
|
for (int i = 0; i < arrSize; i++)
|
||||||
@@ -121,7 +125,7 @@ bool JsonProcessor::jsonGetBoolValue(QJsonObject obj, QString param, QString jso
|
|||||||
{
|
{
|
||||||
QJsonValue val = obj[param];
|
QJsonValue val = obj[param];
|
||||||
if (val == QJsonValue::Null)
|
if (val == QJsonValue::Null)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonGeneral, param, "отсутствует параметр")); }
|
{ throw(ErrInJsonSet(jsonPath, jsonGeneral, param, "parameter is missing")); }
|
||||||
return val.toBool(false);
|
return val.toBool(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +133,7 @@ void JsonProcessor::jsonGetStrValue(QJsonObject obj, QString paramName, QString
|
|||||||
{
|
{
|
||||||
QString val = obj[paramName].toString();
|
QString val = obj[paramName].toString();
|
||||||
if (val == NULL)
|
if (val == NULL)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, paramName, "parameter missing")); }
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, paramName, "parameter is missing")); }
|
||||||
else
|
else
|
||||||
{ paramValue = val; }
|
{ paramValue = val; }
|
||||||
}
|
}
|
||||||
@@ -140,34 +144,34 @@ void JsonProcessor::jsonSetComPortSettings(QString jsonObjName, QJsonObject obj,
|
|||||||
com.addrRS485 = obj["RS485_address"].toInt();
|
com.addrRS485 = obj["RS485_address"].toInt();
|
||||||
if (com.addrRS485 < 1 ||
|
if (com.addrRS485 < 1 ||
|
||||||
com.addrRS485 > 254)
|
com.addrRS485 > 254)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "RS485_address", "отсутствует параметр")); }
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "RS485_address", "paremeter is missing")); }
|
||||||
|
|
||||||
com.name = obj["COM_port"].toString();
|
com.name = obj["COM_port"].toString();
|
||||||
if (com.name == NULL) { throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_port", "отсутствует параметр")); }
|
if (com.name == NULL) { throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_port", "paremeter is missing")); }
|
||||||
|
|
||||||
com.baudRate = (quint32)obj["COM_baudRate"].toInt();
|
com.baudRate = (quint32)obj["COM_baudRate"].toInt();
|
||||||
if (com.baudRate == 0) { throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_baudRate", "отсутствует параметр")); }
|
if (com.baudRate == 0) { throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_baudRate", "paremeter is missing")); }
|
||||||
|
|
||||||
com.dataBits = (QSerialPort::DataBits)obj["COM_bits"].toInt();
|
com.dataBits = (QSerialPort::DataBits)obj["COM_bits"].toInt();
|
||||||
if (com.dataBits < QSerialPort::Data5 ||
|
if (com.dataBits < QSerialPort::Data5 ||
|
||||||
com.dataBits > QSerialPort::Data8)
|
com.dataBits > QSerialPort::Data8)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_bits", "отсутствует параметр")); }
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_bits", "paremeter is missing")); }
|
||||||
|
|
||||||
com.parity = (QSerialPort::Parity)obj["COM_parity"].toInt();
|
com.parity = (QSerialPort::Parity)obj["COM_parity"].toInt();
|
||||||
if (com.parity < QSerialPort::UnknownParity ||
|
if (com.parity < QSerialPort::UnknownParity ||
|
||||||
com.parity == 1 ||
|
com.parity == 1 ||
|
||||||
com.parity > QSerialPort::MarkParity)
|
com.parity > QSerialPort::MarkParity)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_parity", "отсутствует параметр")); }
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_parity", "paremeter is missing")); }
|
||||||
|
|
||||||
com.stopBits = (QSerialPort::StopBits)obj["COM_stopBits"].toInt();
|
com.stopBits = (QSerialPort::StopBits)obj["COM_stopBits"].toInt();
|
||||||
if (com.stopBits < QSerialPort::OneStop ||
|
if (com.stopBits < QSerialPort::OneStop ||
|
||||||
com.stopBits > QSerialPort::OneAndHalfStop)
|
com.stopBits > QSerialPort::OneAndHalfStop)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_stopBits", "отсутствует параметр")); }
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_stopBits", "paremeter is missing")); }
|
||||||
|
|
||||||
com.flowControl = (QSerialPort::FlowControl)obj["COM_flowCotrol"].toInt();
|
com.flowControl = (QSerialPort::FlowControl)obj["COM_flowCotrol"].toInt();
|
||||||
if (com.flowControl < QSerialPort::NoFlowControl ||
|
if (com.flowControl < QSerialPort::NoFlowControl ||
|
||||||
com.flowControl > QSerialPort::SoftwareControl)
|
com.flowControl > QSerialPort::SoftwareControl)
|
||||||
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_flowControl", "отсутствует параметр")); }
|
{ throw(ErrInJsonSet(jsonPath, jsonObjName, "COM_flowControl", "paremeter is missing")); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonProcessor::jsonSaveComPortSettings(QJsonObject &obj, comSettings_t &com)
|
void JsonProcessor::jsonSaveComPortSettings(QJsonObject &obj, comSettings_t &com)
|
||||||
|
|||||||
@@ -16,6 +16,43 @@ void Logger::write(const QString& file, const QString& text)
|
|||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Logger::saveTestLog(const QString& filename, const QJsonObject& cfg,
|
||||||
|
bool passed, QString& error, QString mismatches)
|
||||||
|
{
|
||||||
|
QString log;
|
||||||
|
|
||||||
|
log += "\n<<<TEST_START>>>\n";
|
||||||
|
|
||||||
|
log += "TEST: ";
|
||||||
|
log += cfg["meta"].toObject()["name"].toString();
|
||||||
|
log += "\n";
|
||||||
|
|
||||||
|
log += "TIME: ";
|
||||||
|
log += QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss");
|
||||||
|
log += "\n";
|
||||||
|
|
||||||
|
log += passed ? "STATUS: PASS\n" : "STATUS: FAIL\n";
|
||||||
|
|
||||||
|
if (!error.isEmpty())
|
||||||
|
{
|
||||||
|
log += "\n--- ERROR ---\n";
|
||||||
|
log += error;
|
||||||
|
log += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mismatches.isEmpty())
|
||||||
|
{
|
||||||
|
log += "\n--- MISMATCHES ---\n";
|
||||||
|
log += mismatches;
|
||||||
|
log += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
log += "<<<TEST_END>>>\n";
|
||||||
|
|
||||||
|
write(filename, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Logger::saveTestLog(
|
void Logger::saveTestLog(
|
||||||
const QString& filename,
|
const QString& filename,
|
||||||
const ProtocolHandler& handler,
|
const ProtocolHandler& handler,
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ public:
|
|||||||
bool passed,
|
bool passed,
|
||||||
const QString& error = "");
|
const QString& error = "");
|
||||||
|
|
||||||
|
|
||||||
|
static void saveTestLog(const QString& filename, const QJsonObject& cfg,
|
||||||
|
bool passed, QString &error, QString mismatches);
|
||||||
|
|
||||||
static void appendSummary(
|
static void appendSummary(
|
||||||
const QString& filename,
|
const QString& filename,
|
||||||
int total,
|
int total,
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ std::vector<TestCaseParam> getJsonTests()
|
|||||||
for (const QString &path : list)
|
for (const QString &path : list)
|
||||||
{
|
{
|
||||||
QFile f(path);
|
QFile f(path);
|
||||||
|
|
||||||
QString testName = "unknown";
|
QString testName = "unknown";
|
||||||
|
|
||||||
if (f.open(QIODevice::ReadOnly))
|
if (f.open(QIODevice::ReadOnly))
|
||||||
@@ -75,108 +74,3 @@ INSTANTIATE_TEST_SUITE_P(
|
|||||||
return info.param.name.toStdString();
|
return info.param.name.toStdString();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//TEST_F(UARTFixture, SmokeTests)
|
|
||||||
//{
|
|
||||||
// TestStats stats;
|
|
||||||
// QString msgItog;
|
|
||||||
// QString msg;
|
|
||||||
// QStringList tests;
|
|
||||||
|
|
||||||
// bool fail = extract_struct_from_elf("Snapshot_HK_t");
|
|
||||||
// if (fail == true) { return; }
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// tests = TestLoader::loadCases(g_options.group,
|
|
||||||
// g_options.caseFilter,
|
|
||||||
// g_options.repeat);
|
|
||||||
// }
|
|
||||||
// catch (ErrOpenFile &errOpen)
|
|
||||||
// {
|
|
||||||
// qDebug(logCritical()) << QString("%1, path: %2")
|
|
||||||
// .arg(errOpen.getMessage(),
|
|
||||||
// errOpen.getFilePath());
|
|
||||||
|
|
||||||
// Logger::writeToConsol(QString("\nERROR: %1, path: %2\n").arg(
|
|
||||||
// errOpen.getMessage(),errOpen.getFilePath()));
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QString curTime = QDateTime::currentDateTime().toString("dd_MM_yyyy_hh_mm_ss");
|
|
||||||
// QString curTime1 = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss");
|
|
||||||
|
|
||||||
// QString logFile = QString("%1%2.log").arg(path.test_log_path, curTime);
|
|
||||||
// QString htmlFile = path.stand_report_html_path;
|
|
||||||
|
|
||||||
// QFile::remove(logFile);
|
|
||||||
|
|
||||||
// for (const QString &caseFile : qAsConst(tests))
|
|
||||||
// {
|
|
||||||
// QFile caseFileJson(caseFile);
|
|
||||||
// QString error;
|
|
||||||
|
|
||||||
// if (!caseFileJson.open(QIODevice::ReadOnly))
|
|
||||||
|
|
||||||
// {
|
|
||||||
// msg = QString("%1, path: %2").arg("json test case not found", caseFile);
|
|
||||||
// msgItog.append(msg);
|
|
||||||
|
|
||||||
// qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
// Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QJsonObject cfg =
|
|
||||||
// QJsonDocument::fromJson(caseFileJson.readAll()).object();
|
|
||||||
// QString binaryFile = cfg["binary"].toString();
|
|
||||||
// QFile cmdFile(binaryFile);
|
|
||||||
|
|
||||||
// if (!cmdFile.open(QIODevice::ReadOnly))
|
|
||||||
// {
|
|
||||||
// msg = QString("%1, path: %2").arg("command binary not found", binaryFile);
|
|
||||||
// msgItog.append(msg);
|
|
||||||
|
|
||||||
// qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
// Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QByteArray tx_cmd = cmdFile.readAll();
|
|
||||||
// QString err;
|
|
||||||
// if (!uart.send(tx_cmd, err))
|
|
||||||
// {
|
|
||||||
// msg = QString("%1: %2").arg("UART data did not send", err);
|
|
||||||
// msgItog.append(msg);
|
|
||||||
|
|
||||||
// qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
// Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
// }
|
|
||||||
// QByteArray rx_data = uart.receive(cfg["timeout_msec"].toInt());
|
|
||||||
|
|
||||||
// ProtocolHandler handler(cfg["expectations"].toObject());
|
|
||||||
// handler.feed(rx_data);
|
|
||||||
// QString msg1;
|
|
||||||
// bool passed = handler.isDone(msg1);
|
|
||||||
|
|
||||||
// if (!passed)
|
|
||||||
// {
|
|
||||||
// msgItog.append(msg1);
|
|
||||||
// error = QString("Protocol validation failed: \n %1").arg(msgItog);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Logger::saveTestLog(logFile, handler, cfg, passed, error);
|
|
||||||
// stats.total++;
|
|
||||||
// if (passed) stats.passed++;
|
|
||||||
// else stats.failed++;
|
|
||||||
// EXPECT_TRUE(passed);
|
|
||||||
|
|
||||||
// if (g_options.delayMs > 0)
|
|
||||||
// {
|
|
||||||
// QThread::msleep(g_options.delayMs);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Logger::appendSummary(logFile, stats.total, stats.passed, stats.failed);
|
|
||||||
// HtmlReport::generate(logFile, htmlFile, curTime1);
|
|
||||||
//}
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include "uart_fixture.h"
|
#include "uart_fixture.h"
|
||||||
|
#include "../core/cli_parser.h"
|
||||||
|
#include "../core/html_report.h"
|
||||||
|
|
||||||
UART UARTFixture::uart;
|
UART UARTFixture::uart;
|
||||||
comSettings_t UARTFixture::comPortSettings;
|
comSettings_t UARTFixture::comPortSettings;
|
||||||
@@ -6,44 +8,9 @@ Stats_t UARTFixture::stats;
|
|||||||
path_t UARTFixture::path;
|
path_t UARTFixture::path;
|
||||||
UART_cmdReadMemory_t UARTFixture::iData;
|
UART_cmdReadMemory_t UARTFixture::iData;
|
||||||
char UARTFixture::cmdDataBuf[UART_DATA_MAX_BYTES];
|
char UARTFixture::cmdDataBuf[UART_DATA_MAX_BYTES];
|
||||||
|
QVector<QString> UARTFixture::struct_names;
|
||||||
QString UARTFixture::logFile;
|
QString UARTFixture::logFile;
|
||||||
|
extern TestOptions g_options;
|
||||||
int UARTFixture::extract_struct_from_elf(QString structTypeName)
|
|
||||||
{
|
|
||||||
QProcess process;
|
|
||||||
QString program = path.local_python;
|
|
||||||
|
|
||||||
QStringList arguments;
|
|
||||||
arguments << path.elf_parser
|
|
||||||
<< "-f" << path.MK_elf_file
|
|
||||||
<< "-t" << structTypeName
|
|
||||||
<< "-o" << path.iar_json_out;
|
|
||||||
|
|
||||||
process.start(program, arguments);
|
|
||||||
|
|
||||||
if (!process.waitForFinished(3000)) {
|
|
||||||
QString msg = QString("timeout processing scipt %1").arg(path.map_parser);
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1").arg(msg));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int exitCode = process.exitCode();
|
|
||||||
|
|
||||||
if (exitCode != 0) {
|
|
||||||
QString msg = QString("scipt %1 return error code %2: %3")
|
|
||||||
.arg(path.map_parser,
|
|
||||||
QString(exitCode),
|
|
||||||
QString::fromUtf8(process.readAllStandardError()));
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1").arg(msg));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int UARTFixture::convert_map_file()
|
int UARTFixture::convert_map_file()
|
||||||
{
|
{
|
||||||
@@ -58,11 +25,9 @@ int UARTFixture::convert_map_file()
|
|||||||
|
|
||||||
process.start(program, arguments);
|
process.start(program, arguments);
|
||||||
|
|
||||||
if (!process.waitForFinished(3000)) {
|
if (!process.waitForFinished(3000))
|
||||||
QString msg = QString("timeout processing scipt %1").arg(path.map_parser);
|
{
|
||||||
|
writeToLog(QString("timeout processing scipt %1").arg(path.map_parser), false);
|
||||||
qDebug(logCritical()) << msg;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1").arg(msg));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,12 +35,10 @@ int UARTFixture::convert_map_file()
|
|||||||
|
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
QString msg = QString("scipt %1 return error code %2: %3")
|
QString msg = QString("scipt %1 return error code %2: %3")
|
||||||
.arg(path.map_parser,
|
.arg(path.map_parser, QString(exitCode),
|
||||||
QString(exitCode),
|
|
||||||
QString::fromUtf8(process.readAllStandardError()));
|
QString::fromUtf8(process.readAllStandardError()));
|
||||||
|
|
||||||
qDebug(logCritical()) << msg;
|
writeToLog(msg, false);
|
||||||
Logger::writeToConsol(QString("\nERROR: %1").arg(msg));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,12 +70,8 @@ int UARTFixture::readConfig()
|
|||||||
}
|
}
|
||||||
catch (ErrOpenFile &errOpen)
|
catch (ErrOpenFile &errOpen)
|
||||||
{
|
{
|
||||||
qDebug(logCritical()) << QString("%1, path: %2")
|
QString msg = QString("%1, path: %2").arg(errOpen.getMessage(), errOpen.getFilePath());
|
||||||
.arg(errOpen.getMessage(),
|
writeToLog(msg, false);
|
||||||
errOpen.getFilePath());
|
|
||||||
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1, path: %2\n").arg(
|
|
||||||
errOpen.getMessage(),errOpen.getFilePath()));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
catch (ErrInJsonSet &jsonSet)
|
catch (ErrInJsonSet &jsonSet)
|
||||||
@@ -120,26 +79,17 @@ int UARTFixture::readConfig()
|
|||||||
if (jsonSet.checkErrFromJson())
|
if (jsonSet.checkErrFromJson())
|
||||||
{
|
{
|
||||||
QString msg = QString("%1. %2 : %3. file: %4")
|
QString msg = QString("%1. %2 : %3. file: %4")
|
||||||
.arg(jsonSet.getIntro(),
|
.arg(jsonSet.getIntro(), jsonSet.getErrMsg(),
|
||||||
jsonSet.getErrMsg(),
|
jsonSet.getErrFromJson(), jsonSet.getFname());
|
||||||
jsonSet.getErrFromJson(),
|
writeToLog(msg, false);
|
||||||
jsonSet.getFname());
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1").arg(msg));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QString msg = QString("%1. %2: \nJSON parameter: %3\nJSON object: %4.\nfile: %5")
|
QString msg = QString("%1. %2: \nJSON parameter: %3\nJSON object: %4.\nfile: %5")
|
||||||
.arg(jsonSet.getIntro(),
|
.arg(jsonSet.getIntro(), jsonSet.getErrMsg(), jsonSet.getParam(),
|
||||||
jsonSet.getErrMsg(),
|
jsonSet.getJsonObj(), jsonSet.getFname());
|
||||||
jsonSet.getParam(),
|
writeToLog(msg, false);
|
||||||
jsonSet.getJsonObj(),
|
|
||||||
jsonSet.getFname());
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1").arg(msg));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,12 +116,8 @@ void UARTFixture::SetUpTestSuite()
|
|||||||
}
|
}
|
||||||
catch (ErrOpenFile &errOpen)
|
catch (ErrOpenFile &errOpen)
|
||||||
{
|
{
|
||||||
qDebug(logCritical()) << QString("%1, path: %2")
|
QString msg = QString("%1, path: %2").arg(errOpen.getMessage(), errOpen.getFilePath());
|
||||||
.arg(errOpen.getMessage(),
|
writeToLog(msg, false);
|
||||||
errOpen.getFilePath());
|
|
||||||
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1, path: %2\n").arg(
|
|
||||||
errOpen.getMessage(),errOpen.getFilePath()));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,12 +132,6 @@ void UARTFixture::TearDownTestSuite()
|
|||||||
HtmlReport::generate(logFile, htmlFile, curTime1);
|
HtmlReport::generate(logFile, htmlFile, curTime1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "../core/cli_parser.h"
|
|
||||||
#include "../core/html_report.h"
|
|
||||||
|
|
||||||
extern TestOptions g_options;
|
|
||||||
|
|
||||||
TEST_P(UARTFixture, JsonCase)
|
TEST_P(UARTFixture, JsonCase)
|
||||||
{
|
{
|
||||||
TestCaseParam param = GetParam();
|
TestCaseParam param = GetParam();
|
||||||
@@ -199,190 +139,434 @@ TEST_P(UARTFixture, JsonCase)
|
|||||||
runCase(caseFile);
|
runCase(caseFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UARTFixture::writeToLog(QString errMsg, bool passed)
|
|
||||||
{
|
|
||||||
if (!passed)
|
|
||||||
{
|
|
||||||
stats.failed++;
|
|
||||||
qDebug(logCritical()) << errMsg << Qt::endl;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1\n").arg(errMsg));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stats.passed++;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_TRUE(passed);
|
bool UARTFixture::loadTestCase(const QString& caseFile,
|
||||||
stats.total++;
|
QJsonObject& cfg, QJsonObject &meta)
|
||||||
}
|
|
||||||
|
|
||||||
void UARTFixture::runCase(
|
|
||||||
const QString& caseFile)
|
|
||||||
{
|
{
|
||||||
QString msgItog;
|
|
||||||
QString msg;
|
|
||||||
QString err;
|
|
||||||
QString error;
|
|
||||||
bool passed = false;
|
|
||||||
QString protocolMsg;
|
|
||||||
QString test_case_path = "";
|
|
||||||
|
|
||||||
QFile caseFileJson(caseFile);
|
QFile caseFileJson(caseFile);
|
||||||
|
|
||||||
if (!caseFileJson.open(QIODevice::ReadOnly))
|
if (!caseFileJson.open(QIODevice::ReadOnly))
|
||||||
{ writeToLog(QString("%1, path: %2").arg("json test case not found", caseFile), false); }
|
|
||||||
|
|
||||||
QJsonObject cfg =
|
|
||||||
QJsonDocument::fromJson(caseFileJson.readAll()).object();
|
|
||||||
|
|
||||||
QJsonObject meta = cfg["meta"].toObject();
|
|
||||||
|
|
||||||
if (meta.isEmpty())
|
|
||||||
{
|
{
|
||||||
msg = QString("%1, path: %2").arg("incorrect json file: ", caseFile);
|
writeToLog(QString("%1, path: %2").arg("json test case not found", caseFile), false);
|
||||||
msgItog.append(msg);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
qDebug(logCritical()) << msg << Qt::endl;
|
cfg = QJsonDocument::fromJson(caseFileJson.readAll()).object();
|
||||||
Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
meta = cfg["meta"].toObject();
|
||||||
|
|
||||||
|
if (cfg.isEmpty() || meta.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("%1, path: %2").arg("incorrect json file", caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (meta["input_data_type"].toString() == "binary")
|
void UARTFixture::updateStats(bool passed)
|
||||||
{
|
{
|
||||||
QJsonObject param = meta["parameters"].toObject();
|
stats.total++;
|
||||||
|
|
||||||
bool ok = false;
|
if (passed) { stats.passed++; }
|
||||||
iData.version = param["version"].toInt();
|
else { stats.failed++; }
|
||||||
|
|
||||||
if (param["addr_user_set"].toBool() == true)
|
EXPECT_TRUE(passed);
|
||||||
{ iData.addr_begin = param["addr"].toString().toUInt(&ok, 16); }
|
|
||||||
|
|
||||||
if (param["size_user_set"].toBool() == true)
|
|
||||||
{ iData.size_bytes = param["size"].toInt(); }
|
|
||||||
|
|
||||||
|
|
||||||
if (iData.size_bytes >= UART_DATA_MAX_BYTES - 1)
|
|
||||||
{
|
|
||||||
msg = QString("%1: %2")
|
|
||||||
.arg("UART data did not send: ",
|
|
||||||
QString("required structure size %1 too big for UART transmission (MAX: %2). See test_case file: %3")
|
|
||||||
.arg(QString(iData.size_bytes), QString(UART_DATA_MAX_BYTES),
|
|
||||||
test_case_path));
|
|
||||||
msgItog.append(msg);
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
formCmdDataInBuffer();
|
|
||||||
QByteArray data;
|
|
||||||
|
|
||||||
if (param["cmd_from_binary_file"].toBool() == true)
|
|
||||||
{
|
|
||||||
QString binaryFile = cfg["binary"].toString();
|
|
||||||
QFile cmdFile(binaryFile);
|
|
||||||
if (!cmdFile.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
msg = QString("%1, path: %2").arg("command binary not found", binaryFile);
|
|
||||||
msgItog.append(msg);
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data = cmdFile.readAll();
|
bool UARTFixture::sendCommand(const QByteArray &data)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
QByteArray data1(QByteArray::fromRawData(cmdDataBuf, UART_DATA_MAX_BYTES));
|
QString err;
|
||||||
data = data1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!uart.send(data, err))
|
if (!uart.send(data, err))
|
||||||
{
|
{
|
||||||
msg = QString("%1: %2").arg("UART data did not send", err);
|
writeToLog(QString("UART send failed: %1").arg(err), false);
|
||||||
msgItog.append(msg);
|
return false;
|
||||||
|
|
||||||
qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray rx_data = uart.receive(cfg["timeout_msec"].toInt());
|
QByteArray UARTFixture::receiveResponse(const QJsonObject &cfg)
|
||||||
|
|
||||||
Snapshot_HK_t snapshot;
|
|
||||||
memcpy(&snapshot, rx_data.constData(), sizeof(snapshot));
|
|
||||||
|
|
||||||
EXPECT_EQ(snapshot.version, 1);
|
|
||||||
EXPECT_EQ(snapshot.size, 222);
|
|
||||||
EXPECT_EQ(snapshot.system_error, 0);
|
|
||||||
EXPECT_EQ(snapshot.guard.all, 0);
|
|
||||||
|
|
||||||
EXPECT_EQ(snapshot.uart.errorLastOperation, 0);
|
|
||||||
|
|
||||||
QVector<int> excludedIdx;
|
|
||||||
excludedIdx.push_back(0);
|
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++)
|
|
||||||
{
|
{
|
||||||
bool excludeFlag = false;
|
int timeout = cfg["timeout_msec"].toInt();
|
||||||
|
return uart.receive(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < excludedIdx.size(); j++)
|
|
||||||
|
bool UARTFixture::loadBinaryFile(const QString& fileName, QByteArray& data)
|
||||||
{
|
{
|
||||||
if (i == excludedIdx[j])
|
QFile binaryFile(fileName);
|
||||||
{ excludeFlag = true; break; }
|
|
||||||
|
|
||||||
}
|
if (!binaryFile.open(QIODevice::ReadOnly))
|
||||||
|
|
||||||
if (excludeFlag == false)
|
|
||||||
{ EXPECT_EQ(snapshot.uart.error[i], 0); }
|
|
||||||
}
|
|
||||||
|
|
||||||
passed = true;
|
|
||||||
}
|
|
||||||
else if (meta["input_data_type"].toString() == "text")
|
|
||||||
{
|
{
|
||||||
QString binaryFile = cfg["binary"].toString();
|
writeToLog(QString("command binary not found: %1").arg(fileName), false);
|
||||||
QFile cmdFile(binaryFile);
|
return false;
|
||||||
if (!cmdFile.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
msg = QString("%1, path: %2").arg("command binary not found", binaryFile);
|
|
||||||
msgItog.append(msg);
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray tx_cmd = cmdFile.readAll();
|
data = binaryFile.readAll();
|
||||||
if (!uart.send(tx_cmd, err))
|
return true;
|
||||||
{
|
|
||||||
msg = QString("%1: %2").arg("UART data did not send", err);
|
|
||||||
msgItog.append(msg);
|
|
||||||
|
|
||||||
qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray rx_data = uart.receive(cfg["timeout_msec"].toInt());
|
bool UARTFixture::validateTextResponse(const QByteArray& rx,
|
||||||
|
const QJsonObject& cfg, QString caseFile)
|
||||||
|
{
|
||||||
|
QString protocolMsg;
|
||||||
|
QString error;
|
||||||
|
bool passed = false;
|
||||||
|
|
||||||
ProtocolHandler handler(cfg["expectations"].toObject());
|
QJsonObject exp = cfg["expectations"].toObject();
|
||||||
handler.feed(rx_data);
|
|
||||||
|
if (exp.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'expectations' field not found in %1").arg(caseFile), false);
|
||||||
|
passed = false; return passed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtocolHandler handler(exp);
|
||||||
|
|
||||||
|
handler.feed(rx);
|
||||||
|
|
||||||
|
passed = handler.isDone(protocolMsg);
|
||||||
|
|
||||||
if (!passed)
|
if (!passed)
|
||||||
{ error = QString("Protocol validation failed:\n%1").arg(protocolMsg); }
|
{ error = QString("Protocol validation failed:\n%1").arg(protocolMsg); }
|
||||||
|
|
||||||
passed = handler.isDone(protocolMsg);
|
|
||||||
Logger::saveTestLog(logFile, handler, cfg, passed, error);
|
Logger::saveTestLog(logFile, handler, cfg, passed, error);
|
||||||
|
|
||||||
|
return passed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UARTFixture::runTextCase(const QJsonObject& cfg, QString caseFile)
|
||||||
|
{
|
||||||
|
QByteArray tx;
|
||||||
|
QString binaryFname = cfg["binary"].toString();
|
||||||
|
|
||||||
|
if (binaryFname.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'binary' field not found in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loadBinaryFile(binaryFname, tx)) { return false; }
|
||||||
|
if (!sendCommand(tx)) { return false; }
|
||||||
|
|
||||||
|
QByteArray rx = receiveResponse(cfg);
|
||||||
|
|
||||||
|
return validateTextResponse(rx, cfg, caseFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stats.total++;
|
bool UARTFixture::prepareBinaryCommand(const QJsonObject& cfg, QByteArray& data)
|
||||||
if (passed) stats.passed++;
|
{
|
||||||
else stats.failed++;
|
// bool ok = false;
|
||||||
EXPECT_TRUE(passed);
|
QJsonObject meta, param;
|
||||||
|
meta = cfg["meta"].toObject();
|
||||||
|
param = meta["parameters"].toObject();
|
||||||
|
|
||||||
|
if (meta.isEmpty() || param.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'meta' or 'parameters' field not found"), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
iData.version = param["version"].toInt();
|
||||||
|
|
||||||
|
if (param["addr_user_set"].toBool())
|
||||||
|
{ iData.size_bytes = param["size"].toInt(); }
|
||||||
|
|
||||||
|
if (iData.size_bytes >= UART_DATA_MAX_BYTES)
|
||||||
|
{
|
||||||
|
writeToLog(QString("structure too big"), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param["cmd_from_binary_file"].toBool())
|
||||||
|
{ return loadBinaryFile(cfg["binary"].toString(), data); }
|
||||||
|
|
||||||
|
formCmdDataInBuffer();
|
||||||
|
|
||||||
|
data = QByteArray::fromRawData(cmdDataBuf, UART_DATA_MAX_BYTES);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UARTFixture::validateStructField(const QByteArray& rxData,
|
||||||
|
const QJsonObject& fieldCfg,
|
||||||
|
const QJsonObject& structJson,
|
||||||
|
QString& errMsg,
|
||||||
|
QString& errMsgMismatch,
|
||||||
|
QString caseFile)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
QJsonObject fieldInfo;
|
||||||
|
QString fieldName, fieldType, op;
|
||||||
|
bool isArray = false;
|
||||||
|
QJsonArray fields;
|
||||||
|
|
||||||
|
fieldName = fieldCfg["field"].toString();
|
||||||
|
if (fieldName.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'field' field not found or incorrect in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fieldType = fieldCfg["type"].toString();
|
||||||
|
if (fieldType.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'type' field not found or incorrect in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
op = fieldCfg["op"].toString("==");
|
||||||
|
if (op.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'op' field not found or incorrect in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isArray = fieldCfg["array"].toBool(false);
|
||||||
|
fields = structJson["fields"].toArray();
|
||||||
|
|
||||||
|
for (const QJsonValue& v : qAsConst(fields))
|
||||||
|
{
|
||||||
|
QJsonObject obj = v.toObject();
|
||||||
|
|
||||||
|
if (obj["name"].toString() == fieldName)
|
||||||
|
{
|
||||||
|
fieldInfo = obj;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
errMsg = QString("field '%1' not found in struct json").arg(fieldName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// offset and size from ELF JSON
|
||||||
|
int offset = fieldInfo["offset"].toInt();
|
||||||
|
int size = fieldInfo["size"].toInt();
|
||||||
|
|
||||||
|
if ((offset + size) > rxData.size())
|
||||||
|
{
|
||||||
|
errMsg = QString("field '%1' out of bounds (offset=%2 size=%3 rx_size=%4)")
|
||||||
|
.arg(fieldName).arg(offset).arg(size).arg(rxData.size());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ARRAY CHECK
|
||||||
|
if (isArray)
|
||||||
|
{
|
||||||
|
// exclude list
|
||||||
|
QVector<int> excludeIdx;
|
||||||
|
QJsonArray excludeArr = fieldCfg["exclude"].toArray();
|
||||||
|
|
||||||
|
for (const QJsonValue& v : qAsConst(excludeArr))
|
||||||
|
{ excludeIdx.push_back(v.toInt()); }
|
||||||
|
|
||||||
|
// element array size
|
||||||
|
int elemSize = 1;
|
||||||
|
|
||||||
|
if (fieldType == "uint8" || fieldType == "int8") { elemSize = 1; }
|
||||||
|
else if (fieldType == "uint16" || fieldType == "int16") { elemSize = 2; }
|
||||||
|
else if (fieldType == "uint32" || fieldType == "int32" || fieldType == "float") { elemSize = 4; }
|
||||||
|
else if (fieldType == "uint64" || fieldType == "int64" || fieldType == "double") { elemSize = 8; }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errMsg = QString("unsupported array type '%1'").arg(fieldType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arrayCount = size / elemSize;
|
||||||
|
|
||||||
|
// expected value
|
||||||
|
double expectValue = fieldCfg["expect"].toDouble();
|
||||||
|
|
||||||
|
// iterate array
|
||||||
|
for (int i = 0; i < arrayCount; i++)
|
||||||
|
{
|
||||||
|
bool skip = false;
|
||||||
|
for (int ex : excludeIdx)
|
||||||
|
{ if (ex == i) { skip = true; break; } }
|
||||||
|
|
||||||
|
if (skip) { continue; }
|
||||||
|
|
||||||
|
// read value by type
|
||||||
|
double actual = 0;
|
||||||
|
const char* ptr = rxData.constData() + offset + i * elemSize;
|
||||||
|
|
||||||
|
if (fieldType == "uint8") actual = *(reinterpret_cast<const uint8_t*>(ptr));
|
||||||
|
else if (fieldType == "int8") actual = *(reinterpret_cast<const int8_t*>(ptr));
|
||||||
|
else if (fieldType == "uint16") actual = *(reinterpret_cast<const uint16_t*>(ptr));
|
||||||
|
else if (fieldType == "int16") actual = *(reinterpret_cast<const int16_t*>(ptr));
|
||||||
|
else if (fieldType == "uint32") actual = *(reinterpret_cast<const uint32_t*>(ptr));
|
||||||
|
else if (fieldType == "int32") actual = *(reinterpret_cast<const int32_t*>(ptr));
|
||||||
|
else if (fieldType == "uint64") actual = static_cast<double>(*(reinterpret_cast<const uint64_t*>(ptr)));
|
||||||
|
else if (fieldType == "int64") actual = static_cast<double>(*(reinterpret_cast<const int64_t*>(ptr)));
|
||||||
|
else if (fieldType == "float") actual = *(reinterpret_cast<const float*>(ptr));
|
||||||
|
else if (fieldType == "double") actual = *(reinterpret_cast<const double*>(ptr));
|
||||||
|
|
||||||
|
// compare
|
||||||
|
bool ok = false;
|
||||||
|
if (op == "==") ok = (actual == expectValue);
|
||||||
|
else if (op == "!=") ok = (actual != expectValue);
|
||||||
|
else if (op == ">") ok = (actual > expectValue);
|
||||||
|
else if (op == "<") ok = (actual < expectValue);
|
||||||
|
else if (op == ">=") ok = (actual >= expectValue);
|
||||||
|
else if (op == "<=") ok = (actual <= expectValue);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
errMsgMismatch = QString("array check failed: %1[%2] actual=%3 expect %4 %5")
|
||||||
|
.arg(fieldName).arg(i).arg(actual).arg(op).arg(expectValue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SINGLE VARIABLE CHECK
|
||||||
|
const char* ptr = rxData.constData() + offset;
|
||||||
|
|
||||||
|
double actual = 0;
|
||||||
|
|
||||||
|
if (fieldType == "uint8") { actual = *(reinterpret_cast<const uint8_t*>(ptr)); }
|
||||||
|
else if (fieldType == "int8") { actual = *(reinterpret_cast<const int8_t*>(ptr)); }
|
||||||
|
else if (fieldType == "uint16") { actual = *(reinterpret_cast<const uint16_t*>(ptr)); }
|
||||||
|
else if (fieldType == "int16") { actual = *(reinterpret_cast<const int16_t*>(ptr)); }
|
||||||
|
else if (fieldType == "uint32") { actual = *(reinterpret_cast<const uint32_t*>(ptr)); }
|
||||||
|
else if (fieldType == "int32") { actual = *(reinterpret_cast<const int32_t*>(ptr)); }
|
||||||
|
else if (fieldType == "uint64") { actual = static_cast<double>(*(reinterpret_cast<const uint64_t*>(ptr))); }
|
||||||
|
else if (fieldType == "int64") { actual = static_cast<double>(*(reinterpret_cast<const int64_t*>(ptr))); }
|
||||||
|
else if (fieldType == "float") { actual = *(reinterpret_cast<const float*>(ptr)); }
|
||||||
|
else if (fieldType == "double") { actual = *(reinterpret_cast<const double*>(ptr)); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errMsg = QString("unsupported field type '%1'").arg(fieldType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double expectValue = fieldCfg["expect"].toDouble();
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
if (op == "==") { ok = (actual == expectValue); }
|
||||||
|
else if (op == "!=") { ok = (actual != expectValue); }
|
||||||
|
else if (op == ">") { ok = (actual > expectValue); }
|
||||||
|
else if (op == "<") { ok = (actual < expectValue); }
|
||||||
|
else if (op == ">=") { ok = (actual >= expectValue); }
|
||||||
|
else if (op == "<=") { ok = (actual <= expectValue); }
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
errMsgMismatch = QString("field check failed: %1 actual=%2 expect %3 %4")
|
||||||
|
.arg(fieldName).arg(actual).arg(op).arg(expectValue);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UARTFixture::validateBinaryResponse(const QByteArray& rx, const QJsonObject& cfg,
|
||||||
|
const QJsonObject& structJson, QString caseFile)
|
||||||
|
{
|
||||||
|
QJsonArray checks = cfg["struct_check"].toArray();
|
||||||
|
QString err, errMsgMismatch;
|
||||||
|
bool passed;
|
||||||
|
|
||||||
|
if (checks.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'struct_check' field not found in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QJsonValue& v: qAsConst(checks))
|
||||||
|
{
|
||||||
|
passed = validateStructField(rx, v.toObject(), structJson,
|
||||||
|
err, errMsgMismatch, caseFile);
|
||||||
|
if (!passed) { writeToLog(QString("%1\n%2").arg(err, errMsgMismatch) , false); break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::saveTestLog(logFile, cfg, passed, err, errMsgMismatch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UARTFixture::runBinaryCase(const QJsonObject& cfg, const QJsonObject& meta,
|
||||||
|
QString caseFile)
|
||||||
|
{
|
||||||
|
QByteArray tx;
|
||||||
|
QString struct_name, struct_type, structJsonFileName;
|
||||||
|
QJsonObject param, structJson;
|
||||||
|
|
||||||
|
// find struct_name from test_case
|
||||||
|
param = meta["parameters"].toObject();
|
||||||
|
if (param.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'parameters' field not found in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct_name = param["struct_name"].toString();
|
||||||
|
if (struct_name.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'struct_name' field incorrect or not found in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct_type = param["struct_type"].toString();
|
||||||
|
if (struct_type.isEmpty())
|
||||||
|
{
|
||||||
|
writeToLog(QString("'struct_type' field incorrect or not found in %1").arg(caseFile), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
structJsonFileName = QString("%1%2.json").arg(path.iar_json_out, struct_type);
|
||||||
|
|
||||||
|
// extract from elf about struct info
|
||||||
|
if (!struct_names.contains(struct_name))
|
||||||
|
{
|
||||||
|
struct_names.push_back(struct_name);
|
||||||
|
bool fail = extract_struct_from_elf(struct_type);
|
||||||
|
if (fail == true) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// open json-file with specified struct info and get json object
|
||||||
|
QFile fileJson(structJsonFileName);
|
||||||
|
if (!fileJson.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
writeToLog(QString("%1 %2, path: %3")
|
||||||
|
.arg("json file not found fo struct", struct_name, structJsonFileName), false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
structJson = QJsonDocument::fromJson(fileJson.readAll()).object();
|
||||||
|
|
||||||
|
if (!prepareBinaryCommand(cfg, tx)) { return false; }
|
||||||
|
if (!sendCommand(tx)) { return false; }
|
||||||
|
|
||||||
|
QByteArray rx = receiveResponse(cfg);
|
||||||
|
return validateBinaryResponse(rx, cfg, structJson, caseFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UARTFixture::runCase(const QString& caseFile)
|
||||||
|
{
|
||||||
|
QJsonObject cfg, meta;
|
||||||
|
bool passed = false;
|
||||||
|
|
||||||
|
if (!loadTestCase(caseFile, cfg, meta)) { return; }
|
||||||
|
|
||||||
|
QString rx_data_type = meta["input_data_type"].toString();
|
||||||
|
|
||||||
|
if (rx_data_type == "text")
|
||||||
|
{ passed = runTextCase(cfg, caseFile); }
|
||||||
|
else if (rx_data_type == "binary")
|
||||||
|
{ passed = runBinaryCase(cfg, meta, caseFile); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeToLog(QString("unknown input_data_type (%1) in file: %2")
|
||||||
|
.arg(rx_data_type, caseFile), false);
|
||||||
|
passed = false;
|
||||||
|
updateStats(passed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStats(passed);
|
||||||
|
|
||||||
if (g_options.delayMs > 0)
|
if (g_options.delayMs > 0)
|
||||||
{ QThread::msleep(g_options.delayMs); }
|
{ QThread::msleep(g_options.delayMs); }
|
||||||
@@ -415,62 +599,48 @@ void UARTFixture::formCmdDataInBuffer()
|
|||||||
|
|
||||||
void UARTFixture::TearDown()
|
void UARTFixture::TearDown()
|
||||||
{
|
{
|
||||||
// QThread::msleep(200);
|
}
|
||||||
// QString msgItog;
|
|
||||||
// QString msg;
|
int UARTFixture::extract_struct_from_elf(QString structTypeName)
|
||||||
// QString err;
|
{
|
||||||
// QString test_case_path = "";
|
QProcess process;
|
||||||
|
QString program = path.local_python;
|
||||||
// iData.version = 0x1;
|
|
||||||
// iData.addr_begin = 0x08125600;
|
QStringList arguments;
|
||||||
// iData.size_bytes = 222;
|
arguments << path.elf_parser
|
||||||
|
<< "-f" << path.MK_elf_file
|
||||||
// if (iData.size_bytes >= UART_DATA_MAX_BYTES - 1)
|
<< "-t" << structTypeName
|
||||||
// {
|
<< "-o" << path.iar_json_out;
|
||||||
// msg = QString("%1: %2")
|
|
||||||
// .arg("UART data did not send: ",
|
process.start(program, arguments);
|
||||||
// QString("required structure size %1 too big for UART transmission (MAX: %2). See test_case file: %3")
|
|
||||||
// .arg(QString(iData.size_bytes), QString(UART_DATA_MAX_BYTES),
|
if (!process.waitForFinished(3000))
|
||||||
// test_case_path));
|
{
|
||||||
// msgItog.append(msg);
|
writeToLog(QString("timeout script processig: %1").arg(path.elf_parser), false);
|
||||||
|
return 1;
|
||||||
// qDebug(logCritical()) << msg << Qt::endl;
|
}
|
||||||
// Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
// return;
|
int exitCode = process.exitCode();
|
||||||
// }
|
|
||||||
// else
|
if (exitCode != 0) {
|
||||||
// {
|
QString msg = QString("scipt %1 return error code %2: %3")
|
||||||
// formCmdDataInBuffer();
|
.arg(path.elf_parser, QString(exitCode),
|
||||||
|
QString::fromUtf8(process.readAllStandardError()));
|
||||||
// QByteArray data(QByteArray::fromRawData(cmdDataBuf, UART_DATA_MAX_BYTES));
|
|
||||||
|
writeToLog(msg, false);
|
||||||
|
return 1;
|
||||||
// QString pathData = "data.bin";
|
}
|
||||||
// QFile file(pathData);
|
|
||||||
|
return 0;
|
||||||
// if (!file.open(QIODevice::WriteOnly))
|
}
|
||||||
// { printf("\t\n ERROR open file!"); }
|
|
||||||
// else
|
void UARTFixture::writeToLog(const QString& errMsg, bool passed)
|
||||||
// {
|
{
|
||||||
// QDataStream out(&file);
|
if (!passed)
|
||||||
// out.writeRawData(data, UART_DATA_MAX_BYTES);
|
{
|
||||||
// file.close();
|
qDebug(logCritical()) << errMsg << Qt::endl;
|
||||||
// }
|
Logger::writeToConsol(QString("\nERROR: %1\n").arg(errMsg));
|
||||||
|
}
|
||||||
// uart.send(data, err);
|
else {
|
||||||
|
}
|
||||||
// if (!uart.send(data, err))
|
|
||||||
// {
|
|
||||||
// msg = QString("%1: %2").arg("UART data did not send", err);
|
|
||||||
// msgItog.append(msg);
|
|
||||||
|
|
||||||
// qDebug(logCritical()) << msg << Qt::endl;
|
|
||||||
// Logger::writeToConsol(QString("\nERROR: %1\n").arg(msg));
|
|
||||||
// }
|
|
||||||
//// QByteArray rx_data = uart.receive(cfg["timeout_msec"].toInt());
|
|
||||||
// QByteArray rx_data = uart.receive(1000);
|
|
||||||
// printf(rx_data);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// QThread::msleep(200);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ protected:
|
|||||||
static QString logFile;
|
static QString logFile;
|
||||||
static UART_cmdReadMemory_t iData;
|
static UART_cmdReadMemory_t iData;
|
||||||
static char cmdDataBuf[UART_DATA_MAX_BYTES];
|
static char cmdDataBuf[UART_DATA_MAX_BYTES];
|
||||||
|
static QVector<QString> struct_names;
|
||||||
|
|
||||||
static void serializeCmdDataBuf(void *dataStruct, int countBytes);
|
static void serializeCmdDataBuf(void *dataStruct, int countBytes);
|
||||||
static void formCmdDataInBuffer();
|
static void formCmdDataInBuffer();
|
||||||
@@ -88,12 +89,37 @@ protected:
|
|||||||
|
|
||||||
static int readConfig();
|
static int readConfig();
|
||||||
static int convert_map_file();
|
static int convert_map_file();
|
||||||
static int extract_struct_from_elf(QString structTypeName);
|
|
||||||
|
|
||||||
void TearDown() override;
|
void TearDown() override;
|
||||||
void runCase(const QString& caseFile);
|
void runCase(const QString& caseFile);
|
||||||
|
void updateStats(bool passed);
|
||||||
|
bool sendCommand(const QByteArray &data);
|
||||||
|
QByteArray receiveResponse(const QJsonObject &cfg);
|
||||||
|
|
||||||
static void writeToLog(QString errMsg, bool passed);
|
bool loadBinaryFile(const QString& fileName, QByteArray& data);
|
||||||
|
|
||||||
|
bool validateTextResponse(const QByteArray& rx,
|
||||||
|
const QJsonObject& cfg, QString caseFile);
|
||||||
|
bool runTextCase(const QJsonObject& cfg, QString caseFile);
|
||||||
|
|
||||||
|
bool prepareBinaryCommand(const QJsonObject& cfg, QByteArray& data);
|
||||||
|
|
||||||
|
bool validateStructField(const QByteArray& rxData,
|
||||||
|
const QJsonObject& fieldCfg,
|
||||||
|
const QJsonObject& structJson,
|
||||||
|
QString& errMsg,
|
||||||
|
QString &errMsgMismatch, QString caseFile);
|
||||||
|
bool validateBinaryResponse(const QByteArray& rx, const QJsonObject& cfg,
|
||||||
|
const QJsonObject &structJson, QString caseFile);
|
||||||
|
bool runBinaryCase(const QJsonObject& cfg, const QJsonObject &meta,
|
||||||
|
QString caseFile);
|
||||||
|
|
||||||
|
bool loadTestCase(const QString& caseFile,
|
||||||
|
QJsonObject& cfg,
|
||||||
|
QJsonObject& meta);
|
||||||
|
|
||||||
|
static void writeToLog(const QString &errMsg, bool passed);
|
||||||
|
static int extract_struct_from_elf(QString structTypeName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user