Make the module API more concise. (#3571)

engineModules.get<FOO>(). becomes modules<FOO>()->

I believe the new API is more conducive to supporting arrays, by doing std::array<T, N> or
std::array<Mockable<T>, N>, with the support of a helper class.
This commit is contained in:
Scott Smith 2021-11-17 18:50:00 -08:00 committed by GitHub
parent ba8bd0a704
commit 98040ad9af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 45 additions and 53 deletions

View File

@ -553,7 +553,7 @@ void startIdleBench(void) {
#endif /* EFI_UNIT_TEST */
void startIdleThread() {
engine->engineModules.unmock<IdleController>().init(&engineConfiguration->idleTimingPid);
engine->module<IdleController>().unmock().init(&engineConfiguration->idleTimingPid);
getIdlePid()->initPidClass(&engineConfiguration->idleRpmPid);

View File

@ -51,7 +51,7 @@ static angle_t getRunningAdvance(int rpm, float engineLoad) {
// get advance from the separate table for Idle
if (engineConfiguration->useSeparateAdvanceForIdle &&
engine->engineModules.unmock<IdleController>().isIdlingOrTaper()) {
engine->module<IdleController>().unmock().isIdlingOrTaper()) {
float idleAdvance = interpolate2d(rpm, config->idleAdvanceBins, config->idleAdvance);
auto [valid, tps] = Sensor::get(SensorType::DriverThrottleIntent);
@ -89,7 +89,7 @@ angle_t getAdvanceCorrections(int rpm) {
iatCorrection = iatAdvanceCorrectionMap.getValue(rpm, iat);
}
float pidTimingCorrection = engine->engineModules.unmock<IdleController>().getIdleTimingAdjustment(rpm);
float pidTimingCorrection = engine->module<IdleController>().unmock().getIdleTimingAdjustment(rpm);
if (engineConfiguration->debugMode == DBG_IGNITION_TIMING) {
#if EFI_TUNER_STUDIO

View File

@ -24,7 +24,7 @@ float AirmassVeModelBase::getVe(int rpm, float load) const {
auto tps = Sensor::get(SensorType::Tps1);
// get VE from the separate table for Idle if idling
if (engine->engineModules.unmock<IdleController>().isIdlingOrTaper() &&
if (engine->module<IdleController>().unmock().isIdlingOrTaper() &&
tps && engineConfiguration->useSeparateVeForIdle) {
float idleVe = interpolate2d(rpm, config->idleVeBins, config->idleVe);
// interpolate between idle table and normal (running) table using TPS threshold

View File

@ -131,6 +131,14 @@ public:
EngineModule // dummy placeholder so the previous entries can all have commas
> engineModules;
/**
* Slightly shorter helper function to keep the code looking clean.
*/
template<typename get_t>
auto & module() {
return engineModules.get<get_t>();
}
cyclic_buffer<int> triggerErrorDetection;
GearControllerBase *gearController;

View File

@ -155,7 +155,7 @@ void EngineState::periodicFastCallback() {
}
// Store the pre-wall wetting injection duration for scheduling purposes only, not the actual injection duration
engine->injectionDuration = engine->engineModules.get<InjectorModel>().getInjectionDuration(injectionMass);
engine->injectionDuration = engine->module<InjectorModel>()->getInjectionDuration(injectionMass);
float fuelLoad = getFuelingLoad();
injectionOffset = getInjectionOffset(rpm, fuelLoad);

View File

@ -279,7 +279,7 @@ float getInjectionMass(int rpm) {
float injectionFuelMass = cycleFuelMass * durationMultiplier;
// Prepare injector flow rate & deadtime
engine->engineModules.get<InjectorModel>().prepare();
engine->module<InjectorModel>()->prepare();
floatms_t tpsAccelEnrich = engine->tpsAccelEnrichment.getTpsEnrichment();
efiAssert(CUSTOM_ERR_ASSERT, !cisnan(tpsAccelEnrich), "NaN tpsAccelEnrich", 0);
@ -288,7 +288,7 @@ float getInjectionMass(int rpm) {
// For legacy reasons, the TPS accel table is in units of milliseconds, so we have to convert BACK to mass
float tpsAccelPerInjection = durationMultiplier * tpsAccelEnrich;
float tpsFuelMass = engine->engineModules.get<InjectorModel>().getFuelMassForDuration(tpsAccelPerInjection);
float tpsFuelMass = engine->module<InjectorModel>()->getFuelMassForDuration(tpsAccelPerInjection);
return injectionFuelMass + tpsFuelMass;
#else

View File

@ -172,7 +172,7 @@ void InjectionEvent::onTriggerTooth(size_t trgEventIndex, int rpm, efitick_t now
// Perform wall wetting adjustment on fuel mass, not duration, so that
// it's correct during fuel pressure (injector flow) or battery voltage (deadtime) transients
injectionMassGrams = wallFuel.adjust(injectionMassGrams);
const floatms_t injectionDuration = engine->engineModules.get<InjectorModel>().getInjectionDuration(injectionMassGrams);
const floatms_t injectionDuration = engine->module<InjectorModel>()->getInjectionDuration(injectionMassGrams);
#if EFI_PRINTF_FUEL_DETAILS
if (printFuelDebug) {

View File

@ -46,9 +46,13 @@ struct type_list {
}
/*
* Return the object representing the type get_t. May return a mocked get_t::interface_t instead.
* Return the container object for type get_t.
*
* get_t should not be Mockable, it should be the actual type.
* The return object will have the methods unmock(), operator->, operator*, and if
* Mockable, set().
*
* The return type is type_list<get_t> or type_list<Mockable<get_t>>
*/
template<typename get_t>
auto get() -> std::enable_if_t<decltype(first)::template has<get_t>(),
@ -62,39 +66,6 @@ struct type_list {
return others.template get<get_t>();
}
/*
* Return the regular, unmocked object unmock_t.
*
* unmock_t should not be Mockable, it should be the actual type.
*/
template<typename unmock_t>
auto unmock() -> std::enable_if_t<decltype(first)::template has<unmock_t>(), unmock_t &> {
return first.template unmock<unmock_t>();
}
template<typename unmock_t>
auto unmock() -> std::enable_if_t<!decltype(first)::template has<unmock_t>(), unmock_t &> {
return others.template unmock<unmock_t>();
}
#if EFI_UNIT_TEST
/*
* Change the object returned by get<set_t>().
*
* param_t should be a pointer or nullptr. If you pass nullptr, it will be reset to the
* unmock version.
*/
template<typename set_t, typename param_t>
auto set(param_t ptr) -> std::enable_if_t<decltype(first)::template has<set_t>()> {
first.template set<set_t>(ptr);
}
template<typename set_t, typename param_t>
auto set(param_t ptr) -> std::enable_if_t<!decltype(first)::template has<set_t>()> {
others.template set<set_t>(ptr);
}
#endif // EFI_UNIT_TEST
/*
* Returns whether has_t exists in the type list
*
@ -128,14 +99,20 @@ public:
template<typename get_t, typename = std::enable_if_t<has<get_t>()>>
auto & get() {
return me;
return *this;
}
template<typename unmock_t, typename = std::enable_if_t<has<unmock_t>()>>
auto & unmock() {
return me;
}
base_t * operator->() {
return &me;
}
base_t & operator*() {
return me;
}
};
#if !EFI_UNIT_TEST
@ -173,22 +150,29 @@ public:
template<typename get_t, typename = std::enable_if_t<has<get_t>()>>
auto & get() {
return *cur;
return *this;
}
template<typename unmock_t, typename = std::enable_if_t<has<unmock_t>()>>
auto & unmock() {
return me;
}
template<typename set_t, typename param_t>
auto set(param_t ptr) -> std::enable_if_t<has<set_t>()> {
void set(typename base_t::interface_t * ptr) {
if (ptr) {
cur = ptr;
} else {
cur = &me;
}
}
auto * operator->() {
return cur;
}
auto & operator*() {
return *cur;
}
};
#endif // EFI_UNIT_TEST

View File

@ -22,7 +22,7 @@ TEST(injectionScheduling, NormalDutyCycle) {
// Injection duration of 20ms
MockInjectorModel2 im;
EXPECT_CALL(im, getInjectionDuration(_)).WillOnce(Return(20.0f));
engine->engineModules.set<InjectorModel>(&im);
engine->module<InjectorModel>().set(&im);
{
InSequence is;

View File

@ -697,7 +697,7 @@ void doTestFuelSchedulerBug299smallAndMedium(int startUpDelayMs) {
// Injection duration of 12.5ms
MockInjectorModel2 im;
EXPECT_CALL(im, getInjectionDuration(_)).WillRepeatedly(Return(12.5f));
engine->engineModules.set<InjectorModel>(&im);
engine->module<InjectorModel>().set(&im);
assertEqualsM("duty for maf=3", 62.5, getInjectorDutyCycle(GET_RPM()));
@ -857,7 +857,7 @@ void doTestFuelSchedulerBug299smallAndMedium(int startUpDelayMs) {
// Injection duration of 17.5ms
MockInjectorModel2 im2;
EXPECT_CALL(im2, getInjectionDuration(_)).WillRepeatedly(Return(17.5f));
engine->engineModules.set<InjectorModel>(&im2);
engine->module<InjectorModel>().set(&im2);
// duty cycle above 75% is a special use-case because 'special' fuel event overlappes the next normal event in batch mode
assertEqualsM("duty for maf=3", 87.5, getInjectorDutyCycle(GET_RPM()));
@ -994,7 +994,7 @@ TEST(big, testFuelSchedulerBug299smallAndLarge) {
// Injection duration of 17.5ms
MockInjectorModel2 im;
EXPECT_CALL(im, getInjectionDuration(_)).WillRepeatedly(Return(17.5f));
engine->engineModules.set<InjectorModel>(&im);
engine->module<InjectorModel>().set(&im);
assertEqualsM("Lduty for maf=3", 87.5, getInjectorDutyCycle(GET_RPM()));
@ -1061,7 +1061,7 @@ TEST(big, testFuelSchedulerBug299smallAndLarge) {
engine->injectionDuration = 2.0f;
MockInjectorModel2 im2;
EXPECT_CALL(im2, getInjectionDuration(_)).WillRepeatedly(Return(2.0f));
engine->engineModules.set<InjectorModel>(&im2);
engine->module<InjectorModel>().set(&im2);
ASSERT_EQ( 10, getInjectorDutyCycle(GET_RPM())) << "Lduty for maf=3";