Improve unittest build system (#13554)
[betaflight.git] / src / test / unit / cli_unittest.cc
bloba83e91e3c95d48d017da3ec9b6c11fb821bdf7ec
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdint.h>
19 #include <stdbool.h>
21 #include <limits.h>
23 #include <math.h>
25 extern "C" {
26 #include "platform.h"
27 #include "target.h"
28 #include "build/version.h"
29 #include "io/gps.h"
30 #include "cli/cli.h"
31 #include "cli/settings.h"
32 #include "common/printf.h"
33 #include "common/maths.h"
34 #include "common/gps_conversion.h"
35 #include "config/feature.h"
36 #include "drivers/buf_writer.h"
37 #include "drivers/vtx_common.h"
38 #include "config/config.h"
39 #include "fc/rc_adjustments.h"
40 #include "fc/runtime_config.h"
41 #include "flight/mixer.h"
42 #include "flight/pid.h"
43 #include "flight/servos.h"
44 #include "io/beeper.h"
45 #include "io/ledstrip.h"
46 #include "io/serial.h"
47 #include "io/vtx.h"
48 #include "msp/msp.h"
49 #include "msp/msp_box.h"
50 #include "osd/osd.h"
51 #include "pg/pg.h"
52 #include "pg/gps_rescue.h"
53 #include "pg/pg_ids.h"
54 #include "pg/beeper.h"
55 #include "pg/gps.h"
56 #include "pg/rx.h"
57 #include "rx/rx.h"
58 #include "scheduler/scheduler.h"
59 #include "sensors/battery.h"
60 #include "sensors/gyro.h"
62 void cliSet(const char *cmdName, char *cmdline);
63 int cliGetSettingIndex(char *name, uint8_t length);
64 void *cliGetValuePointer(const clivalue_t *value);
66 const clivalue_t valueTable[] = {
67 { .name = "array_unit_test", .type = VAR_INT8 | MODE_ARRAY | MASTER_VALUE, .config = { .array = { .length = 3}}, .pgn = PG_RESERVED_FOR_TESTING_1, .offset = 0 },
68 { .name = "str_unit_test", .type = VAR_UINT8 | MODE_STRING | MASTER_VALUE, .config = { .string = { 0, 16, 0 }}, .pgn = PG_RESERVED_FOR_TESTING_1, .offset = 0 },
69 { .name = "wos_unit_test", .type = VAR_UINT8 | MODE_STRING | MASTER_VALUE, .config = { .string = { 0, 16, STRING_FLAGS_WRITEONCE }}, .pgn = PG_RESERVED_FOR_TESTING_1, .offset = 0 },
71 const uint16_t valueTableEntryCount = ARRAYLEN(valueTable);
72 const lookupTableEntry_t lookupTables[] = {};
73 const char * const lookupTableOsdDisplayPortDevice[] = {};
74 const char * const buildKey = NULL;
75 const char * const releaseName = NULL;
78 PG_REGISTER(osdConfig_t, osdConfig, PG_OSD_CONFIG, 0);
79 PG_REGISTER(batteryConfig_t, batteryConfig, PG_BATTERY_CONFIG, 0);
80 PG_REGISTER(ledStripConfig_t, ledStripConfig, PG_LED_STRIP_CONFIG, 0);
81 PG_REGISTER(ledStripStatusModeConfig_t, ledStripStatusModeConfig, PG_LED_STRIP_STATUS_MODE_CONFIG, 0);
82 PG_REGISTER(systemConfig_t, systemConfig, PG_SYSTEM_CONFIG, 0);
83 PG_REGISTER(pilotConfig_t, pilotConfig, PG_PILOT_CONFIG, 0);
84 PG_REGISTER_ARRAY(adjustmentRange_t, MAX_ADJUSTMENT_RANGE_COUNT, adjustmentRanges, PG_ADJUSTMENT_RANGE_CONFIG, 0);
85 PG_REGISTER_ARRAY(modeActivationCondition_t, MAX_MODE_ACTIVATION_CONDITION_COUNT, modeActivationConditions, PG_MODE_ACTIVATION_PROFILE, 0);
86 PG_REGISTER(mixerConfig_t, mixerConfig, PG_MIXER_CONFIG, 0);
87 PG_REGISTER_ARRAY(motorMixer_t, MAX_SUPPORTED_MOTORS, customMotorMixer, PG_MOTOR_MIXER, 0);
88 PG_REGISTER_ARRAY(servoParam_t, MAX_SUPPORTED_SERVOS, servoParams, PG_SERVO_PARAMS, 0);
89 PG_REGISTER_ARRAY(servoMixer_t, MAX_SERVO_RULES, customServoMixers, PG_SERVO_MIXER, 0);
90 PG_REGISTER(beeperConfig_t, beeperConfig, PG_BEEPER_CONFIG, 0);
91 PG_REGISTER(rxConfig_t, rxConfig, PG_RX_CONFIG, 0);
92 PG_REGISTER(serialConfig_t, serialConfig, PG_SERIAL_CONFIG, 0);
93 PG_REGISTER_ARRAY(rxChannelRangeConfig_t, NON_AUX_CHANNEL_COUNT, rxChannelRangeConfigs, PG_RX_CHANNEL_RANGE_CONFIG, 0);
94 PG_REGISTER_ARRAY(rxFailsafeChannelConfig_t, MAX_SUPPORTED_RC_CHANNEL_COUNT, rxFailsafeChannelConfigs, PG_RX_FAILSAFE_CHANNEL_CONFIG, 0);
95 PG_REGISTER(pidConfig_t, pidConfig, PG_PID_CONFIG, 0);
96 PG_REGISTER(gyroConfig_t, gyroConfig, PG_GYRO_CONFIG, 0);
97 PG_REGISTER(gpsConfig_t, gpsConfig, PG_GPS_CONFIG, 0);
98 PG_REGISTER(gpsRescueConfig_t, gpsRescueConfig, PG_GPS_RESCUE, 0);
100 PG_REGISTER_WITH_RESET_FN(int8_t, unitTestData, PG_RESERVED_FOR_TESTING_1, 0);
103 #include "unittest_macros.h"
104 #include "gtest/gtest.h"
106 const bool PRINT_TEST_DATA = false;
108 TEST(CLIUnittest, TestCliSetArray)
110 char *str = (char *)"array_unit_test = 123, -3 , 1";
111 cliSet("", str);
113 const uint16_t index = cliGetSettingIndex(str, 15);
114 EXPECT_LT(index, valueTableEntryCount);
116 const clivalue_t val = valueTable[index];
117 int8_t *data = (int8_t *)cliGetValuePointer(&val);
119 if (PRINT_TEST_DATA) {
120 printf("\n===============================\n");
121 for(int i = 0; i < val.config.array.length; i++){
122 printf("data[%d] = %d\n", i, data[i]);
124 printf("\n===============================\n");
127 EXPECT_EQ(123, data[0]);
128 EXPECT_EQ( -3, data[1]);
129 EXPECT_EQ( 1, data[2]);
132 TEST(CLIUnittest, TestCliSetStringNoFlags)
134 char *str = (char *)"str_unit_test = SAMPLE";
135 cliSet("", str);
137 const uint16_t index = cliGetSettingIndex(str, 13);
138 EXPECT_LT(index, valueTableEntryCount);
140 const clivalue_t val = valueTable[index];
141 uint8_t *data = (uint8_t *)cliGetValuePointer(&val);
143 if (PRINT_TEST_DATA) {
144 printf("\n===============================\n");
145 for(int i = 0; i < val.config.string.maxlength && data[i] != 0; i++){
146 printf("data[%d] = %d (%c)\n", i, data[i], data[i]);
148 printf("\n===============================\n");
151 EXPECT_EQ('S', data[0]);
152 EXPECT_EQ('A', data[1]);
153 EXPECT_EQ('M', data[2]);
154 EXPECT_EQ('P', data[3]);
155 EXPECT_EQ('L', data[4]);
156 EXPECT_EQ('E', data[5]);
157 EXPECT_EQ(0, data[6]);
160 TEST(CLIUnittest, TestCliSetStringWriteOnce)
162 char *str1 = (char *)"wos_unit_test = SAMPLE";
163 char *str2 = (char *)"wos_unit_test = ELPMAS";
164 cliSet("", str1);
166 const uint16_t index = cliGetSettingIndex(str1, 13);
167 EXPECT_LT(index, valueTableEntryCount);
169 const clivalue_t val = valueTable[index];
171 uint8_t *data = (uint8_t *)cliGetValuePointer(&val);
172 if (PRINT_TEST_DATA) {
173 printf("\n===============================\n");
174 for(int i = 0; i < val.config.string.maxlength && data[i] != 0; i++){
175 printf("data[%d] = %d (%c)\n", i, data[i], data[i]);
177 printf("\n===============================\n");
179 EXPECT_EQ('S', data[0]);
180 EXPECT_EQ('A', data[1]);
181 EXPECT_EQ('M', data[2]);
182 EXPECT_EQ('P', data[3]);
183 EXPECT_EQ('L', data[4]);
184 EXPECT_EQ('E', data[5]);
185 EXPECT_EQ(0, data[6]);
187 cliSet("", str2);
189 EXPECT_EQ('S', data[0]);
190 EXPECT_EQ('A', data[1]);
191 EXPECT_EQ('M', data[2]);
192 EXPECT_EQ('P', data[3]);
193 EXPECT_EQ('L', data[4]);
194 EXPECT_EQ('E', data[5]);
195 EXPECT_EQ(0, data[6]);
197 cliSet("", str1);
199 EXPECT_EQ('S', data[0]);
200 EXPECT_EQ('A', data[1]);
201 EXPECT_EQ('M', data[2]);
202 EXPECT_EQ('P', data[3]);
203 EXPECT_EQ('L', data[4]);
204 EXPECT_EQ('E', data[5]);
205 EXPECT_EQ(0, data[6]);
208 // STUBS
209 extern "C" {
211 int16_t debug[8];
212 float motor_disarmed[MAX_SUPPORTED_MOTORS];
214 uint16_t batteryWarningVoltage;
215 uint8_t useHottAlarmSoundPeriod (void) { return 0; }
216 const uint32_t baudRates[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000, 400000}; // see baudRate_e
218 uint8_t debugMode;
219 int32_t schedLoopStartCycles;
220 int32_t taskGuardCycles;
222 uint32_t micros(void) {return 0;}
224 int32_t getAmperage(void)
226 return 100;
229 uint16_t getBatteryVoltage(void)
231 return 42;
234 batteryState_e getBatteryState(void)
236 return BATTERY_OK;
239 uint8_t calculateBatteryPercentageRemaining(void)
241 return 67;
244 uint8_t getMotorCount()
246 return 4;
249 size_t getEEPROMStorageSize()
251 return 0;
255 void setPrintfSerialPort(struct serialPort_s) {}
257 static const box_t boxes[] = { { "DUMMYBOX", 0, 0 } };
258 const box_t *findBoxByPermanentId(uint8_t) { return &boxes[0]; }
259 const box_t *findBoxByBoxId(boxId_e) { return &boxes[0]; }
261 int8_t unitTestDataArray[3];
263 void pgResetFn_unitTestData(int8_t *)
266 uint32_t getBeeperOffMask(void) { return 0; }
267 uint32_t getPreferredBeeperOffMask(void) { return 0; }
269 void beeper(beeperMode_e) {}
270 void beeperSilence(void) {}
271 void beeperConfirmationBeeps(uint8_t) {}
272 void beeperWarningBeeps(uint8_t) {}
273 void beeperUpdate(timeUs_t) {}
274 uint32_t getArmingBeepTimeMicros(void) {return 0;}
275 beeperMode_e beeperModeForTableIndex(int) {return BEEPER_SILENCE;}
276 uint32_t beeperModeMaskForTableIndex(int idx) {UNUSED(idx); return 0;}
277 const char *beeperNameForTableIndex(int) {return NULL;}
278 int beeperTableEntryCount(void) {return 0;}
279 bool isBeeperOn(void) {return false;}
280 void beeperOffSetAll(uint8_t) {}
281 void setBeeperOffMask(uint32_t) {}
282 void setPreferredBeeperOffMask(uint32_t) {}
284 void beeperOffSet(uint32_t) {}
285 void beeperOffClear(uint32_t) {}
286 void beeperOffClearAll(void) {}
287 bool parseColor(int, const char *) {return false; }
288 bool resetEEPROM(void) { return true; }
289 void bufWriterFlush(bufWriter_t *) {}
290 void mixerResetDisarmedMotors(void) {}
292 typedef enum {
293 DUMMY
294 } pageId_e;
296 void dashboardShowFixedPage(pageId_e){}
297 void dashboardUpdate(timeUs_t) {}
299 bool parseLedStripConfig(int, const char *){return false; }
300 const char rcChannelLetters[] = "AERT12345678abcdefgh";
302 void parseRcChannels(const char *, rxConfig_t *){}
303 void mixerLoadMix(int, motorMixer_t *) {}
304 bool setModeColor(ledModeIndex_e, int, int) { return false; }
305 float motorConvertFromExternal(uint16_t) { return 1.0; }
306 void motorShutdown(void) { }
307 uint8_t getCurrentPidProfileIndex(void){ return 1; }
308 uint8_t getCurrentControlRateProfileIndex(void){ return 1; }
309 void changeControlRateProfile(uint8_t) {}
310 void resetAllRxChannelRangeConfigurations(rxChannelRangeConfig_t *) {}
311 void writeEEPROM() {}
312 serialPortConfig_t *serialFindPortConfigurationMutable(serialPortIdentifier_e) {return NULL; }
313 baudRate_e lookupBaudRateIndex(uint32_t){return BAUD_9600; }
314 serialPortUsage_t *findSerialPortUsageByIdentifier(serialPortIdentifier_e){ return NULL; }
315 serialPort_t *openSerialPort(serialPortIdentifier_e, serialPortFunction_e, serialReceiveCallbackPtr, void *, uint32_t, portMode_e, portOptions_e) { return NULL; }
316 const serialPortConfig_t *findSerialPortConfig(serialPortFunction_e) { return NULL; }
317 void serialPassthrough(serialPort_t *, serialPort_t *, serialConsumer *, serialConsumer *) {}
318 uint32_t millis(void) { return 0; }
319 uint8_t getBatteryCellCount(void) { return 1; }
320 void servoMixerLoadMix(int) {}
321 const char * getBatteryStateString(void){ return "_getBatteryStateString_"; }
323 uint32_t stackTotalSize(void) { return 0x4000; }
324 uint32_t stackHighMem(void) { return 0x80000000; }
325 uint16_t getEEPROMConfigSize(void) { return 1024; }
327 uint8_t __config_start = 0x00;
328 uint8_t __config_end = 0x10;
329 uint16_t averageSystemLoadPercent = 0;
331 timeDelta_t getTaskDeltaTimeUs(taskId_e){ return 0; }
332 uint16_t currentRxIntervalUs = 9000;
334 /*const char *armingDisableFlagNames[]= {
335 "DUMMYDISABLEFLAGNAME"
336 };*/
338 void getTaskInfo(taskId_e, taskInfo_t *) {}
339 void getCheckFuncInfo(cfCheckFuncInfo_t *) {}
340 void schedulerResetTaskMaxExecutionTime(taskId_e) {}
341 void schedulerResetCheckFunctionMaxExecutionTime(void) {}
343 const char * const targetName = "UNITTEST";
344 const char* const buildDate = "Jan 01 2017";
345 const char * const buildTime = "00:00:00";
346 const char * const shortGitRevision = "MASTER";
348 //uint32_t serialRxBytesWaiting(const serialPort_t *) {return 0;}
349 //uint8_t serialRead(serialPort_t *){return 0;}
351 void bufWriterAppend(bufWriter_t *, uint8_t ch){ printf("%c", ch); }
352 //void serialWriteBufShim(void *, const uint8_t *, int) {}
353 void bufWriterInit(bufWriter_t *, uint8_t *, int, bufWrite_t, void *) { }
354 //void setArmingDisabled(armingDisableFlags_e) {}
356 void waitForSerialPortToFinishTransmitting(serialPort_t *) {}
357 void systemResetToBootloader(void) {}
358 void resetConfig(void) {}
359 void systemReset(void) {}
360 void writeUnmodifiedConfigToEEPROM(void) {}
362 void changePidProfile(uint8_t) {}
363 bool serialIsPortAvailable(serialPortIdentifier_e) { return false; }
364 void generateLedConfig(ledConfig_t *, char *, size_t) {}
365 //bool isSerialTransmitBufferEmpty(const serialPort_t *) {return true; }
366 //void serialWrite(serialPort_t *, uint8_t ch) { printf("%c", ch);}
368 //void serialSetCtrlLineStateCb(serialPort_t *, void (*)(void *, uint16_t ), void *) {}
369 void serialSetCtrlLineStateDtrPin(serialPort_t *, ioTag_t ) {}
370 void serialSetCtrlLineState(serialPort_t *, uint16_t ) {}
372 //void serialSetBaudRateCb(serialPort_t *, void (*)(serialPort_t *context, uint32_t baud), serialPort_t *) {}
373 void rescheduleTask(taskId_e, timeDelta_t){}
374 void schedulerSetNextStateTime(timeDelta_t ){}
375 char *getBoardName(void) { return NULL; }
376 char *getManufacturerId(void) { return NULL; }
377 bool boardInformationIsSet(void) { return true; }
379 bool setBoardName(char *newBoardName) { UNUSED(newBoardName); return true; };
380 bool setManufacturerId(char *newManufacturerId) { UNUSED(newManufacturerId); return true; };
381 bool persistBoardInformation(void) { return true; };
383 void activeAdjustmentRangeReset(void) {}
384 void analyzeModeActivationConditions(void) {}
385 bool isModeActivationConditionConfigured(const modeActivationCondition_t *, const modeActivationCondition_t *) { return false; }
387 void delay(uint32_t) {}
388 displayPort_t *osdGetDisplayPort(osdDisplayPortDevice_e *) { return NULL; }
389 mcuTypeId_e getMcuTypeId(void) { return MCU_TYPE_UNKNOWN; }
390 uint16_t getCurrentRxIntervalUs(void) { return 0; }
391 uint16_t getAverageSystemLoadPercent(void) { return 0; }