Пример #1
0
TEST(util, crc) {
	ASSERT_EQ(4, efiRound(4.4, 1));
	ASSERT_FLOAT_EQ(1.2, efiRound(1.2345, 0.1));

	print("*************************************** testCrc\r\n");

	const char * A = "A";

	ASSERT_EQ( 168,  calc_crc((const crc_t *) A, 1)) << "crc8";
	uint32_t c = crc32(A, 1);
	printf("crc32(A)=%x\r\n", c);
	assertEqualsM("crc32 1", 0xd3d99e8b, c);

	const char * line = "AbcDEFGF";
	c = crc32(line, 8);
	printf("crc32(line)=%x\r\n", c);
	assertEqualsM("crc32 line", 0x4775a7b1, c);

	c = crc32(line, 1);
	c = crc32inc(line + 1, c, 8 - 1);
	assertEqualsM("crc32 line inc", 0x4775a7b1, c);
}
Пример #2
0
void testSpeedDensity(void) {
	printf("*************************************************** testSpeedDensity\r\n");
	EngineTestHelper eth(FORD_INLINE_6_1995);

	eth.ec->triggerConfig.customTotalToothCount = 8;
	eth.initTriggerShapeAndRpmCalculator();

	eth.fireTriggerEvents();
	assertEqualsM("RPM", 1500, eth.rpmState.rpm());

	// 427 cubic inches, that's a LOT of engine
	eth.ec->displacement = 6.99728;
	eth.ec->cylindersCount = 8;

	eth.ec->injectorFlow = gramm_second_to_cc_minute(5.303);

	// 0.01414 sec or 14.14 ms
	assertEquals(0.01414, sdMath(eth.ec, 0.92, 98, 12.5, 293.16));
}
Пример #3
0
TEST(misc, testMisc) {
	print("******************************************* testMisc\r\n");
	strcpy(buff, "  ab  ");
	// we need a mutable array here
	ASSERT_TRUE(strEqual("ab", efiTrim(buff)));


	{
		float v = atoff("1.0");
		assertEqualsM("atoff", 1.0, v);
	}
	{
		float v = atoff("nan");
		ASSERT_TRUE(cisnan(v)) << "NaN atoff";
	}
	{
		float v = atoff("N");
		ASSERT_TRUE(cisnan(v)) << "NaN atoff";
	}

//	ASSERT_EQ(true, strEqual("spa3", getPinName(SPARKOUT_3_OUTPUT)));
//	ASSERT_EQ(SPARKOUT_12_OUTPUT, getPinByName("spa12"));
}
Пример #4
0
void testAngleResolver(void) {
	printf("*************************************************** testAngleResolver\r\n");

	EngineTestHelper eth(FORD_ASPIRE_1996);
	Engine *engine = &eth.engine;

	engine_configuration_s *engineConfiguration = eth.engine.engineConfiguration;

	engineConfiguration->globalTriggerAngleOffset = 175;
	assertTrue(engine->engineConfiguration2!=NULL);
	trigger_shape_s * ts = &engine->triggerShape;

	confgiureFordAspireTriggerShape(ts);

	ts->calculateTriggerSynchPoint(engineConfiguration, engine);

	assertEqualsM("index 2", 228.0450, ts->eventAngles[3]); // this angle is relation to synch point
	assertEqualsM("time 2", 0.3233, ts->wave.getSwitchTime(2));
	assertEqualsM("index 5", 413.7470, ts->eventAngles[6]);
	assertEqualsM("time 5", 0.5692, ts->wave.getSwitchTime(5));

	assertEquals(4, ts->getTriggerShapeSynchPointIndex());

	assertEqualsM("shape size", 10, ts->getSize());

	OutputSignalList list;

	ae.resetEventList();
	printf("*************************************************** testAngleResolver 0\r\n");
	findTriggerPosition(&ae.getNextActuatorEvent()->position, 53 - 175 PASS_ENGINE_PARAMETER);
	assertEqualsM("size", 1, ae.size);
	assertEquals(1, ae.events[0].position.eventIndex);
	assertEquals(3.1588, ae.events[0].position.angleOffset);

	printf("*************************************************** testAngleResolver 2\r\n");
	ae.resetEventList();
	findTriggerPosition(&ae.getNextActuatorEvent()->position, 51 + 180 - 175 PASS_ENGINE_PARAMETER);
	assertEquals(2, ae.events[0].position.eventIndex);
	assertEquals(112.3495, ae.events[0].position.angleOffset);
}
Пример #5
0
static void testNoiselessDecoderProcedure(EngineTestHelper &eth, int errorToleranceCnt DECLARE_ENGINE_PARAMETER_SUFFIX) {
	printf("*** (bc->useNoiselessTriggerDecoder = %s)\r\n",
			CONFIGB(useNoiselessTriggerDecoder) ? "true" : "false");

	resetTrigger(eth);
	
	// first, no noise
	fireNoisyCycle60_2(&eth, 2, 1000, -1, 0, 0, 0);

	// should be no errors anyway
	ASSERT_EQ( 0,  engine->triggerCentral.triggerState.totalTriggerErrorCounter) << "testNoiselessDecoderProcedure totalTriggerErrorCounter";
	// check if we're imitating the 60-2 signal correctly
	ASSERT_EQ( 0,  eth.engine.triggerCentral.triggerState.getCurrentIndex()) << "index #1";
	// check rpm (60secs / (1000us * 60teeth)) = 1000rpm
	ASSERT_EQ( 1000,  GET_RPM()) << "testNoiselessDecoder RPM";

	// add noise1 - 1 spike in the middle of the 2nd rising pulse
	fireNoisyCycle60_2(&eth, 2, 1000, 2, 10, 500, 1);

	assertEqualsM("testNoiselessDecoder noise#1", errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter);

	resetTrigger(eth);

	// add noise2 - 1 spike in the middle of the 2nd falling pulse
	fireNoisyCycle60_2(&eth, 2, 1000, 3, 10, 500, 1);

	//assertEqualsM("noise#2", errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter);

	resetTrigger(eth);

	// add noise3 - in the middle of the sync.gap,
	// so that we cannot tell for sure if it's a start of another 'extra' tooth or just a noise inside the gap,
	// that's why we used expectedEventCount[] in our filtering algo to make a prediction about gap
	fireNoisyCycle60_2(&eth, 2, 1000, 114, 10, 1500, 1);

	// so everything runs smoothly!
	assertEqualsM("noise#3", errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter);

	resetTrigger(eth);

	// add noise4 - too close to the start of the real next signal, so the noise spike is accepted as a signal
	// but when the real signal comes shortly afterwards, it we be treated as a noise spike,
	fireNoisyCycle60_2(&eth, 2, 1000, 4, 10, 980, 1);

	// and we won't get out of sync!
	assertEqualsM("noise#4", errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter);

	resetTrigger(eth);

	// add noise5 - one very long 333us noise spike
	fireNoisyCycle60_2(&eth, 2, 1000, 4, 333, 10, 1);
	// still ok
	assertEqualsM("noise#5", errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter);

	resetTrigger(eth);

	// add noise6 - 10 short spikes across the entire signal pulse
	const int failProofNumSpikes = 10;
	fireNoisyCycle60_2(&eth, 2, 1000, 4, 5, 10, failProofNumSpikes);

	// we barely survived this time
	assertEqualsM("testNoiselessDecoder noise#6", errorToleranceCnt, engine->triggerCentral.triggerState.totalTriggerErrorCounter);

	resetTrigger(eth);

	// add noise7 - 34 short spikes across the entire signal pulse
	fireNoisyCycle60_2(&eth, 2, 1000, 2, 10, 10, failProofNumSpikes + 1);

	// alas, this is a hard case even for noiseless decoder, and it fails...
	// but still we're close to 33% signal-noise ratio threshold - not bad!
	// so here's an error anyway!
	ASSERT_EQ( 1,  engine->triggerCentral.triggerState.totalTriggerErrorCounter) << "testNoiselessDecoder noise#7_fail_test";

}
Пример #6
0
A_Test void whenComparingZeroAndZero_thenReturnsZero(void)
{
    int n1 = 0;
    int n2 = 0;
    assertEqualsM("Comparing two equal numbers must return 0.", 0, compareInt(&n1, &n2));
}
Пример #7
0
void testFuelMap(void) {
	printf("*************************************************** testFuelMap\r\n");

	EngineTestHelper eth(FORD_ASPIRE_1996);

	for (int k = 0; k < FUEL_LOAD_COUNT; k++) {
		for (int r = 0; r < FUEL_RPM_COUNT; r++) {
			eth.engine.engineConfiguration->fuelTable[k][r] = k * 200 + r;
		}
	}
	for (int i = 0; i < FUEL_LOAD_COUNT; i++)
		eth.engine.engineConfiguration->fuelLoadBins[i] = i;
	for (int i = 0; i < FUEL_RPM_COUNT; i++)
		eth.engine.engineConfiguration->fuelRpmBins[i] = i;

	assertEqualsM("base fuel table", 1005, getBaseTableFuel(eth.engine.engineConfiguration, 5, 5));

	printf("*************************************************** initThermistors\r\n");

	Engine *engine = &eth.engine;
	engine_configuration_s *engineConfiguration = engine->engineConfiguration;

	initThermistors(engine);


	printf("*** getInjectorLag\r\n");
	assertEquals(1.0, getInjectorLag(12 PASS_ENGINE_PARAMETER));

	eth.engine.engineConfiguration->injectorLag = 0.5;

	for (int i = 0; i < VBAT_INJECTOR_CURVE_SIZE; i++) {
		eth.engine.engineConfiguration->battInjectorLagCorrBins[i] = i;
		eth.engine.engineConfiguration->battInjectorLagCorr[i] = 2 * i;
	}


	// because all the correction tables are zero
	printf("*************************************************** getRunningFuel 1\r\n");
	float baseFuel = getBaseTableFuel(eth.engine.engineConfiguration, 5, getEngineLoadT(PASS_ENGINE_PARAMETER_F));
	assertEqualsM("base fuel", 5.05, getRunningFuel(baseFuel, 5 PASS_ENGINE_PARAMETER));

	printf("*************************************************** setting IAT table\r\n");
	for (int i = 0; i < IAT_CURVE_SIZE; i++) {
		eth.engine.engineConfiguration->iatFuelCorrBins[i] = i;
		eth.engine.engineConfiguration->iatFuelCorr[i] = 2 * i;
	}
	eth.engine.engineConfiguration->iatFuelCorr[0] = 2;

	printf("*************************************************** setting CLT table\r\n");
	for (int i = 0; i < CLT_CURVE_SIZE; i++) {
		eth.engine.engineConfiguration->cltFuelCorrBins[i] = i;
		eth.engine.engineConfiguration->cltFuelCorr[i] = 1;
	}
	eth.engine.engineConfiguration->injectorLag = 0;

	assertEquals(NAN, getIntakeAirTemperature(&eth.engine));
	float iatCorrection = getIatCorrection(-KELV PASS_ENGINE_PARAMETER);
	assertEqualsM("IAT", 2, iatCorrection);
	float cltCorrection = getCltCorrection(getCoolantTemperature(&eth.engine) PASS_ENGINE_PARAMETER);
	assertEqualsM("CLT", 1, cltCorrection);
	float injectorLag = getInjectorLag(getVBatt(engineConfiguration) PASS_ENGINE_PARAMETER);
	assertEquals(0, injectorLag);

	testMafValue = 5;

	// 1005 * 2 for IAT correction
	printf("*************************************************** getRunningFuel 2\r\n");
	 baseFuel = getBaseTableFuel(eth.engine.engineConfiguration, 5, getEngineLoadT(PASS_ENGINE_PARAMETER_F));
	assertEqualsM("v1", 30150, getRunningFuel(baseFuel, 5 PASS_ENGINE_PARAMETER));

	testMafValue = 0;

	engineConfiguration->crankingSettings.baseCrankingFuel = 4;

	printf("*************************************************** getStartingFuel\r\n");
	// NAN in case we have issues with the CLT sensor
	assertEqualsM("getStartingFuel nan", 4, getCrankingFuel3(engineConfiguration, NAN, 0));
	assertEqualsM("getStartingFuel#1", 23.7333, getCrankingFuel3(engineConfiguration, 0, 4));
	assertEqualsM("getStartingFuel#2", 18.0419, getCrankingFuel3(engineConfiguration, 8, 15));
	assertEqualsM("getStartingFuel#3", 11.2000, getCrankingFuel3(engineConfiguration, 70, 0));
	assertEqualsM("getStartingFuel#3", 5.6000, getCrankingFuel3(engineConfiguration, 70, 50));
}
Пример #8
0
static void confgiureFordAspireTriggerShape(trigger_shape_s * s) {
	s->reset(FOUR_STROKE_CAM_SENSOR);

	s->addEvent(53.747, T_SECONDARY, TV_HIGH);
	s->addEvent(121.90, T_SECONDARY, TV_LOW);
	s->addEvent(232.76, T_SECONDARY, TV_HIGH);
	s->addEvent(300.54, T_SECONDARY, TV_LOW);
	s->addEvent(360, T_PRIMARY, TV_HIGH);

	s->addEvent(409.8412, T_SECONDARY, TV_HIGH);
	s->addEvent(478.6505, T_SECONDARY, TV_LOW);
	s->addEvent(588.045, T_SECONDARY, TV_HIGH);
	s->addEvent(657.03, T_SECONDARY, TV_LOW);
	s->addEvent(720, T_PRIMARY, TV_LOW);

	assertEquals(53.747 / 720, s->wave.getSwitchTime(0));
	assertEqualsM("@0", 1, s->wave.getChannelState(1, 0));
	assertEqualsM("@0", 1, s->wave.getChannelState(1, 0));

	assertEqualsM("@1", 0, s->wave.getChannelState(0, 1));
	assertEqualsM("@1", 0, s->wave.getChannelState(1, 1));

	assertEqualsM("@2", 0, s->wave.getChannelState(0, 2));
	assertEqualsM("@2", 1, s->wave.getChannelState(1, 2));

	assertEqualsM("@3", 0, s->wave.getChannelState(0, 3));
	assertEqualsM("@3", 0, s->wave.getChannelState(1, 3));

	assertEqualsM("@4", 1, s->wave.getChannelState(0, 4));
	assertEqualsM("@5", 1, s->wave.getChannelState(1, 5));
	assertEqualsM("@8", 0, s->wave.getChannelState(1, 8));
	assertEquals(121.90 / 720, s->wave.getSwitchTime(1));
	assertEquals(657.03 / 720, s->wave.getSwitchTime(8));

	assertEqualsM("expecting 0", 0, s->wave.findAngleMatch(53.747 / 720.0, s->getSize()));
	assertEqualsM("expecting not found", -1, s->wave.findAngleMatch(53 / 720.0, s->getSize()));
	assertEquals(7, s->wave.findAngleMatch(588.045 / 720.0, s->getSize()));

	assertEqualsM("expecting 0", 0, s->wave.waveIndertionAngle(23.747 / 720.0, s->getSize()));
	assertEqualsM("expecting 1", 1, s->wave.waveIndertionAngle(63.747 / 720.0, s->getSize()));
}
Пример #9
0
void assertFalseM(const char *msg, float actual) {
	assertEqualsM(msg, FALSE, actual);
}
Пример #10
0
void assertTrueM(const char *msg, float actual) {
	assertEqualsM(msg, TRUE, actual);
}
Пример #11
0
void assertEquals(float expected, float actual) {
	assertEqualsM("", expected, actual);
}
Пример #12
0
void testSignalExecutor(void) {
	testSignalExecutor3();
	print("*************************************** testSignalExecutor\r\n");

	eq.clear();
	assertEquals(EMPTY_QUEUE, eq.getNextEventTime(0));
	scheduling_s s1;
	scheduling_s s2;
	scheduling_s s3;
	scheduling_s s4;

	eq.insertTask(&s1, 10, callback, NULL);
	eq.insertTask(&s4, 10, callback, NULL);
	eq.insertTask(&s3, 12, callback, NULL);
	eq.insertTask(&s2, 11, callback, NULL);

	assertEquals(4, eq.size());
	assertEquals(10, eq.getHead()->momentX);
	assertEquals(10, eq.getHead()->next->momentX);
	assertEquals(11, eq.getHead()->next->next->momentX);
	assertEquals(12, eq.getHead()->next->next->next->momentX);

	callbackCounter = 0;
	eq.executeAll(10);
	assertEqualsM("callbackCounter/2", 2, callbackCounter);
	callbackCounter = 0;
	eq.executeAll(11);
	assertEqualsM("callbackCounter/1#1", 1, callbackCounter);
	eq.executeAll(100);
	assertEquals(0, eq.size());

	eq.insertTask(&s1, 12, callback, NULL);
	eq.insertTask(&s2, 11, callback, NULL);
	eq.insertTask(&s3, 10, callback, NULL);
	callbackCounter = 0;
	eq.executeAll(10);
	assertEqualsM("callbackCounter/1#2", 1, callbackCounter);
	callbackCounter = 0;
	eq.executeAll(11);
	assertEquals(1, callbackCounter);
	eq.executeAll(100);
	assertEquals(0, eq.size());

	callbackCounter = 0;
	eq.insertTask(&s1, 10, callback, NULL);
	assertEquals(10, eq.getNextEventTime(0));

	eq.executeAll(1);
	assertEqualsM("callbacks not expected", 0, callbackCounter);

	eq.executeAll(11);
	assertEquals(1, callbackCounter);

	assertEquals(EMPTY_QUEUE, eq.getNextEventTime(0));

	eq.insertTask(&s1, 10, callback, NULL);
	eq.insertTask(&s2, 13, callback, NULL);
	assertEquals(10, eq.getNextEventTime(0));

	eq.executeAll(1);
	assertEquals(10, eq.getNextEventTime(0));

	eq.executeAll(100);
	assertEquals(0, eq.size());
	callbackCounter = 0;
	// both events are scheduled for the same time
	eq.insertTask(&s1, 10, callback, NULL);
	eq.insertTask(&s2, 10, callback, NULL);

	eq.executeAll(11);

	assertEquals(2, callbackCounter);
	testSignalExecutor2();
}
Пример #13
0
void testFuelMap(void) {
	chDbgCheck(engineConfiguration!=NULL, "engineConfiguration");

	printf("*************************************************** testFuelMap\r\n");

	for (int k = 0; k < FUEL_LOAD_COUNT; k++) {
		for (int r = 0; r < FUEL_RPM_COUNT; r++) {
			engineConfiguration->fuelTable[k][r] = k * 200 + r;
		}
	}
	printf("*************************************************** initThermistors\r\n");

	initThermistors();

	printf("*** getInjectorLag\r\n");
	assertEquals(0, getInjectorLag(12));

	for (int i = 0; i < FUEL_LOAD_COUNT; i++)
		engineConfiguration->fuelLoadBins[i] = i;
	for (int i = 0; i < FUEL_RPM_COUNT; i++)
		engineConfiguration->fuelRpmBins[i] = i;

	printf("*************************************************** prepareFuelMap\r\n");
	assertEquals(1005, getBaseTableFuel(5, 5));

	engineConfiguration->injectorLag = 0.5;

	for (int i = 0; i < VBAT_INJECTOR_CURVE_SIZE; i++) {
		engineConfiguration->battInjectorLagCorrBins[i] = i;
		engineConfiguration->battInjectorLagCorr[i] = 2 * i;
	}

	EngineTestHelper eth(FORD_ASPIRE_1996);

	// because all the correction tables are zero
	printf("*************************************************** getRunningFuel\r\n");
	float baseFuel = getBaseTableFuel(5, getEngineLoadT(&eth.engine));
	assertEqualsM("value", 0.5, getRunningFuel(baseFuel, &eth.engine, 5));

	printf("*************************************************** setting IAT table\r\n");
	for (int i = 0; i < IAT_CURVE_SIZE; i++) {
		engineConfiguration->iatFuelCorrBins[i] = i;
		engineConfiguration->iatFuelCorr[i] = 2 * i;
	}
	engineConfiguration->iatFuelCorr[0] = 2;

	printf("*************************************************** setting CLT table\r\n");
	for (int i = 0; i < CLT_CURVE_SIZE; i++) {
		engineConfiguration->cltFuelCorrBins[i] = i;
		engineConfiguration->cltFuelCorr[i] = 1;
	}
	engineConfiguration->injectorLag = 0;

	assertEquals(NAN, getIntakeAirTemperature());
	float iatCorrection = getIatCorrection(-KELV);
	assertEqualsM("IAT", 2, iatCorrection);
	float cltCorrection = getCltCorrection(getCoolantTemperature());
	assertEqualsM("CLT", 1, cltCorrection);
	float injectorLag = getInjectorLag(getVBatt());
	assertEquals(0, injectorLag);

	testMafValue = 5;

	// 1005 * 2 for IAT correction
	printf("*************************************************** getRunningFuel\r\n");
	 baseFuel = getBaseTableFuel(5, getEngineLoadT(&eth.engine));
	assertEqualsM("v1", 30150, getRunningFuel(baseFuel, &eth.engine, 5));

	testMafValue = 0;

	engineConfiguration->crankingSettings.coolantTempMaxC = 65; // 8ms at 65C
	engineConfiguration->crankingSettings.fuelAtMaxTempMs = 8;

	engineConfiguration->crankingSettings.coolantTempMinC = 0; // 20ms at 0C
	engineConfiguration->crankingSettings.fuelAtMinTempMs = 20;

	printf("*************************************************** getStartingFuel\r\n");
	// NAN in case we have issues with the CLT sensor
//	assertEquals(16, getStartingFuel(NAN));
	assertEquals(20, getStartingFuel(0));
	assertEquals(18.5231, getStartingFuel(8));
	assertEquals(8, getStartingFuel(70));
}
Пример #14
0
void testLogicExpressions(void) {
	printf("*************************************************** testLogicExpressions\r\n");

	testParsing();

	LECalculator c;

	LEElement value1;
	value1.init(LE_NUMERIC_VALUE, 123.0);
	c.add(&value1);

	assertEqualsM("123", 123.0, c.getValue(0, NULL));

	LEElement value2;
	value2.init(LE_NUMERIC_VALUE, 321.0);
	c.add(&value2);

	LEElement value3;
	value3.init(LE_OPERATOR_AND);
	c.add(&value3);
	assertEqualsM("123 and 321", 1.0, c.getValue(0, NULL));

	/**
	 * 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");
	assertTrueM("NULL expected", element == NULL);


	/**
	 * fan = (not fan && coolant > 90) OR (fan && coolant > 85)
	 * fan = fan NOT coolant 90 AND more fan coolant 85 more AND OR
	 */


	mockFan = 0;
	mockCoolant = 100;

	testExpression("coolant", 100);
	testExpression("fan", 0);
	testExpression("fan not", 1);
	testExpression("coolant 90 >", 1);
	testExpression("fan not coolant 90 > and", 1);

	testExpression("100 200 1 if", 200);
	testExpression("10 99 max", 99);

	testExpression2(123, "10 self max", 123);

	testExpression("fan NOT coolant 90 > AND fan coolant 85 > AND OR", 1);
	{
		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");
		assertTrueM("Not NULL expected", element != NULL);
		LECalculator c;
		assertEqualsM("that expression", 1, c.getValue2(0, element, NULL));

		assertEquals(12, c.currentCalculationLogPosition);
		assertEquals(102, c.calcLogAction[0]);
		assertEquals(0, c.calcLogValue[0]);
	}

	testExpression("coolant", 100);
	testExpression("fan_off_setting", 0);
	testExpression("coolant fan_off_setting >", 1);

	testExpression("0 1 &", 0);
	testExpression("0 1 |", 1);

	testExpression("0 1 >", 0);

	testExpression(FAN_CONTROL_LOGIC, 1);

	mockRpm = 900;
	testExpression(FUEL_PUMP_LOGIC, 1);

}