enhance minimal unit test for existing overdwell mechanism #6373

This commit is contained in:
kifir 2024-05-05 14:46:11 +03:00
parent 2425fc5599
commit 455c00d9be
3 changed files with 89 additions and 15 deletions

View File

@ -247,6 +247,10 @@ public:
TestExecutor executor;
std::function<void(IgnitionEvent*, bool)> onIgnitionEvent;
std::function<void(const IgnitionEvent&, efitick_t, angle_t, efitick_t)> onScheduleTurnSparkPinHighStartCharging
= [](const IgnitionEvent&, efitick_t, angle_t, efitick_t) -> void {};
std::function<void(const IgnitionEvent&, efitick_t)> onScheduleOverFireSparkAndPrepareNextSchedule
= [](const IgnitionEvent&, efitick_t) -> void {};
#endif // EFI_UNIT_TEST
#if EFI_ENGINE_CONTROL

View File

@ -413,6 +413,10 @@ static void scheduleSparkEvent(bool limitedSpark, IgnitionEvent *event,
*/
chargeTime = scheduleByAngle(&event->dwellStartTimer, edgeTimestamp, angleOffset, { &turnSparkPinHighStartCharging, event });
#if EFI_UNIT_TEST
engine->onScheduleTurnSparkPinHighStartCharging(*event, edgeTimestamp, angleOffset, chargeTime);
#endif
#if SPARK_EXTREME_LOGGING
efiPrintf("sparkUp revolution scheduled=%d for %d ticks [%s] %d later id=%d", getRevolutionCounter(), time2print(chargeTime), event->getOutputForLoggins()->getName(), (int)angleOffset,
event->sparkCounter);
@ -463,6 +467,10 @@ static void scheduleSparkEvent(bool limitedSpark, IgnitionEvent *event,
* and it looks like current (smart?) re-queuing is effectively cancelling out the overdwell? is that the way this was intended to work?
*/
engine->executor.scheduleByTimestampNt("overdwell", &event->sparkEvent.scheduling, fireTime, { overFireSparkAndPrepareNextSchedule, event });
#if EFI_UNIT_TEST
engine->onScheduleOverFireSparkAndPrepareNextSchedule(*event, fireTime);
#endif
} else {
engine->engineState.overDwellNotScheduledCounter++;
}

View File

@ -1193,8 +1193,8 @@ TEST(big, testAssertWeAreNotMissingASpark299) {
ASSERT_EQ( 0, unitTestWarningCodeState.recentWarnings.getCount()) << "warningCounter#1";
}
TEST(big, testSparkDwell) {
printf("*************************************************** testSparkDwell\r\n");
TEST(coil, testOverdwellProtection) {
printf("*************************************************** testOverdwellProtection\r\n");
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
engineConfiguration->ignitionMode = IM_WASTED_SPARK;
@ -1202,6 +1202,10 @@ TEST(big, testSparkDwell) {
engineConfiguration->isIgnitionEnabled = true;
engineConfiguration->isInjectionEnabled = false;
engine->onScheduleOverFireSparkAndPrepareNextSchedule = [&](const IgnitionEvent&, efitick_t) -> void {
FAIL() << "Unexpected scheduling of overFireSparkAndPrepareNextSchedule";
};
ASSERT_EQ( 0, unitTestWarningCodeState.recentWarnings.getCount()) << "warningCounter#0";
eth.smartFireRise(20);
@ -1223,38 +1227,96 @@ TEST(big, testSparkDwell) {
ASSERT_EQ(3000, Sensor::getOrZero(SensorType::Rpm));
// negative advance is rarely used but worth testing considering all out angleWrap.
// negative advance is rarely used but worth testing considering all out angleWrap.
setWholeTimingTable(-5);
eth.engine.periodicFastCallback();
eth.smartFireRise(20);
eth.smartFireFall(20);
printf("*************************************************** testSparkDwell start\r\n");
printf("*************************************************** testOverdwellProtection start\r\n");
// Magic above is the simpliest way to schedule overdwell sparkDown that I found in
// testAssertWeAreNotMissingASpark299. May be later we will be able to simplify this spell.
const efitimeus_t expectedSparkUpTimestampUs = NT2US(17727777); // magic constant from debugger
const IgnitionOutputPin& testCoil = enginePins.coils[0];
const std::string testOutputName(testCoil.getName());
ASSERT_STREQ("Coil 1", testOutputName.c_str()) << "Unexpected test output name";
std::optional<efitick_t> turnSparkPinHighStartChargingTimestamp;
std::optional<int> testSparkCounter;
engine->onScheduleTurnSparkPinHighStartCharging =
[&](const IgnitionEvent& event, efitick_t, angle_t, efitick_t chargeTime) -> void {
if (testOutputName == event.outputs[0]->getName()) {
EXPECT_FALSE(turnSparkPinHighStartChargingTimestamp.has_value())
<< "Extra scheduled overFireSparkAndPrepareNextSchedule";
turnSparkPinHighStartChargingTimestamp = chargeTime;
testSparkCounter = event.sparkCounter;
}
};
std::optional<efitick_t> overFireSparkAndPrepareNextTimestamp;
engine->onScheduleOverFireSparkAndPrepareNextSchedule =
[&](const IgnitionEvent& event, efitick_t fireTime) -> void {
EXPECT_STREQ(testOutputName.c_str(), event.outputs[0]->getName())
<< "overFireSparkAndPrepareNextSchedule is scheduled for unexpected output";
EXPECT_FALSE(overFireSparkAndPrepareNextTimestamp.has_value())
<< "Extra scheduled overFireSparkAndPrepareNextSchedule";
overFireSparkAndPrepareNextTimestamp = fireTime;
ASSERT_TRUE(testSparkCounter.has_value()) << "Missed scheduled turnSparkPinHighStartCharging";
EXPECT_EQ(testSparkCounter.value(), event.sparkCounter)
<< "Scheduled overFireSparkAndPrepareNextSchedule doesn't match scheduled turnSparkPinHighStartCharging";
};
eth.smartFireFall(20); // this operation should schedule over fire spark
ASSERT_TRUE(turnSparkPinHighStartChargingTimestamp.has_value())
<< "Missed scheduled overFireSparkAndPrepareNextSchedule";
const efitimeus_t expectedSparkUpTimestampUs = NT2US(turnSparkPinHighStartChargingTimestamp.value());
const efitimeus_t sparkDownOverdwellDurationUs = MS2US(1.5f * engine->ignitionState.sparkDwell);
EXPECT_EQ(4500, sparkDownOverdwellDurationUs);
EXPECT_EQ(4500, sparkDownOverdwellDurationUs) << "Unexpected sparkDown overdwell duration";
const efitimeus_t expectedSparkDownOverdwellTimestampUs = expectedSparkUpTimestampUs + sparkDownOverdwellDurationUs;
EXPECT_EQ(expectedSparkDownOverdwellTimestampUs, NT2US(18177776)); // magic constant from debugger
ASSERT_TRUE(overFireSparkAndPrepareNextTimestamp.has_value())
<< "Missed scheduled overFireSparkAndPrepareNextSchedule";
const efitimeus_t expectedSparkDownOverdwellTimestampUs = NT2US(overFireSparkAndPrepareNextTimestamp.value());
EXPECT_EQ(expectedSparkDownOverdwellTimestampUs, expectedSparkUpTimestampUs + sparkDownOverdwellDurationUs);
EXPECT_EQ(enginePins.coils[0].getLogicValue(), false);
EXPECT_FALSE(testCoil.getLogicValue()) << "Test coil should be off";
engine->onScheduleTurnSparkPinHighStartCharging =
[&](const IgnitionEvent&, efitick_t, angle_t, efitick_t) -> void {
FAIL() << "Unexpected scheduling of turnSparkPinHighStartCharging";
};
engine->onScheduleOverFireSparkAndPrepareNextSchedule =
[&](const IgnitionEvent&, efitick_t) -> void {
FAIL() << "Unexpected scheduling of overFireSparkAndPrepareNextSchedule";
};
std::optional<int> testIgnitionEventState;
engine->onIgnitionEvent = [&](IgnitionEvent* event, bool state) -> void {
if (testOutputName == event->outputs[0]->getName()) {
EXPECT_EQ(testSparkCounter.value(), event->sparkCounter) << "Unexpected spark counter in ignition event";
testIgnitionEventState = state;
}
};
eth.setTimeAndInvokeEventsUs(expectedSparkUpTimestampUs - 1);
EXPECT_EQ(enginePins.coils[0].getLogicValue(), false);
EXPECT_FALSE(testCoil.getLogicValue()) << "Test still coil should be off";
EXPECT_FALSE(testIgnitionEventState.has_value()) << "Unexpected ignition event";
eth.setTimeAndInvokeEventsUs(expectedSparkUpTimestampUs);
EXPECT_EQ(enginePins.coils[0].getLogicValue(), true);
EXPECT_TRUE(testCoil.getLogicValue()) << "Test coil should be on";
ASSERT_TRUE(testIgnitionEventState.has_value()) << "Missed ignition event";
EXPECT_TRUE(testIgnitionEventState.value()) << "Unexpected state in ignition event";
testIgnitionEventState.reset();
eth.setTimeAndInvokeEventsUs(expectedSparkDownOverdwellTimestampUs - 1);
EXPECT_EQ(enginePins.coils[0].getLogicValue(), true);
EXPECT_TRUE(testCoil.getLogicValue()) << "Test coil still should be on";
EXPECT_FALSE(testIgnitionEventState.has_value()) << "Unexpected ignition event";
eth.setTimeAndInvokeEventsUs(expectedSparkDownOverdwellTimestampUs);
EXPECT_EQ(enginePins.coils[0].getLogicValue(), false);
EXPECT_FALSE(testCoil.getLogicValue()) << "Test coil should be off";
ASSERT_TRUE(testIgnitionEventState.has_value()) << "Missed ignition event";
EXPECT_FALSE(testIgnitionEventState.value()) << "Unexpected state in ignition event";
}