2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @file test_logic_expression.cpp
|
|
|
|
*
|
|
|
|
* https://sourceforge.net/p/rusefi/tickets/102/
|
|
|
|
*
|
|
|
|
* @date Oct 3, 2014
|
2020-01-13 18:57:43 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "fsio_impl.h"
|
|
|
|
#include "cli_registry.h"
|
2017-06-04 12:25:37 -07:00
|
|
|
#include "engine_test_helper.h"
|
2019-10-13 06:59:06 -07:00
|
|
|
#include "thermistors.h"
|
2020-07-01 17:45:37 -07:00
|
|
|
#include "allsensors.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
#define TEST_POOL_SIZE 256
|
|
|
|
|
2017-06-04 12:25:37 -07:00
|
|
|
float getEngineValue(le_action_e action DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2015-07-10 06:01:56 -07:00
|
|
|
switch(action) {
|
|
|
|
case LE_METHOD_FAN:
|
2019-09-19 05:05:23 -07:00
|
|
|
return engine->fsioState.mockFan;
|
2015-07-10 06:01:56 -07:00
|
|
|
case LE_METHOD_COOLANT:
|
2020-04-15 13:20:45 -07:00
|
|
|
return Sensor::get(SensorType::Clt).value_or(0);
|
2015-07-10 06:01:56 -07:00
|
|
|
case LE_METHOD_RPM:
|
2019-09-19 05:05:23 -07:00
|
|
|
return engine->fsioState.mockRpm;
|
2017-06-25 22:49:11 -07:00
|
|
|
case LE_METHOD_CRANKING_RPM:
|
2019-09-19 05:05:23 -07:00
|
|
|
return engine->fsioState.mockCrankingRpm;
|
2015-07-10 06:01:56 -07:00
|
|
|
case LE_METHOD_TIME_SINCE_BOOT:
|
2019-09-19 05:05:23 -07:00
|
|
|
return engine->fsioState.mockTimeSinceBoot;
|
2019-01-19 19:09:37 -08:00
|
|
|
case LE_METHOD_VBATT:
|
|
|
|
return 12;
|
2020-07-01 17:45:37 -07:00
|
|
|
case LE_METHOD_AC_TOGGLE:
|
|
|
|
return getAcToggle(PASS_ENGINE_PARAMETER_SIGNATURE);
|
2019-06-01 06:11:01 -07:00
|
|
|
case LE_METHOD_IS_COOLANT_BROKEN:
|
|
|
|
return 0;
|
2020-07-01 17:45:37 -07:00
|
|
|
#include "fsio_getters.def"
|
2015-07-10 06:01:56 -07:00
|
|
|
default:
|
2019-06-01 06:11:01 -07:00
|
|
|
firmwareError(OBD_PCM_Processor_Fault, "FSIO: No mock value for %d", action);
|
2015-07-10 06:01:56 -07:00
|
|
|
return NAN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void testParsing(void) {
|
|
|
|
char buffer[64];
|
|
|
|
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(strEqualCaseInsensitive("hello", "HELlo"));
|
|
|
|
ASSERT_FALSE(strEqualCaseInsensitive("hello", "HElo2"));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
const char *ptr;
|
|
|
|
ptr = getNextToken(" hello ", buffer, sizeof(buffer));
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(strEqual("hello", buffer));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
ptr = getNextToken("hello", buffer, sizeof(buffer));
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(strEqual("hello", buffer));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
ptr = getNextToken(" hello world ", buffer, sizeof(buffer));
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(strEqual("hello", buffer));
|
2015-07-10 06:01:56 -07:00
|
|
|
ptr = getNextToken(ptr, buffer, sizeof(buffer));
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(strEqual("world", buffer));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(isNumeric("123"));
|
|
|
|
ASSERT_FALSE(isNumeric("a123"));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
LEElement thepool[TEST_POOL_SIZE];
|
|
|
|
LEElementPool pool(thepool, TEST_POOL_SIZE);
|
|
|
|
|
|
|
|
LEElement *element;
|
|
|
|
element = pool.parseExpression("1 3 AND not");
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(element != NULL);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-01-14 12:45:35 -08:00
|
|
|
ASSERT_EQ(element->action, LE_NUMERIC_VALUE);
|
|
|
|
ASSERT_EQ(element->fValue, 1.0);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
element = element->next;
|
2019-01-14 12:45:35 -08:00
|
|
|
ASSERT_EQ(element->action, LE_NUMERIC_VALUE);
|
|
|
|
ASSERT_EQ(element->fValue, 3.0);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
element = element->next;
|
2019-01-14 12:45:35 -08:00
|
|
|
ASSERT_EQ(element->action, LE_OPERATOR_AND);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
element = element->next;
|
2019-01-14 12:45:35 -08:00
|
|
|
ASSERT_EQ(element->action, LE_OPERATOR_NOT);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
element = element->next;
|
2019-01-14 12:37:05 -08:00
|
|
|
ASSERT_TRUE(element == NULL);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2019-01-19 19:09:37 -08:00
|
|
|
static void testExpression2(float selfValue, const char *line, float expected, Engine *engine) {
|
2015-07-10 06:01:56 -07:00
|
|
|
LEElement thepool[TEST_POOL_SIZE];
|
|
|
|
LEElementPool pool(thepool, TEST_POOL_SIZE);
|
|
|
|
LEElement * element = pool.parseExpression(line);
|
2020-07-01 17:45:37 -07:00
|
|
|
print("Parsing [%s]\n", line);
|
2019-01-14 15:56:32 -08:00
|
|
|
ASSERT_TRUE(element != NULL) << "Not NULL expected";
|
2015-07-10 06:01:56 -07:00
|
|
|
LECalculator c;
|
2017-06-04 12:25:37 -07:00
|
|
|
|
2019-01-19 19:09:37 -08:00
|
|
|
EXPAND_Engine;
|
|
|
|
|
|
|
|
ASSERT_EQ(expected, c.getValue2(selfValue, element PASS_ENGINE_PARAMETER_SUFFIX)) << line;
|
|
|
|
}
|
2017-06-04 12:25:37 -07:00
|
|
|
|
2020-04-15 13:20:45 -07:00
|
|
|
static void testExpression2(float selfValue, const char *line, float expected, const std::unordered_map<SensorType, float>& sensorVals = {}) {
|
|
|
|
WITH_ENGINE_TEST_HELPER_SENS(FORD_INLINE_6_1995, sensorVals);
|
2019-01-19 19:09:37 -08:00
|
|
|
testExpression2(selfValue, line, expected, engine);
|
2016-03-02 19:02:37 -08:00
|
|
|
}
|
|
|
|
|
2020-04-15 13:20:45 -07:00
|
|
|
static void testExpression(const char *line, float expectedValue, const std::unordered_map<SensorType, float>& sensorVals = {}) {
|
|
|
|
testExpression2(0, line, expectedValue, sensorVals);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
2019-09-12 04:31:13 -07:00
|
|
|
TEST(fsio, testIfFunction) {
|
|
|
|
testExpression("1 22 33 if", 22);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(fsio, testLogicExpressions) {
|
2015-07-10 06:01:56 -07:00
|
|
|
testParsing();
|
2019-01-19 19:09:37 -08:00
|
|
|
{
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-01-19 17:42:29 -08:00
|
|
|
WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995);
|
2017-06-04 12:25:37 -07:00
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
LECalculator c;
|
|
|
|
|
|
|
|
LEElement value1;
|
|
|
|
value1.init(LE_NUMERIC_VALUE, 123.0);
|
|
|
|
c.add(&value1);
|
|
|
|
|
2017-06-04 12:25:37 -07:00
|
|
|
assertEqualsM("123", 123.0, c.getValue(0 PASS_ENGINE_PARAMETER_SUFFIX));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
LEElement value2;
|
|
|
|
value2.init(LE_NUMERIC_VALUE, 321.0);
|
|
|
|
c.add(&value2);
|
|
|
|
|
|
|
|
LEElement value3;
|
|
|
|
value3.init(LE_OPERATOR_AND);
|
|
|
|
c.add(&value3);
|
2017-06-04 12:25:37 -07:00
|
|
|
assertEqualsM("123 and 321", 1.0, c.getValue(0 PASS_ENGINE_PARAMETER_SUFFIX));
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fuel_pump = (time_since_boot < 4 seconds) OR (rpm > 0)
|
|
|
|
* fuel_pump = time_since_boot 4 less rpm 0 > OR
|
|
|
|
*/
|
|
|
|
|
|
|
|
c.reset();
|
|
|
|
|
|
|
|
LEElement thepool[TEST_POOL_SIZE];
|
|
|
|
LEElementPool pool(thepool, TEST_POOL_SIZE);
|
|
|
|
LEElement *e = pool.next();
|
|
|
|
e->init(LE_METHOD_TIME_SINCE_BOOT);
|
|
|
|
|
|
|
|
e = pool.next();
|
|
|
|
e->init(LE_NUMERIC_VALUE, 4);
|
|
|
|
|
|
|
|
e = pool.next();
|
|
|
|
e->init(LE_OPERATOR_LESS);
|
|
|
|
|
|
|
|
e = pool.next();
|
|
|
|
e->init(LE_METHOD_RPM);
|
|
|
|
|
|
|
|
e = pool.next();
|
|
|
|
e->init(LE_NUMERIC_VALUE, 0);
|
|
|
|
|
|
|
|
e = pool.next();
|
|
|
|
e->init(LE_OPERATOR_MORE);
|
|
|
|
|
|
|
|
e = pool.next();
|
|
|
|
e->init(LE_OPERATOR_OR);
|
|
|
|
|
|
|
|
pool.reset();
|
|
|
|
LEElement *element;
|
|
|
|
element = pool.parseExpression("fan no_such_method");
|
2019-01-14 15:56:32 -08:00
|
|
|
ASSERT_TRUE(element == NULL) << "NULL expected";
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-01-19 19:09:37 -08:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fan = (not fan && coolant > 90) OR (fan && coolant > 85)
|
|
|
|
* fan = fan NOT coolant 90 AND more fan coolant 85 more AND OR
|
|
|
|
*/
|
|
|
|
|
2020-04-15 13:20:45 -07:00
|
|
|
std::unordered_map<SensorType, float> sensorVals = {{SensorType::Clt, 100}};
|
|
|
|
testExpression("coolant 1 +", 101, sensorVals);
|
|
|
|
|
|
|
|
testExpression("fan", 0, sensorVals);
|
|
|
|
testExpression("fan not", 1, sensorVals);
|
|
|
|
testExpression("coolant 90 >", 1, sensorVals);
|
|
|
|
testExpression("fan not coolant 90 > and", 1, sensorVals);
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
testExpression("100 200 1 if", 200);
|
|
|
|
testExpression("10 99 max", 99);
|
|
|
|
|
2016-03-02 19:02:37 -08:00
|
|
|
testExpression2(123, "10 self max", 123);
|
|
|
|
|
2020-04-15 13:20:45 -07:00
|
|
|
testExpression("fan NOT coolant 90 > AND fan coolant 85 > AND OR", 1, sensorVals);
|
|
|
|
|
2020-07-01 17:45:37 -07:00
|
|
|
{
|
|
|
|
WITH_ENGINE_TEST_HELPER_SENS(FORD_INLINE_6_1995, sensorVals);
|
|
|
|
LEElement thepool[TEST_POOL_SIZE];
|
|
|
|
LEElementPool pool(thepool, TEST_POOL_SIZE);
|
|
|
|
LEElement * element = pool.parseExpression("fan NOT coolant 90 > AND fan coolant 85 > AND OR");
|
|
|
|
ASSERT_TRUE(element != NULL) << "Not NULL expected";
|
|
|
|
LECalculator c;
|
|
|
|
ASSERT_EQ( 1, c.getValue2(0, element PASS_ENGINE_PARAMETER_SUFFIX)) << "that expression";
|
|
|
|
|
|
|
|
ASSERT_EQ(12, c.currentCalculationLogPosition);
|
|
|
|
ASSERT_EQ(102, c.calcLogAction[0]);
|
|
|
|
ASSERT_EQ(0, c.calcLogValue[0]);
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
|
|
|
|
testExpression("0 1 &", 0);
|
|
|
|
testExpression("0 1 |", 1);
|
|
|
|
|
|
|
|
testExpression("0 1 >", 0);
|
|
|
|
|
2020-07-01 17:45:37 -07:00
|
|
|
{
|
|
|
|
WITH_ENGINE_TEST_HELPER_SENS(FORD_INLINE_6_1995, sensorVals);
|
|
|
|
engineConfiguration->fanOnTemperature = 0;
|
|
|
|
engineConfiguration->fanOffTemperature = 0;
|
|
|
|
|
|
|
|
testExpression2(0, "cfg_fanOffTemperature", 0, engine);
|
|
|
|
testExpression2(0, FAN_CONTROL_LOGIC, 1, engine);
|
|
|
|
testExpression2(0, "coolant cfg_fanOffTemperature >", 1, engine);
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2020-07-01 17:45:37 -07:00
|
|
|
{
|
|
|
|
WITH_ENGINE_TEST_HELPER_SENS(FORD_INLINE_6_1995, sensorVals);
|
|
|
|
engine->fsioState.mockRpm = 900;
|
|
|
|
engine->fsioState.mockCrankingRpm = 200;
|
|
|
|
testExpression2(0, "rpm", 900, engine);
|
|
|
|
testExpression2(0, "cranking_rpm", 200, engine);
|
|
|
|
testExpression2(0, STARTER_RELAY_LOGIC, 0, engine);
|
|
|
|
testExpression2(0, "rpm cranking_rpm > ", 1, engine);
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|