diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..9da13e1b3 --- /dev/null +++ b/.clang-format @@ -0,0 +1,270 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseBlocks: false +IndentCaseLabels: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +KeepEmptyLinesAtEOF: false +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 4 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: NextLine +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +PPIndentWidth: -1 +QualifierAlignment: Leave +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: pb + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInContainerLiterals: true +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +VerilogBreakBetweenInstancePorts: true +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..36d765f8b --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,59 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*, + bugprone-*, cppcoreguidelines-*, readability-*, + -cppcoreguidelines-avoid-non-const-global-variables, + -bugprone-easily-swappable-parameters, + -clang-analyzer-security.insecureAPI.*' +WarningsAsErrors: '' +HeaderFileExtensions: + - '' + - h + - hh + - hpp + - hxx +ImplementationFileExtensions: + - c + - cc + - cpp + - cxx +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: none +User: nate +CheckOptions: + cppcoreguidelines-avoid-magic-numbers.IgnoredIntegerValues: 1;2;3;4;100 + readability-magic-numbers.IgnoredIntegerValues: 1;2;3;4;100 + readability-identifier-naming.EnumCase: CamelCase + readability-identifier-naming.EnumConstantCase: CamelCase + readability-identifier-naming.EnumConstantPrefix: k + readability-identifier-naming.FunctionCase: camelBack + readability-identifier-naming.GlobalConstantCase: CamelCase + readability-identifier-naming.GlobalConstantPrefix: k + readability-identifier-naming.GlobalConstantPointerCase: CamelCase + readability-identifier-naming.GlobalConstantPointerPrefix: k + readability-identifier-naming.GlobalFunctionCase: CamelCase + readability-identifier-naming.GlobalPointerCase: lower_case + readability-identifier-naming.GlobalVariableCase: lower_case + readability-identifier-naming.LocalConstantCase: CamelCase + readability-identifier-naming.LocalConstantPrefix: k + readability-identifier-naming.LocalConstantPointerCase: CamelCase + readability-identifier-naming.LocalConstantPointerPrefix: k + readability-identifier-naming.LocalPointerCase: lower_case + readability-identifier-naming.LocalVariableCase: lower_case + readability-identifier-naming.MacroDefinitionCase: UPPER_CASE + readability-identifier-naming.ParameterCase: lower_case + readability-identifier-naming.PointerParameterCase: lower_case + readability-identifier-naming.StaticConstantCase: CamelCase + readability-identifier-naming.StaticConstantPrefix: k + readability-identifier-naming.StaticVariableCase: lower_case + readability-identifier-naming.TypedefCase: CamelCase + readability-identifier-naming.StructCase: lower_case + readability-identifier-naming.UnionCase: CamelCase + readability-identifier-naming.VariableCase: lower_case + readability-identifier-naming.IgnoreMainLikeFunctions: false + readability-identifier-length.MinimumVariableNameLength: 2 + readability-identifier-length.MinimumParameterNameLength: 2 + readability-function-cognitive-complexity.Threshold: 32 +SystemHeaders: false +... + diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index 2c1b365dd..3329fd716 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -21,3 +21,12 @@ jobs: run: make clean - name: make leader run: make leader + # Check that format was ran and has no errors + - name: format-check + run: make format-check + # Apply format in case newline changes create tidy warnings (NOLINT comments change lines) + - name: format + run: make format + # Check that tidy was ran and has no errors + - name: tidy-check + run: make tidy-check diff --git a/Apps/Inc/MedianFilter.h b/Apps/Inc/MedianFilter.h deleted file mode 100644 index 5dd629571..000000000 --- a/Apps/Inc/MedianFilter.h +++ /dev/null @@ -1,221 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file MedianFilter.h - * @brief - * - * @defgroup MedianFilter - * @addtogroup MedianFilter - * @{ - */ - -/* - * This file implements a median filter. - * - * In order to use it in another file, you must import it in - * a particular way. - * - * 1. Define your data type, like so - * #define MEDIAN_FILTER_TYPE int - * 2. Define your filter depth, like so - * #define MEDIAN_FILTER_DEPTH (128) - * 3. Define the number of channels in your filter, like so - * #define MEDIAN_FILTER_CHANNELS (31) - * 3. Name your median filter - * #define MEDIAN_FILTER_NAME my_fifo - * 4. Import this file - * #include "MedianFilter.h" - * - * This file includes some defaults, but they might not work for - * your case! - * - * Also, this file undef's everything at the end, so you can import - * multiple times if you need. - * - * If MEDIAN_FILTER_NAME == my_filter, then your new data structure will be - * called my_filter_t. - * - * NOTE: importantly, this does not currently support usage from - * header files. That is, all these types/functions are statically - * declared, so there cannot be a non-static fifo at the moment. - */ - -// The header guard only guard the import, -// since this file can be imported multiple times -#ifndef MEDIAN_FILTER_H -#define MEDIAN_FILTER_H -#include -#include -#endif - -// The type of the median filter -#ifndef MEDIAN_FILTER_TYPE -#define MEDIAN_FILTER_TYPE int32_t -#endif - -// The depth of the median filter -#ifndef MEDIAN_FILTER_DEPTH -#define MEDIAN_FILTER_DEPTH 3 -#endif - -// The number of channels in the median filter -#ifndef MEDIAN_FILTER_CHANNELS -#define MEDIAN_FILTER_CHANNELS 1 -#endif - -// The name of the median filter (minus the _t) -#ifndef MEDIAN_FILTER_NAME -#define MEDIAN_FILTER_NAME define_your_filter_type -#endif - -// Utility definitions -#define _CONCAT(A, B) A ## B -#define CONCAT(A, B) _CONCAT(A, B) - -// some shorthand -#define MF_TYPE MEDIAN_FILTER_TYPE -#define MF_DEPTH MEDIAN_FILTER_DEPTH -#define MF_CHANNELS MEDIAN_FILTER_CHANNELS -#define MF_NAME MEDIAN_FILTER_NAME - -// Type names -#define MEDIAN_FILTER_STRUCT_NAME CONCAT(MF_NAME, _s) -#define MEDIAN_FILTER_TYPE_NAME CONCAT(MF_NAME, _t) - -// more shorthand -#define MF_STRUCT_NAME MEDIAN_FILTER_STRUCT_NAME -#define MF_TYPE_NAME MEDIAN_FILTER_TYPE_NAME - -// The actual structure -typedef struct MF_STRUCT_NAME { - MF_TYPE raw[MF_CHANNELS][MF_DEPTH]; - MF_TYPE filtered[MF_CHANNELS]; - uint32_t index; -} MF_TYPE_NAME; - -// Define some names for our functions -#define MEDIAN CONCAT(MF_NAME, _median) -#define INIT CONCAT(MF_NAME, _init) -#define GET CONCAT(MF_NAME, _get) -#define PUT CONCAT(MF_NAME, _put) -#define GETSINGLE CONCAT(MF_NAME, _getSingle) - -/** - * @brief Helper function to find the median of an array of MF_TYPE with length MF_DEPTH. - * DO NOT call this function directly. - * - * @param channel the channel in the median filter to find the median of - */ -static inline MF_TYPE __attribute__((unused)) -MEDIAN (MF_TYPE *channel) { - static MF_TYPE sorted[MF_DEPTH]; - - // copy channels into temporary array - memcpy(sorted, channel, MF_DEPTH * sizeof(MF_TYPE)); - - // sort temporary array - for (uint32_t i = 0; i < MF_DEPTH; ++i) { - MF_TYPE min = sorted[i]; - uint32_t minIdx = i; - for (uint32_t j = i + 1; j < MF_DEPTH; ++j) { - if (sorted[j] < min) { - min = sorted[j]; - minIdx = j; - } - } - sorted[minIdx] = sorted[i]; - sorted[i] = min; - } - - // return median - return sorted[MF_DEPTH >> 1]; -} - -/** - * @brief Initialize a new median filter - * - * If the type of the filter is myfilter_t, then this function - * will be called myfilter_init(). - * - * @param filter a pointer to the median filter to initialize - * @param low a value that is below the range of expected values - * @param high a value that is above the range of expected values - */ -static inline void __attribute__((unused)) -INIT (MF_TYPE_NAME *filter, MF_TYPE low, MF_TYPE high) { - // intialize the filter with alternating low and high values, so it will be stable at startup - for (uint32_t channel = 0; channel < MF_CHANNELS; ++channel) { - for (uint32_t i = 0; i < MF_DEPTH - 1; ++i) { - filter->raw[channel][i] = (i & 1) ? high : low; - } - filter->filtered[channel] = MEDIAN(filter->raw[channel]); - } - - filter->index = MF_DEPTH - 1; -} - -/** - * @brief update the median filter by giving it a new set of values for all channels - * - * @param filter a pointer to the median filter - * @param channels a complete set of new values for all channels to add to the median filter - * - */ -static inline void __attribute__((unused)) -PUT (MF_TYPE_NAME *filter, MF_TYPE *channels) { - // put the new data into the filter - for (uint32_t channel = 0; channel < MF_CHANNELS; ++channel) { - filter->raw[channel][filter->index] = channels[channel]; - } - (filter->index) = (filter->index + 1) % MF_DEPTH; - - // update the list of filtered values - for (uint32_t channel = 0; channel < MF_CHANNELS; ++channel) { - filter->filtered[channel] = MEDIAN(filter->raw[channel]); - } -} - -/** - * @brief get a complete set of filtered values for all channels - * - * @param filter a pointer to the median filter - * @param dest a pointer to a buffer to store all of the filtered values - */ -static inline void __attribute__((unused)) -GET (MF_TYPE_NAME *filter, MF_TYPE *dest) { - memcpy(dest, filter->filtered, sizeof(MF_TYPE) * MF_CHANNELS); -} - -/** - * @brief get a filtered value for a single channel in the median filter - * - * @param filter a pointer to the median filter - * @param channel the channel to read - * @return the filtered value - */ -static inline MF_TYPE __attribute__((unused)) -GETSINGLE (MF_TYPE_NAME *filter, uint32_t channel) { - return filter->filtered[channel]; -} - -// undef everything, so this file can be included multiple times -#undef MEDIAN_FILTER_TYPE -#undef MEDIAN_FILTER_DEPTH -#undef MEDIAN_FILTER_CHANNELS -#undef MEDIAN_FILTER_NAME -#undef _CONCAT -#undef CONCAT -#undef MF_TYPE -#undef MF_DEPTH -#undef MF_CHANNELS -#undef MF_NAME -#undef MEDIAN_FILTER_STRUCT_NAME -#undef MEDIAN_FILTER_TYPE_NAME -#undef MF_STRUCT_NAME -#undef MF_TYPE_NAME -#undef MEDIAN -#undef INIT -#undef GET -#undef PUT -#undef GETSINGLE - -/* @} */ \ No newline at end of file diff --git a/Apps/Inc/ReadCarCAN.h b/Apps/Inc/ReadCarCAN.h deleted file mode 100644 index a082bf312..000000000 --- a/Apps/Inc/ReadCarCAN.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file ReadCarCAN.h - * @brief - * - * @defgroup ReadCarCAN - * @addtogroup ReadCarCAN - * @{ - */ - -#ifndef __READ_CAR_CAN_H -#define __READ_CAR_CAN_H - -#include "os.h" -#include "common.h" -#include "Tasks.h" -#include "CANbus.h" - -/** - * Error types - */ -typedef enum{ - READCARCAN_ERR_NONE, - READCARCAN_ERR_CHARGE_DISABLE, // Received a charge disable msg - READCARCAN_ERR_MISSED_MSG, // Didn't receive a BPS charge msg in time - READCARCAN_ERR_DISABLE_CONTACTORS_MSG, // Ignition is turned to neither (off due to LV) or both at the same time (impossible) are on at - READCARCAN_ERR_BPS_TRIP // Received a BPS trip msg (0 or 1) -} ReadCarCAN_error_code_t; - -/** - * @brief Returns whether regen braking / charging is enabled or not - * @return Whether regen braking / charging is enabled or not -*/ -bool ChargeEnable_Get(void); - -#endif - - -/* @} */ diff --git a/Apps/Inc/ReadCarCan.h b/Apps/Inc/ReadCarCan.h new file mode 100644 index 000000000..8b56ee8dd --- /dev/null +++ b/Apps/Inc/ReadCarCan.h @@ -0,0 +1,42 @@ +/** + * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file ReadCarCAN.h + * @brief + * + * @defgroup ReadCarCAN + * @addtogroup ReadCarCAN + * @{ + */ + +#ifndef READ_CAR_CAN_H +#define READ_CAR_CAN_H + +#include "common.h" + +/** + * Task Prototype + */ +void TaskReadCarCan(void* p_arg); + +/** + * Error types + */ +typedef enum { + kReadCarCanErrNone, + kReadCarCanErrChargeDisable, // Received a charge disable msg + kReadCarCanErrMissedMsg, // Didn't receive a BPS charge msg in time + kReadCarCanErrDisableContactorsMsg, // Ignition is turned to neither (off + // due to LV) or both at the same time + // (impossible) are on at + kReadCarCanErrBpsTrip // Received a BPS trip msg (0 or 1) +} ReadCarCanErrorCode; + +/** + * @brief Returns whether regen braking / charging is enabled or not + * @return Whether regen braking / charging is enabled or not + */ +bool ChargeEnableGet(void); + +#endif + +/* @} */ diff --git a/Apps/Inc/ReadTritium.h b/Apps/Inc/ReadTritium.h old mode 100755 new mode 100644 index 0d1f76338..4c61bc945 --- a/Apps/Inc/ReadTritium.h +++ b/Apps/Inc/ReadTritium.h @@ -1,43 +1,44 @@ /* Copyright (c) 2021 UT Longhorn Racing Solar * @file ReadTritium.h - * @brief - * + * @brief + * * @defgroup ReadTritium * @addtogroup ReadTritium * @{ */ -#ifndef __READ_TRITIUM_H -#define __READ_TRITIUM_H - -#include "os.h" -#include "common.h" -#include "Tasks.h" +#ifndef READ_TRITIUM_H +#define READ_TRITIUM_H /** * Motor Error States - * Read messages from motor in ReadTritium and trigger appropriate error messages as needed based on bits - * + * Read messages from motor in ReadTritium and trigger appropriate error + * messages as needed based on bits + * */ -typedef enum{ - T_HARDWARE_OVER_CURRENT_ERR = (1<<0), - T_SOFTWARE_OVER_CURRENT_ERR = (1<<1), - T_DC_BUS_OVERVOLT_ERR = (1<<2), - T_HALL_SENSOR_ERR = (1<<3), - T_WATCHDOG_LAST_RESET_ERR = (1<<4), - T_CONFIG_READ_ERR = (1<<5), - T_UNDER_VOLTAGE_LOCKOUT_ERR = (1<<6), - T_DESAT_FAULT_ERR = (1<<7), - T_MOTOR_OVER_SPEED_ERR = (1<<8), - T_INIT_FAIL = (1<<9), //motor controller fails to restart or initialize - T_MOTOR_WATCHDOG_TRIP = (1 << 15), - T_NONE = 0x00, -} tritium_error_code_t; +typedef enum { + kHardwareOverCurrentErr = (1 << 0), + kSoftwareOverCurrentErr = (1 << 1), + kDcBusOverVoltErr = (1 << 2), + kHallSensorErr = (1 << 3), + kWatchdogLastResetErr = (1 << 4), + kConfigReadErr = (1 << 5), + kUnderVoltageLockoutErr = (1 << 6), + kDesatFaultErr = (1 << 7), + kMotorOverSpeedErr = (1 << 8), + kInitFail = (1 << 9), // motor controller fails to restart or initialize + kMotorWatchdogTrip = (1 << 15), + kNone = 0x00, +} TritiumErrorCode; -float Motor_RPM_Get(); -float Motor_Velocity_Get(); +/** + * Task Prototype + */ +void TaskReadTritium(void* p_arg); -#endif +float MotorRpmGet(); +float MotorVelocityGet(); +#endif /* @} */ diff --git a/Apps/Inc/SendCarCAN.h b/Apps/Inc/SendCarCAN.h deleted file mode 100644 index 99772bfb3..000000000 --- a/Apps/Inc/SendCarCAN.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __SENDCARCAN_H -#define __SENDCARCAN_H - -#include "CANbus.h" - -/** - * @brief Initialize SendCarCAN -*/ -void SendCarCAN_Init(); - -/** - * @brief Wrapper to put new message in the CAN queue -*/ -void SendCarCAN_Put(CANDATA_t message); - -/** - * @brief return the space left in SendCarCAN_Q for debug purposes -*/ -#ifdef DEBUG -uint8_t get_SendCarCAN_Q_Space(void); -#endif - -#endif \ No newline at end of file diff --git a/Apps/Inc/SendCarCan.h b/Apps/Inc/SendCarCan.h new file mode 100644 index 000000000..aedfabc8d --- /dev/null +++ b/Apps/Inc/SendCarCan.h @@ -0,0 +1,28 @@ +#ifndef SENDCARCAN_H +#define SENDCARCAN_H + +#include "CanBus.h" + +/** + * Task Prototype + */ +void TaskSendCarCan(void* p_arg); + +/** + * @brief Initialize SendCarCAN + */ +void SendCarCanInit(); + +/** + * @brief Wrapper to put new message in the CAN queue + */ +void SendCarCanPut(CanData message); + +/** + * @brief return the space left in SendCarCAN_Q for debug purposes + */ +#ifdef DEBUG +uint8_t GetSendCarCanQueueSpace(void); +#endif + +#endif \ No newline at end of file diff --git a/Apps/Inc/SendTritium.h b/Apps/Inc/SendTritium.h index 8791f3833..df675c8c6 100644 --- a/Apps/Inc/SendTritium.h +++ b/Apps/Inc/SendTritium.h @@ -1,102 +1,87 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file SendTritium.h - * @brief - * + * @brief + * * @defgroup SendTritium * @addtogroup SendTritium * @{ */ -#ifndef __SENDTRITIUM_H -#define __SENDTRITIUM_H +#ifndef SENDTRITIUM_H +#define SENDTRITIUM_H #include "common.h" -//#define SENDTRITIUM_PRINT_MES +#define SENDTRITIUM_PRINT_MES +#define SENDTRITIUM_EXPOSE_VARS -#define MOTOR_MSG_PERIOD 100 // in ms -#define FSM_PERIOD 100 // in ms -#define DEBOUNCE_PERIOD 2 // in units of FSM_PERIOD -#define MOTOR_MSG_COUNTER_THRESHOLD (MOTOR_MSG_PERIOD)/(FSM_PERIOD) +#define MOTOR_MSG_PERIOD 100 // in ms +#define FSM_PERIOD 100 // in ms +#define DEBOUNCE_PERIOD 2 // in units of FSM_PERIOD +#define MOTOR_MSG_COUNTER_THRESHOLD ((MOTOR_MSG_PERIOD) / (FSM_PERIOD)) -#define FOREACH_Gear(GEAR) \ - GEAR(FORWARD_GEAR), \ - GEAR(NEUTRAL_GEAR), \ - GEAR(REVERSE_GEAR), \ +#define FOREACH_GEAR(GEAR) \ + GEAR(kForwardGear), GEAR(kNeutralGear), GEAR(kReverseGear), -typedef enum GEAR_ENUM { - FOREACH_Gear(GENERATE_ENUM) - NUM_GEARS, -} Gear_t; +typedef enum { + FOREACH_GEAR(GENERATE_ENUM) kNumGears, +} Gear; // State Names -typedef enum{ - FORWARD_DRIVE, - NEUTRAL_DRIVE, - REVERSE_DRIVE, - RECORD_VELOCITY, - POWERED_CRUISE, - COASTING_CRUISE, - BRAKE_STATE, - ONEPEDAL, - ACCELERATE_CRUISE -} TritiumStateName_t; +typedef enum { + kForwardDrive, + kNeutralDrive, + kReverseDrive, + kRecordVelocity, + kPoweredCruise, + kCoastingCruise, + kBrakeState, + kOnePedal, + kAccelerateCruise +} TritiumStateName; // State Struct for FSM -typedef struct TritiumState{ - TritiumStateName_t name; +typedef struct TritiumState { + TritiumStateName name; void (*stateHandler)(void); void (*stateDecider)(void); -} TritiumState_t; +} TritiumState; -#ifdef SENDTRITIUM_EXPOSE_VARS -// Inputs -extern bool cruiseEnable; -extern bool cruiseSet; -extern bool onePedalEnable; -extern bool regenEnable; - -extern uint8_t brakePedalPercent; -extern uint8_t accelPedalPercent; - -extern Gear_t gear; - -extern TritiumState_t state; -extern float velocityObserved; -extern float cruiseVelSetpoint; -#endif - -// Getter functions for local variables in SendTritium.c -EXPOSE_GETTER(bool, cruiseEnable) -EXPOSE_GETTER(bool, cruiseSet) -EXPOSE_GETTER(bool, onePedalEnable) -EXPOSE_GETTER(bool, regenEnable) -EXPOSE_GETTER(uint8_t, brakePedalPercent) -EXPOSE_GETTER(uint8_t, accelPedalPercent) -EXPOSE_GETTER(Gear_t, gear) -EXPOSE_GETTER(TritiumState_t, state) -EXPOSE_GETTER(float, velocityObserved) -EXPOSE_GETTER(float, cruiseVelSetpoint) -EXPOSE_GETTER(float, currentSetpoint) -EXPOSE_GETTER(float, velocitySetpoint) +/** + * Task Prototype + */ +void TaskSendTritium(void* p_arg); + +// Getter functions for static variables +bool GetCruiseEnable(void); +bool GetCruiseSet(void); +bool GetOnePedalEnable(void); +bool GetRegenEnable(void); +uint8_t GetBrakePedalPercent(void); +uint8_t GetAccelPedalPercent(void); +Gear GetGear(void); +TritiumState GetState(void); +float GetVelocityObserved(void); +float GetCruiseVelSetpoint(void); +float GetCurrentSetpoint(void); +float GetVelocitySetpoint(void); -// Setter functions for local variables in SendTritium.c #ifdef SENDTRITIUM_EXPOSE_VARS -EXPOSE_SETTER(bool, cruiseEnable) -EXPOSE_SETTER(bool, cruiseSet) -EXPOSE_SETTER(bool, onePedalEnable) -EXPOSE_SETTER(bool, regenEnable) -EXPOSE_SETTER(uint8_t, brakePedalPercent) -EXPOSE_SETTER(uint8_t, accelPedalPercent) -EXPOSE_SETTER(Gear_t, gear) -EXPOSE_SETTER(TritiumState_t, state) -EXPOSE_SETTER(float, velocityObserved) -EXPOSE_SETTER(float, cruiseVelSetpoint) -EXPOSE_SETTER(float, currentSetpoint) -EXPOSE_SETTER(float, velocitySetpoint) +// Setter functions for static variables +void SetCruiseEnable(bool value); +void SetCruiseSet(bool value); +void SetOnePedalEnable(bool value); +void SetRegenEnable(bool value); +void SetBrakePedalPercent(uint8_t value); +void SetAccelPedalPercent(uint8_t value); +void SetGear(Gear value); +void SetState(TritiumState value); +void SetVelocityObserved(float value); +void SetCruiseVelSetpoint(float value); +void SetCurrentSetpoint(float value); +void SetVelocitySetpoint(float value); #endif #endif - /* @} */ diff --git a/Apps/Inc/Tasks.h b/Apps/Inc/Tasks.h index ad052d3d3..2f1267387 100644 --- a/Apps/Inc/Tasks.h +++ b/Apps/Inc/Tasks.h @@ -1,20 +1,19 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Tasks.h - * @brief - * + * @brief + * * @defgroup Tasks * @addtogroup Tasks * @{ */ - -#ifndef __TASKS_H -#define __TASKS_H +#ifndef TASKS_H +#define TASKS_H #include "common.h" -#include "os.h" #include "config.h" +#include "os.h" /** * Task initialization macro @@ -26,164 +25,152 @@ /** * Priority Definitions - */ -#define TASK_INIT_PRIO 2 -#define TASK_READ_TRITIUM_PRIO 3 -#define TASK_SEND_TRITIUM_PRIO 4 -#define TASK_READ_CAR_CAN_PRIO 5 -#define TASK_SEND_CAR_CAN_PRIO 6 -#define TASK_PUT_IOSTATE_PRIO 7 -#define TASK_UPDATE_DISPLAY_PRIO 8 -#define TASK_DEBUG_DUMP_PRIO 9 -#define TASK_COMMAND_LINE_PRIO 10 + */ +#define TASK_INIT_PRIO 2 +#define TASK_READ_TRITIUM_PRIO 3 +#define TASK_SEND_TRITIUM_PRIO 4 +#define TASK_READ_CAR_CAN_PRIO 5 +#define TASK_SEND_CAR_CAN_PRIO 6 +#define TASK_PUT_IOSTATE_PRIO 7 +#define TASK_UPDATE_DISPLAY_PRIO 8 +#define TASK_DEBUG_DUMP_PRIO 9 +#define TASK_COMMAND_LINE_PRIO 10 /** * Stack Sizes */ -#define DEFAULT_STACK_SIZE 256 -#define WATERMARK_STACK_LIMIT DEFAULT_STACK_SIZE/2 - -#define TASK_INIT_STACK_SIZE DEFAULT_STACK_SIZE -#define TASK_SEND_TRITIUM_STACK_SIZE DEFAULT_STACK_SIZE -#define TASK_READ_CAR_CAN_STACK_SIZE DEFAULT_STACK_SIZE -#define TASK_UPDATE_DISPLAY_STACK_SIZE DEFAULT_STACK_SIZE -#define TASK_READ_TRITIUM_STACK_SIZE DEFAULT_STACK_SIZE -#define TASK_SEND_CAR_CAN_STACK_SIZE DEFAULT_STACK_SIZE -#define TASK_DEBUG_DUMP_STACK_SIZE DEFAULT_STACK_SIZE -#define TASK_COMMAND_LINE_STACK_SIZE DEFAULT_STACK_SIZE +#define DEFAULT_STACK_SIZE 256 +#define WATERMARK_STACK_LIMIT (DEFAULT_STACK_SIZE / 2) + +#define TASK_INIT_STACK_SIZE DEFAULT_STACK_SIZE +#define TASK_SEND_TRITIUM_STACK_SIZE DEFAULT_STACK_SIZE +#define TASK_READ_CAR_CAN_STACK_SIZE DEFAULT_STACK_SIZE +#define TASK_UPDATE_DISPLAY_STACK_SIZE DEFAULT_STACK_SIZE +#define TASK_READ_TRITIUM_STACK_SIZE DEFAULT_STACK_SIZE +#define TASK_SEND_CAR_CAN_STACK_SIZE DEFAULT_STACK_SIZE +#define TASK_DEBUG_DUMP_STACK_SIZE DEFAULT_STACK_SIZE +#define TASK_COMMAND_LINE_STACK_SIZE DEFAULT_STACK_SIZE /** * Task error variable type -*/ -typedef uint16_t error_code_t; + */ +typedef uint16_t ErrorCode; /** * Task Prototypes */ -void Task_Init(void* p_arg); - -void Task_SendTritium(void* p_arg); - -void Task_ReadCarCAN(void* p_arg); - -void Task_UpdateDisplay(void* p_arg); - -void Task_ReadTritium(void* p_arg); - -void Task_SendCarCAN(void* p_arg); - -void Task_DebugDump(void *p_arg); - -void Task_CommandLine(void* p_arg); - - +void TaskInit(void* p_arg); +void TaskDebugDump(void* p_arg); +void TaskCommandLine(void* p_arg); /** * TCBs */ -extern OS_TCB Init_TCB; -extern OS_TCB SendTritium_TCB; -extern OS_TCB ReadCarCAN_TCB; -extern OS_TCB UpdateDisplay_TCB; -extern OS_TCB ReadTritium_TCB; -extern OS_TCB SendCarCAN_TCB; -extern OS_TCB DebugDump_TCB; -extern OS_TCB CommandLine_TCB; - +extern OS_TCB init_tcb; +extern OS_TCB send_tritium_tcb; +extern OS_TCB read_car_can_tcb; +extern OS_TCB update_display_tcb; +extern OS_TCB read_tritium_tcb; +extern OS_TCB send_car_can_tcb; +extern OS_TCB debug_dump_tcb; +extern OS_TCB command_line_tcb; /** * Stacks */ -extern CPU_STK Init_Stk[TASK_INIT_STACK_SIZE]; -extern CPU_STK SendTritium_Stk[TASK_SEND_TRITIUM_STACK_SIZE]; -extern CPU_STK ReadCarCAN_Stk[TASK_READ_CAR_CAN_STACK_SIZE]; -extern CPU_STK UpdateDisplay_Stk[TASK_UPDATE_DISPLAY_STACK_SIZE]; -extern CPU_STK ReadTritium_Stk[TASK_READ_TRITIUM_STACK_SIZE]; -extern CPU_STK SendCarCAN_Stk[TASK_SEND_CAR_CAN_STACK_SIZE]; -extern CPU_STK DebugDump_Stk[TASK_DEBUG_DUMP_STACK_SIZE]; -extern CPU_STK CommandLine_Stk[TASK_COMMAND_LINE_STACK_SIZE]; +extern CPU_STK init_stk[TASK_INIT_STACK_SIZE]; +extern CPU_STK send_tritium_stk[TASK_SEND_TRITIUM_STACK_SIZE]; +extern CPU_STK read_car_can_stk[TASK_READ_CAR_CAN_STACK_SIZE]; +extern CPU_STK update_display_stk[TASK_UPDATE_DISPLAY_STACK_SIZE]; +extern CPU_STK read_tritium_stk[TASK_READ_TRITIUM_STACK_SIZE]; +extern CPU_STK send_car_can_stk[TASK_SEND_CAR_CAN_STACK_SIZE]; +extern CPU_STK debug_dump_stk[TASK_DEBUG_DUMP_STACK_SIZE]; +extern CPU_STK command_line_stk[TASK_COMMAND_LINE_STACK_SIZE]; /** * Queues */ -extern OS_Q CANBus_MsgQ; +extern OS_Q can_bus_msg_q; /** * @brief Initialize the task switch hook * Registers the hook with the RTOS */ -void TaskSwHook_Init(void); +void TaskSwHookInit(void); /** * Task trace - * + * * Stores the last TASK_TRACE_LENGTH tasks that were run * The most recent task is at tasks[index], the one before at tasks[index-1], * wrapping back around at the beginnning - * + * */ #define TASK_TRACE_LENGTH 8 typedef struct { - OS_TCB *tasks[TASK_TRACE_LENGTH]; + OS_TCB* tasks[TASK_TRACE_LENGTH]; uint32_t index; -} task_trace_t; +} TaskTrace; -extern task_trace_t PrevTasks; +extern TaskTrace prev_tasks; // Store error codes that are set in task error assertion functions -extern error_code_t Error_ReadTritium; -extern error_code_t Error_ReadCarCAN; -extern error_code_t Error_UpdateDisplay; +extern ErrorCode error_read_tritium; +extern ErrorCode error_read_car_can; +extern ErrorCode error_update_display; /** * Error-handling option enums -*/ + */ // Scheduler lock parameter option for asserting a task error -typedef enum { - OPT_NO_LOCK_SCHED, - OPT_LOCK_SCHED -} error_scheduler_lock_opt_t; +typedef enum { kOptNoLockSched, kOptLockSched } ErrorSchedulerLockOpt; // Recoverable/nonrecoverable parameter option for asserting a task error -typedef enum { - OPT_RECOV, - OPT_NONRECOV -} error_recov_opt_t; +typedef enum { kOptRecov, kOptNonrecov } ErrorRecovOpt; /** - * @brief For use in error handling: opens array and motor precharge bypass contactor - * and turns on additional brakelight to signal that a critical error happened. -*/ + * @brief For use in error handling: opens array and motor precharge bypass + * contactor and turns on additional brakelight to signal that a critical error + * happened. + */ void EmergencyContactorOpen(); /** - * @brief Assert a task error by setting the location variable and optionally locking the scheduler, - * displaying a fault screen (if nonrecoverable), jumping to a callback function, and entering an infinite loop. - * Called by task-specific error-assertion functions that are also responsible for setting the error variable. + * @brief Assert a task error by setting the location variable and optionally + * locking the scheduler, displaying a fault screen (if nonrecoverable), jumping + * to a callback function, and entering an infinite loop. Called by + * task-specific error-assertion functions that are also responsible for setting + * the error variable. * @param errorCode the enum for the specific error that happened - * @param errorCallback a callback function to a handler for that specific error, - * @param lockSched whether or not to lock the scheduler to ensure the error is handled immediately - * @param nonrecoverable whether or not to kill the motor, display the fault screen, and enter an infinite while loop -*/ -void throwTaskError(error_code_t errorCode, callback_t errorCallback, error_scheduler_lock_opt_t lockSched, error_recov_opt_t nonrecoverable); + * @param errorCallback a callback function to a handler for that specific + * error, + * @param lockSched whether or not to lock the scheduler to ensure the error is + * handled immediately + * @param nonrecoverable whether or not to kill the motor, display the fault + * screen, and enter an infinite while loop + */ +void ThrowTaskError(ErrorCode error_code, Callback error_callback, + ErrorSchedulerLockOpt lock_sched, + ErrorRecovOpt nonrecoverable); /** * @brief Assert Error if OS function call fails * @param err OS Error that occurred */ -void _assertOSError (OS_ERR err); //TODO: This should be changed to enforce only enum usage +void AssertOsError(OS_ERR err); #if DEBUG == 1 -#define assertOSError(err) \ - if (err != OS_ERR_NONE) { \ - printf("Error asserted at %s, line %d: %d\n\r", __FILE__, __LINE__, err); \ - } \ - _assertOSError(err); +#define ASSERT_OS_ERROR(err) \ + if ((err) != OS_ERR_NONE) { \ + printf("Error asserted at %s, line %d: %d\n\r", __FILE__, __LINE__, \ + err); \ + } \ + AssertOsError(err); #else -#define assertOSError(err) _assertOSError(err); +#define ASSERT_OS_ERROR(err) AssertOsError(err); #endif #endif -/* @} */ \ No newline at end of file +/* @} */ diff --git a/Apps/Inc/UpdateDisplay.h b/Apps/Inc/UpdateDisplay.h index 12cb5ca99..81460bb15 100644 --- a/Apps/Inc/UpdateDisplay.h +++ b/Apps/Inc/UpdateDisplay.h @@ -2,140 +2,139 @@ * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file UpdateDisplay.h * @brief Function prototypes for the display application. - * + * * This contains function prototypes relevant to the UpdateDisplay * application. Call assertUpdateDisplayError after calling any of the * functions in this application. - * - * + * + * * @defgroup UpdateDisplay * @addtogroup UpdateDisplay * @{ */ -#ifndef __UPDATE_DISPLAY_H -#define __UPDATE_DISPLAY_H - -#include "os.h" -#include "common.h" -#include "Tasks.h" +#ifndef UPDATE_DISPLAY_H +#define UPDATE_DISPLAY_H #include "Display.h" -#include "Contactors.h" +#include "common.h" /** * Error types */ -typedef enum{ - UPDATEDISPLAY_ERR_NONE, - UPDATEDISPLAY_ERR_FIFO_PUT, // Error putting command in fifo - UPDATEDISPLAY_ERR_FIFO_POP, // Error popping command from fifo - UPDATEDISPLAY_ERR_PARSE_COMP, // Error parsing component/val in SetComponent - UPDATEDISPLAY_ERR_DRIVER // Driver call returned an error -} UpdateDisplayError_t; +typedef enum { + kUpdateDisplayErrNone, + kUpdateDisplayErrFifoPut, // Error putting command in fifo + kUpdateDisplayErrFifoPop, // Error popping command from fifo + kUpdateDisplayErrParseComp, // Error parsing component/val in SetComponent + kUpdateDisplayErrDriver // Driver call returned an error +} UpdateDisplayError; /** * For display elements with three states */ -typedef enum{ - STATE_0 =0, - STATE_1 =1, - STATE_2 =2 -} TriState_t; +typedef enum { kState0 = 0, kState1 = 1, kState2 = 2 } TriState; // For cruise control and regen -#define DISP_DISABLED STATE_0 -#define DISP_ENABLED STATE_1 // Able to be used -#define DISP_ACTIVE STATE_2 // Actively being used right now +#define DISP_DISABLED kState0 +#define DISP_ENABLED kState1 // Able to be used +#define DISP_ACTIVE kState2 // Actively being used right now // For gear changes -#define DISP_NEUTRAL STATE_0 -#define DISP_FORWARD STATE_1 -#define DISP_REVERSE STATE_2 +#define DISP_NEUTRAL kState0 +#define DISP_FORWARD kState1 +#define DISP_REVERSE kState2 + +/** + * Task Prototype + */ +void TaskUpdateDisplay(void* p_arg); /** * @brief Initializes UpdateDisplay application * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_Init(); +UpdateDisplayError UpdateDisplayInit(); /** * @brief Selects visible page on the display * @param page which page to select * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetPage(Page_t page); +UpdateDisplayError UpdateDisplaySetPage(Page page); /** * @brief Sets the state of charge value on the display * @param percent charge as a percent (0 digits of precision) * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetSOC(uint8_t percent); +UpdateDisplayError UpdateDisplaySetSoc(uint8_t percent); /** * @brief Sets the supplemental battery pack voltage value on the display * @param mv supplemental battery pack voltage in millivolts * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetSBPV(uint32_t mv); +UpdateDisplayError UpdateDisplaySetSbpv(uint32_t mv); /** * @brief Sets the velocity of the vehicle on the display - * @param mphTenths velocity of the vehicle in tenths of mph (1 digit of precision) + * @param mphTenths velocity of the vehicle in tenths of mph (1 digit of + * precision) * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetVelocity(uint32_t mphTenths); +UpdateDisplayError UpdateDisplaySetVelocity(uint32_t mph_tenths); /** * @brief Sets the accelerator slider value on the display * @param percent pressure on accelerator in percent * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetAccel(uint8_t percent); +UpdateDisplayError UpdateDisplaySetAccel(uint8_t percent); /** * @brief Sets the array indicator state on the display * @param state array contactor on (true) or off (false) * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetArray(bool state); +UpdateDisplayError UpdateDisplaySetArray(bool state); /** * @brief Sets the motor contactor indicator state on the display * @param state motor contactor on (true) or off (false) * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetMotor(bool state); +UpdateDisplayError UpdateDisplaySetMotor(bool state); /** * @brief Sets the gear selection state on the display * @param gear DISABLED=N, ENABLED=F, ACTIVE=R * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetGear(TriState_t gear); +UpdateDisplayError UpdateDisplaySetGear(TriState gear); /** * @brief Sets the regenerative braking indicator state on the display * @param state DISABLED, ENABLED, or ACTIVE * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetRegenState(TriState_t state); +UpdateDisplayError UpdateDisplaySetRegenState(TriState state); /** * @brief Sets the cruise control indicator state on the display * @param state DISABLED, ENABLED, or ACTIVE * @returns UpdateDisplayError_t */ -UpdateDisplayError_t UpdateDisplay_SetCruiseState(TriState_t state); +UpdateDisplayError UpdateDisplaySetCruiseState(TriState state); /** - * @brief Clears the display message queue and sets the message counter semaphore value to 0 + * @brief Clears the display message queue and sets the message counter + * semaphore value to 0 * @param none * @returns none -*/ -void UpdateDisplay_ClearQueue(void); + */ +void UpdateDisplayClearQueue(void); #endif /* @} */ diff --git a/Apps/Inc/common.h b/Apps/Inc/common.h index 3c5d7722e..df1f928aa 100644 --- a/Apps/Inc/common.h +++ b/Apps/Inc/common.h @@ -1,66 +1,43 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file common.h - * @brief - * + * @brief + * * @defgroup common * @addtogroup common * @{ */ -#ifndef __COMMON_H -#define __COMMON_H +#ifndef COMMON_H +#define COMMON_H #include -#include +#include #include +#include #include -#include #include -#include +#include + #include "config.h" /* Used for generating ENUMS */ #define GENERATE_ENUM(ENUM) ENUM #define GENERATE_STRING(STRING) #STRING -/** - * Used for creating getter functions (returns the value based on given inputs) - * - * GETTER is used for creating the function and EXPOSE_GETTER is used for creating the declaration in the header file - */ -#define GETTER(type, name) \ - type get_##name(void){ \ - return name; \ - } \ - -#define EXPOSE_GETTER(type, name) \ - type get_##name(void); \ +typedef void (*Callback)(void); -/** - * Used for creating setter functions (sets the value based on given inputs) - * - * SETTER is used for creating the function and EXPOSE_SETTER is used for creating the declaration in the header file - */ -#define SETTER(type, name) \ - void set_##name(type val){ \ - name = val; \ - } \ +void PrintFloat(char *str, float value); -#define EXPOSE_SETTER(type, name) \ - void set_##name(type val); \ - -typedef void (*callback_t)(void); - -void print_float(char *str, float f); +#define SEC_PER_MIN 60 /** * @brief Meters per second to rpm conversion * @param velocity_mps velocity in meters per second * @returns rpm -*/ -inline float mpsToRpm(float velocity_mps){ - return (velocity_mps * 60) / WHEEL_CIRCUMFERENCE; + */ +inline float MpsToRpm(float velocity_mps) { + return (float)((velocity_mps * SEC_PER_MIN) / WHEEL_CIRCUMFERENCE); } #endif diff --git a/Apps/Inc/fifo.h b/Apps/Inc/fifo.h index 2f821c91d..94ed8b18d 100644 --- a/Apps/Inc/fifo.h +++ b/Apps/Inc/fifo.h @@ -1,8 +1,8 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file fifo.h - * @brief - * + * @brief + * * @defgroup fifo * @addtogroup fifo * @{ @@ -10,10 +10,10 @@ /* * This file implements a fifo. - * - * In order to use it in another file, you must import it in + * + * In order to use it in another file, you must import it in * a particular way. - * + * * 1. Define your data type, like so * #define FIFO_TYPE int * 2. Define your fifo size, like so @@ -22,26 +22,28 @@ * #define FIFO_NAME my_fifo * 4. Import this file * #include "fifo.h" - * + * * This file includes some defaults, but they might not work for * your case! - * + * * Also, this file undef's everything at the end, so you can import * multiple times if you need. - * + * * If FIFO_NAME == my_fifo, then your new data structure will be * called my_fifo_t. - * + * * NOTE: importantly, this does not currently support usage from * header files. That is, all these types/functions are statically * declared, so there cannot be a non-static fifo at the moment. */ // The header guard only guard the import, -// since this file can be imported multiple times -#ifndef __FIFO_H -#define __FIFO_H +// since this file can be imported multiple times +#ifndef FIFO_H +#define FIFO_H #include +#include +#include #endif // The type of the fifo @@ -60,12 +62,12 @@ #endif // Utility definitions -#define _CONCAT(A, B) A ## B +#define _CONCAT(A, B) A##B #define CONCAT(A, B) _CONCAT(A, B) // Type names -#define FIFO_STRUCT_NAME CONCAT(FIFO_NAME, _s) -#define FIFO_TYPE_NAME CONCAT(FIFO_NAME, _t) +#define FIFO_STRUCT_NAME FIFO_NAME +#define FIFO_TYPE_NAME FIFO_NAME // The actual structure typedef struct FIFO_STRUCT_NAME { @@ -75,25 +77,24 @@ typedef struct FIFO_STRUCT_NAME { } FIFO_TYPE_NAME; // Define some names for our functions -#define IS_EMPTY CONCAT(FIFO_NAME, _is_empty) -#define IS_FULL CONCAT(FIFO_NAME, _is_full) -#define GET CONCAT(FIFO_NAME, _get) -#define PUT CONCAT(FIFO_NAME, _put) -#define NEW CONCAT(FIFO_NAME, _new) -#define PEEK CONCAT(FIFO_NAME, _peek) -#define POPBACK CONCAT(FIFO_NAME, _popback) -#define RENEW CONCAT(FIFO_NAME, _renew) +#define IS_EMPTY CONCAT(FIFO_NAME, IsEmpty) +#define IS_FULL CONCAT(FIFO_NAME, IsFull) +#define GET CONCAT(FIFO_NAME, Get) +#define PUT CONCAT(FIFO_NAME, Put) +#define NEW CONCAT(FIFO_NAME, New) +#define PEEK CONCAT(FIFO_NAME, Peek) +#define POPBACK CONCAT(FIFO_NAME, PopBack) +#define RENEW CONCAT(FIFO_NAME, Renew) /** * @brief Initialize a new fifo - * + * * If the type of the fifo is myfifo_t, then this function - * will be called myfifo_new(). - * + * will be called myfifoNew(). + * * @return an empty fifo */ -static inline FIFO_TYPE_NAME __attribute__((unused)) -NEW () { +static inline FIFO_TYPE_NAME __attribute__((unused)) NEW() { FIFO_TYPE_NAME fifo; memset(&fifo, 0, sizeof(fifo)); return fifo; @@ -101,62 +102,56 @@ NEW () { /** * @brief Initialize a fifo by reference. - * - * This is going to be faster than _new(). + * + * This is going to be faster than New(). * This does not erase all of the contents of the fifo, but * rather marks it as "empty". */ -static inline void __attribute__((unused)) -RENEW (FIFO_TYPE_NAME * fifo) { - if(fifo != NULL) { +static inline void __attribute__((unused)) RENEW(FIFO_TYPE_NAME *fifo) { + if (fifo != NULL) { fifo->get = fifo->put; } } /** * @brief Determine whether the fifo is empty. - * + * * If the type of the fifo is myfifo_t, then this function - * will be called myfifo_is_empty(). - * + * will be called myfifoIsEmpty(). + * * @param fifo A pointer to the fifo * @return true If empty * @return false If not empty */ -static bool -IS_EMPTY (FIFO_TYPE_NAME *fifo) { - return fifo->put == fifo->get; -} +static bool IS_EMPTY(FIFO_TYPE_NAME *fifo) { return fifo->put == fifo->get; } /** * @brief Determine whether the fifo is full. - * + * * If the type of the fifo is myfifo_t, then this function - * will be called myfifio_is_full(). - * + * will be called myfifioIsFull(). + * * @param fifo A pointer to the fifo * @return true If full * @return false If not full */ -static bool -IS_FULL (FIFO_TYPE_NAME *fifo) { +static bool IS_FULL(FIFO_TYPE_NAME *fifo) { return (fifo->put + 1) % FIFO_SIZE == fifo->get; } /** * @brief Get the next element from the fifo - * + * * If the type of the fifo is myfifo_t, then this function - * will be called myfifo_get(). - * + * will be called myfifoGet(). + * * @param fifo A pointer to the fifo * @param elem A pointer to an element to use for storage * @return true if successful * @return false if unsuccessful */ -static bool __attribute__((unused)) -GET (FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { - if(!IS_EMPTY(fifo)) { +static bool __attribute__((unused)) GET(FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { + if (!IS_EMPTY(fifo)) { *elem = fifo->buffer[fifo->get]; fifo->get = (fifo->get + 1) % FIFO_SIZE; return true; @@ -167,18 +162,17 @@ GET (FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { /** * @brief Put an element into the fifo - * + * * If the type of the fifo is myfifo_t, then this function - * will be called myfifo_put(). - * + * will be called myfifoPut(). + * * @param fifo A pointer to the fifo * @param elem The element to put * @return true if successful * @return false if unsuccessful */ -static bool __attribute__((unused)) -PUT (FIFO_TYPE_NAME *fifo, FIFO_TYPE elem) { - if(!IS_FULL(fifo)) { +static bool __attribute__((unused)) PUT(FIFO_TYPE_NAME *fifo, FIFO_TYPE elem) { + if (!IS_FULL(fifo)) { fifo->buffer[fifo->put] = elem; fifo->put = (fifo->put + 1) % FIFO_SIZE; return true; @@ -189,18 +183,18 @@ PUT (FIFO_TYPE_NAME *fifo, FIFO_TYPE elem) { /** * @brief Peek into the fifo - * + * * If the type of the fifo is myfifo_t, then this function - * will be called myfifo_peek(). - * + * will be called myfifoPeek(). + * * @param fifo A pointer to the fifo * @param elem A pointer to space where the next element will be put * @return true if successful * @return false if unsuccessful */ static bool __attribute__((unused)) -PEEK (FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { - if(!IS_EMPTY(fifo)) { +PEEK(FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { + if (!IS_EMPTY(fifo)) { *elem = fifo->buffer[fifo->get]; return true; } @@ -210,18 +204,18 @@ PEEK (FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { /** * @brief Take the last element of the fifo (most recent) - * + * * If the type of the fifo is myfifo_t, then this function - * will be called myfifo_popback(). - * + * will be called myfifoPopBack(). + * * @param fifo A pointer to the fifo * @param elem A pointer to space to put the element * @return true if successful * @return false if unsuccessful */ static bool __attribute__((unused)) -POPBACK (FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { - if(!IS_EMPTY(fifo)) { +POPBACK(FIFO_TYPE_NAME *fifo, FIFO_TYPE *elem) { + if (!IS_EMPTY(fifo)) { fifo->put = (fifo->put + FIFO_SIZE - 1) % FIFO_SIZE; *elem = fifo->buffer[fifo->put]; return true; diff --git a/Apps/Src/CommandLine.c b/Apps/Src/CommandLine.c index 369759342..ca6d18a25 100644 --- a/Apps/Src/CommandLine.c +++ b/Apps/Src/CommandLine.c @@ -2,348 +2,332 @@ #include #include #include -#include "os.h" -#include "Tasks.h" + #include "BSP_UART.h" -#include "CANbus.h" +#include "CanBus.h" #include "Contactors.h" #include "Minions.h" #include "Pedals.h" +#include "Tasks.h" +#include "os.h" + +#define MAX_BUFFER_SIZE 128 // defined from BSP_UART_Read function + +#define CAN_DIAG_ID 0x0582 -#define MAX_BUFFER_SIZE 128 // defined from BSP_UART_Read function +#define TAB 0x09 +#define LF 0x0A +#define FF 0x0C +#define CR 0x0D +#define SPACE 0x20 // Represents a command that the command line understands struct Command { - const char *name; - bool (*action)(void); + const char *name; + bool (*action)(void); }; -static bool cmd_help(void); - -static bool cmd_CANbus_Send(void); - -static bool cmd_CANbus_Read(void); - -static bool cmd_Contactors_Get(void); - -static bool cmd_Contactors_Set(void); - -static bool cmd_Minions_Read(void); - -static bool cmd_Minions_Write(void); - -static bool cmd_Pedals_Read(void); - - -const struct Command cmdline_commands[] = { - {.name = "help", .action = cmd_help}, - {.name = "CANbus_Send", .action = cmd_CANbus_Send}, - {.name = "CANbus_Read", .action = cmd_CANbus_Read}, - {.name = "Contactors_Get", .action = cmd_Contactors_Get}, - {.name = "Contactors_Set", .action = cmd_Contactors_Set}, - {.name = "Minions_Read", .action = cmd_Minions_Read}, - {.name = "Minions_Write", .action = cmd_Minions_Write}, - {.name = "Pedals_Read", .action = cmd_Pedals_Read}, - {.name = NULL, .action = NULL} -}; +static bool cmdHelp(void); +static bool cmdCanBusSend(void); +static bool cmdCanBusRead(void); +static bool cmdContactorsGet(void); +static bool cmdContactorsSet(void); +static bool cmdMinionsRead(void); +static bool cmdMinionsWrite(void); +static bool cmdPedalsRead(void); + +const struct Command kCmdlineCommands[] = { + {.name = "help", .action = cmdHelp}, + {.name = "CANbus_Send", .action = cmdCanBusSend}, + {.name = "CANbus_Read", .action = cmdCanBusRead}, + {.name = "Contactors_Get", .action = cmdContactorsGet}, + {.name = "Contactors_Set", .action = cmdContactorsSet}, + {.name = "Minions_Read", .action = cmdMinionsRead}, + {.name = "Minions_Write", .action = cmdMinionsWrite}, + {.name = "Pedals_Read", .action = cmdPedalsRead}, + {.name = NULL, .action = NULL}}; static char input[MAX_BUFFER_SIZE]; -char *save; // Save pointer for strtok_r +char *save; // Save pointer for strtok_r char *help = { - "LHRS Controls Command Line:\n\r" - " For help, enter [help]\n\r" - " Format is: cmd [param, ...]\n\r" - " Commands and their params are as follows:\n\r" - " CANbus_Send (non)blocking motor/car 'string' - Sends a CAN\n\r" - "message with the string data as is on the determined line\n\r" - " CANbus_Read (non)blocking motor/car - Reads a CAN message\n\r" - "on the detemined line\n\r" - " Contactors_Get array_c/array_p/motor_c - Gets the status of\n\r" - "determined contactor\n\r" - " Contactors_Set array_c/array_p/motor_c on/off (non)blocking -\n\r" - "Sets the determined contactor\n\r" - " Contactors_Enable array_c/array_p/motor_c - Enables the determined\n\r" - "contactor\n\r" - " Contactors_Disable array_c/array_p/motor_c - Disables the determined\n\r" - "contactor\n\r" - " Minions_Read 'input' - Reads the current status of the input\n\r" - " Minions_Write `output` on/off - Sets the current state of the output\n\r" - " Pedals_Read accel/brake - Reads the current status of the pedal\n\r" -}; - -static inline bool isWhiteSpace(char character){ - switch (character) { - case 0x09: - case 0x0A: - case 0x0C: - case 0x0D: - case 0x20: return true; - default: return false; - } + "LHRS Controls Command Line:\n\r" + " For help, enter [help]\n\r" + " Format is: cmd [param, ...]\n\r" + " Commands and their params are as follows:\n\r" + " CANbus_Send (non)blocking motor/car 'string' - Sends a CAN\n\r" + "message with the string data as is on the determined line\n\r" + " CANbus_Read (non)blocking motor/car - Reads a CAN message\n\r" + "on the detemined line\n\r" + " Contactors_Get array_c/array_p/motor_c - Gets the status of\n\r" + "determined contactor\n\r" + " Contactors_Set array_c/array_p/motor_c on/off (non)blocking -\n\r" + "Sets the determined contactor\n\r" + " Contactors_Enable array_c/array_p/motor_c - Enables the determined\n\r" + "contactor\n\r" + " Contactors_Disable array_c/array_p/motor_c - Disables the " + "determined\n\r" + "contactor\n\r" + " Minions_Read 'input' - Reads the current status of the input\n\r" + " Minions_Write `output` on/off - Sets the current state of the " + "output\n\r" + " Pedals_Read accel/brake - Reads the current status of the pedal\n\r"}; + +static inline bool isWhiteSpace(char character) { + switch (character) { + case TAB: + case LF: + case FF: + case CR: + case SPACE: + return true; + default: + return false; + } } static bool executeCommand(char *input) { - // The first word in the input should be a valid command - char *command = strtok_r(input, " ", &save); - // Iterate through all valid commands and check if the input matches (exits if the action is NULL (acts as a sentinal)) - for (int i=0; cmdline_commands[i].action; i++) { - if (!strcmp(command, cmdline_commands[i].name)) { - return cmdline_commands[i].action(); // Execute the command - } - } - return false; // Didn't find a valid command! + // The first word in the input should be a valid command + char *command = strtok_r(input, " ", &save); + // Iterate through all valid commands and check if the input matches (exits + // if the action is NULL (acts as a sentinal)) + for (int i = 0; kCmdlineCommands[i].action; i++) { + if (!strcmp(command, kCmdlineCommands[i].name)) { + return kCmdlineCommands[i].action(); // Execute the command + } + } + return false; // Didn't find a valid command! } // *********** Command line (shell) ************ -void Task_CommandLine(void* p_arg) { - OS_ERR err; - - // output welcome/help screen - printf(help); - - while(1){ - printf("> "); - BSP_UART_Read(UART_2, input); - printf("\n\r"); - - if (!executeCommand(input)) { // If command failed, error - printf("Bad cmd. Please try again\n\r"); - } - } +void TaskCommandLine(void *p_arg) { + OS_ERR err = 0; + + // output welcome/help screen + printf("%s", help); + + while (1) { + printf("> "); + BspUartRead(kUart2, input); + printf("\n\r"); + + if (!executeCommand(input)) { // If command failed, error + printf("Bad cmd. Please try again\n\r"); + } + } // Delay of 1 seconds OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_HMSM_STRICT, &err); - if (err != OS_ERR_NONE){ - assertOSError(err); + if (err != OS_ERR_NONE) { + ASSERT_OS_ERROR(err); } + +#ifdef MOCKING + break; +#endif } // Function Implementations // ------------------------------------------------------------------------ -static inline bool cmd_help(void) { - printf(help); - return true; +static inline bool cmdHelp(void) { + printf("%s", help); + return true; } -/* This has not been tested and not sure if this implementation is correct (not sure -if we want to just transmit string data from serial) */ -static bool cmd_CANbus_Send(void){ - char *data = strtok_r(NULL, " ", &save); - CANDATA_t msg = {.ID=0x0582, .idx=0}; // this would change in the future (don't assume char as data) - for(int i = 0; i < 8 && i < strlen(data); i++){ - msg.data[i] = data[i]; - } - - char *blockInput = strtok_r(NULL, " ", &save); - bool blocking; - if(strcmp(blockInput, "blocking") == 0){ - blocking = CAN_BLOCKING; - } - else if(strcmp(blockInput, "nonblocking") == 0){ - blocking = CAN_NON_BLOCKING; - } - else{ - return false; - } - - char *busInput = strtok_r(NULL, " ", &save); - CAN_t bus; - if(strcmp(busInput, "motor") == 0){ - bus = CAN_1; - } - else if(strcmp(busInput, "car") == 0){ - bus = CAN_3; - } - else{ - return false; - } - - if(CANbus_Send(msg, blocking, bus)){ - printf("msg sent on %s (%s)\n\r", "can", blockInput); - }else{ - printf("msg sent failed\n\r"); - } - return true; +/* This has not been tested and not sure if this implementation is correct (not +sure if we want to just transmit string data from serial) */ +static bool cmdCanBusSend(void) { + char *data = strtok_r(NULL, " ", &save); + CanData msg = { + .id = CAN_DIAG_ID, + .idx = + 0}; // this would change in the future (don't assume char as data) + for (int i = 0; i < BSP_CAN_DATA_LENGTH && i < strlen(data); i++) { + msg.data[i] = data[i]; + } + + char *block_input = strtok_r(NULL, " ", &save); + bool blocking = false; + if (strcmp(block_input, "blocking") == 0) { + blocking = CAN_BLOCKING; + } else if (strcmp(block_input, "nonblocking") == 0) { + blocking = CAN_NON_BLOCKING; + } else { + return false; + } + + char *bus_input = strtok_r(NULL, " ", &save); + Can bus = 0; + if (strcmp(bus_input, "motor") == 0) { + bus = kCan1; + } else if (strcmp(bus_input, "car") == 0) { + bus = kCan3; + } else { + return false; + } + + if (CanBusSend(msg, blocking, bus)) { + printf("msg sent on %s (%s)\n\r", "can", block_input); + } else { + printf("msg sent failed\n\r"); + } + return true; } -static bool cmd_CANbus_Read(void){ - CANDATA_t msg; - - char *blockInput = strtok_r(NULL, " ", &save); - bool blocking; - if(strcmp(blockInput, "blocking") == 0){ - blocking = CAN_BLOCKING; - } - else if(strcmp(blockInput, "nonblocking") == 0){ - blocking = CAN_NON_BLOCKING; - } - else{ - return false; - } - - char *busInput = strtok_r(NULL, " ", &save); - CAN_t bus; - if(strcmp(busInput, "motor") == 0){ - bus = CAN_1; - } - else if(strcmp(busInput, "car") == 0){ - bus = CAN_3; - } - else{ - return false; - } - - if(CANbus_Read(&msg, blocking, bus) == SUCCESS){ - printf("msg received on %s (%s)\n\r", busInput, blockInput); - printf("ID: %d, Data: ", msg.ID); - for(int i = 0; i < 8; i++){ - printf("[%d] %x \n\r", i, msg.data[i]); - } - }else{ - printf("read failed on %s (%s)\n\r", busInput, blockInput); - } - return true; +static bool cmdCanBusRead(void) { + CanData msg; + + char *block_input = strtok_r(NULL, " ", &save); + bool blocking = false; + if (strcmp(block_input, "blocking") == 0) { + blocking = CAN_BLOCKING; + } else if (strcmp(block_input, "nonblocking") == 0) { + blocking = CAN_NON_BLOCKING; + } else { + return false; + } + + char *bus_input = strtok_r(NULL, " ", &save); + Can bus = 0; + if (strcmp(bus_input, "motor") == 0) { + bus = kCan1; + } else if (strcmp(bus_input, "car") == 0) { + bus = kCan3; + } else { + return false; + } + + if (CanBusRead(&msg, blocking, bus) == SUCCESS) { + printf("msg received on %s (%s)\n\r", bus_input, block_input); + printf("ID: %d, Data: ", msg.id); + for (int i = 0; i < CAN_DIAG_ID; i++) { + printf("[%d] %x \n\r", i, msg.data[i]); + } + } else { + printf("read failed on %s (%s)\n\r", bus_input, block_input); + } + return true; } -static bool cmd_Contactors_Get(void){ - char *contactorInput = strtok_r(NULL, " ", &save); - contactor_t contactor; - if(strcmp(contactorInput, "array_p") == 0){ - contactor = ARRAY_PRECHARGE_BYPASS_CONTACTOR; - } - else if(strcmp(contactorInput, "motor_p") == 0){ - contactor = MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR; - } - else{ - return false; - } - - printf("%s state: %s\n\r", contactorInput, Contactors_Get(contactor) == ON ? "on" : "off"); - return true; +static bool cmdContactorsGet(void) { + char *contactor_input = strtok_r(NULL, " ", &save); + Contactor contactor = 0; + if (strcmp(contactor_input, "array_p") == 0) { + contactor = kArrayPrechargeBypassContactor; + } else if (strcmp(contactor_input, "motor_p") == 0) { + contactor = kMotorControllerPrechargeBypassContactor; + } else { + return false; + } + + printf("%s state: %s\n\r", contactor_input, + ContactorsGet(contactor) == ON ? "on" : "off"); + return true; } -static bool cmd_Contactors_Set(void){ - char *contactorInput = strtok_r(NULL, " ", &save); - contactor_t contactor; - if(strcmp(contactorInput, "array_p") == 0){ - contactor = ARRAY_PRECHARGE_BYPASS_CONTACTOR; - } - else if(strcmp(contactorInput, "motor_p") == 0){ - contactor = MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR; - } - else{ - return false; - } - - char *stateInput = strtok_r(NULL, " ", &save); - bool state; - if(strcmp(stateInput, "on") == 0){ - state = true; - } - else if(strcmp(stateInput, "off") == 0){ - state = false; - } - else{ - return false; - } - - char *blockingInput = strtok_r(NULL, " ", &save); - bool blocking; - if(strcmp(blockingInput, "blocking") == 0){ - blocking = true; - } - else if(strcmp(blockingInput, "nonblocking") == 0){ - blocking = false; - } - else{ - return false; - } - - if(Contactors_Set(contactor, state, blocking)){ - printf("%s set to %s (%s)\n\r", contactorInput, stateInput, blockingInput); - }else{ - printf("set failed\n\r"); - } - return true; +static bool cmdContactorsSet(void) { + char *contactor_input = strtok_r(NULL, " ", &save); + Contactor contactor = 0; + if (strcmp(contactor_input, "array_p") == 0) { + contactor = kArrayPrechargeBypassContactor; + } else if (strcmp(contactor_input, "motor_p") == 0) { + contactor = kMotorControllerPrechargeBypassContactor; + } else { + return false; + } + + char *state_input = strtok_r(NULL, " ", &save); + bool state = false; + if (strcmp(state_input, "on") == 0) { + state = true; + } else if (strcmp(state_input, "off") == 0) { + state = false; + } else { + return false; + } + + char *blocking_input = strtok_r(NULL, " ", &save); + bool blocking = false; + if (strcmp(blocking_input, "blocking") == 0) { + blocking = true; + } else if (strcmp(blocking_input, "nonblocking") == 0) { + blocking = false; + } else { + return false; + } + + if (ContactorsSet(contactor, state, blocking)) { + printf("%s set to %s (%s)\n\r", contactor_input, state_input, + blocking_input); + } else { + printf("set failed\n\r"); + } + return true; } -static bool cmd_Minions_Read(void){ - char *pinInput = strtok_r(NULL, " ", &save); - pin_t pin; - if(strcmp(pinInput, "ign_1") == 0){ - pin = IGN_1; - } - else if(strcmp(pinInput, "ign_2") == 0){ - pin = IGN_2; - } - else if(strcmp(pinInput, "regen_sw") == 0){ - pin = REGEN_SW; - } - else if(strcmp(pinInput, "for_sw") == 0){ - pin = FOR_SW; - } - else if(strcmp(pinInput, "rev_sw") == 0){ - pin = REV_SW; - } - else if(strcmp(pinInput, "cruz_en") == 0){ - pin = CRUZ_EN; - } - else if(strcmp(pinInput, "cruz_st") == 0){ - pin = CRUZ_ST; - } - else if(strcmp(pinInput, "brakelight") == 0){ - pin = BRAKELIGHT; - } - else{ - return false; - } - - printf("%s is %s\n\r", pinInput, Minions_Read(pin) ? "on" : "off"); - return true; +static bool cmdMinionsRead(void) { + char *pin_input = strtok_r(NULL, " ", &save); + Pin pin = 0; + if (strcmp(pin_input, "ign_1") == 0) { + pin = kIgn1; + } else if (strcmp(pin_input, "ign_2") == 0) { + pin = kIgn2; + } else if (strcmp(pin_input, "kRegenSw") == 0) { + pin = kRegenSw; + } else if (strcmp(pin_input, "kForSw") == 0) { + pin = kForSw; + } else if (strcmp(pin_input, "kRevSw") == 0) { + pin = kRevSw; + } else if (strcmp(pin_input, "kCruzEn") == 0) { + pin = kCruzEn; + } else if (strcmp(pin_input, "kCruzSt") == 0) { + pin = kCruzSt; + } else if (strcmp(pin_input, "brakelight") == 0) { + pin = kBrakeLight; + } else { + return false; + } + + printf("%s is %s\n\r", pin_input, MinionsRead(pin) ? "on" : "off"); + return true; } -static bool cmd_Minions_Write(void){ - char *pinInput = strtok_r(NULL, " ", &save); - pin_t pin; - if(strcmp(pinInput, "brakelight") == 0){ - pin = BRAKELIGHT; - } - else{ - return false; - } - - char *stateInput = strtok_r(NULL, " ", &save); - bool state; - if(strcmp(stateInput, "on") == 0){ - state = true; - } - else if(strcmp(stateInput, "off") == 0){ - state = false; - } - else{ - return false; - } - - Minions_Write(pin, state); - printf("%s set to %s\n\r", pinInput, stateInput); - return true; +static bool cmdMinionsWrite(void) { + char *pin_input = strtok_r(NULL, " ", &save); + Pin pin = 0; + if (strcmp(pin_input, "brakelight") == 0) { + pin = kBrakeLight; + } else { + return false; + } + + char *state_input = strtok_r(NULL, " ", &save); + bool state = false; + if (strcmp(state_input, "on") == 0) { + state = true; + } else if (strcmp(state_input, "off") == 0) { + state = false; + } else { + return false; + } + + MinionsWrite(pin, state); + printf("%s set to %s\n\r", pin_input, state_input); + return true; } -static bool cmd_Pedals_Read(void){ - char *pedalInput = strtok_r(NULL, " ", &save); - pedal_t pedal; - if(strcmp(pedalInput, "accel") == 0){ - pedal = ACCELERATOR; - } - else if(strcmp(pedalInput, "brake") == 0){ - pedal = BRAKE; - } - else{ - return false; - } - - printf("%s: %d\n\r", pedalInput, Pedals_Read(pedal)); - return true; +static bool cmdPedalsRead(void) { + char *pedal_input = strtok_r(NULL, " ", &save); + Pedal pedal = 0; + if (strcmp(pedal_input, "accel") == 0) { + pedal = kAccelerator; + } else if (strcmp(pedal_input, "brake") == 0) { + pedal = kBrake; + } else { + return false; + } + + printf("%s: %d\n\r", pedal_input, PedalsRead(pedal)); + return true; } diff --git a/Apps/Src/DebugDump.c b/Apps/Src/DebugDump.c index 15cd48e98..0aef36c7b 100644 --- a/Apps/Src/DebugDump.c +++ b/Apps/Src/DebugDump.c @@ -1,27 +1,18 @@ -#include "os.h" +#include + +#include "CanBus.h" +#include "Contactors.h" +#include "Minions.h" +#include "Pedals.h" +#include "SendTritium.h" #include "Tasks.h" #include "bsp.h" -#include "CANbus.h" -#include "Pedals.h" -#include "Minions.h" -#include "Contactors.h" #include "common.h" -#include -#include "Tasks.h" -#include "SendTritium.h" - - -static const char *MINIONPIN_STRING[] = { - FOREACH_PIN(GENERATE_STRING) -}; - -static const char *CONTACTOR_STRING[] = { - FOREACH_contactor(GENERATE_STRING) -}; +#include "os.h" -static const char *GEAR_STRING[] = { - FOREACH_Gear(GENERATE_STRING) -}; +static const char *minionpin_string[] = {FOREACH_PIN(GENERATE_STRING)}; +static const char *contactor_string[] = {FOREACH_CONTACTOR(GENERATE_STRING)}; +static const char *gear_string[] = {FOREACH_GEAR(GENERATE_STRING)}; // Need to keep this in sync with Task.h /*----------------------------------------------*/ @@ -29,47 +20,53 @@ static const char *GEAR_STRING[] = { /*----------------------------------------------*/ -void Task_DebugDump(void* p_arg) { - OS_ERR err; - - while(1){ +void TaskDebugDump(void *p_arg) { + OS_ERR err = 0; + while (1) { // Get pedal information - int8_t accelPedal = Pedals_Read(ACCELERATOR); - printf("ACCELERATOR: %d\n\r", accelPedal); + int8_t accel_pedal = PedalsRead(kAccelerator); + printf("kAccelerator: %d\n\r", accel_pedal); - int8_t brakePedal = Pedals_Read(BRAKE); - printf("BRAKE: %d\n\r", brakePedal); + int8_t brake_pedal = PedalsRead(kBrake); + printf("kBrake: %d\n\r", brake_pedal); // Get minion information - for(pin_t pin = 0; pin < NUM_PINS; pin++){ - bool pinState = Minions_Read(pin); - // Ignition pins are negative logic, special-case them - printf("%s: %s\n\r", MINIONPIN_STRING[pin], pinState ^ (pin == IGN_1 || pin == IGN_2) ? "on" : "off"); + for (Pin pin = 0; pin < kNumPins; pin++) { + bool pin_state = MinionsRead(pin); + printf("%s: %s\n\r", minionpin_string[pin], + pin_state ? "on" : "off"); } // Get contactor info - for(contactor_t contactor = 0; contactor < NUM_CONTACTORS; contactor++){ - bool contactorState = Contactors_Get(contactor) == ON ? true : false; - printf("%s: %s\n\r", CONTACTOR_STRING[contactor], contactorState ? "on" : "off"); - } + for (Contactor contactor = 0; contactor < kNumContactors; contactor++) { + bool contactor_state = + ContactorsGet(contactor) == ON ? true : false; + printf("%s: %s\n\r", contactor_string[contactor], + contactor_state ? "on" : "off"); + } // Send Tritium variables - printf("Cruise Enable: %s\n\r", get_cruiseEnable() ? "true" : "false"); - printf("Cruise Set: %s\n\r", get_cruiseSet() ? "true" : "false"); - printf("One Pedal Enable: %s\n\r", get_onePedalEnable() ? "true" : "false"); - printf("Regen Enable: %s\n\r", get_regenEnable() ? "true" : "false"); - printf("Pedal Brake Percent: %d\n\r", get_brakePedalPercent()); - printf("Pedal Accel Percent: %d\n\r", get_accelPedalPercent()); - printf("Current Gear: %s\n\r", GEAR_STRING[get_gear()]); - print_float("Current Setpoint: ", get_currentSetpoint()); + printf("Cruise Enable: %s\n\r", GetCruiseEnable() ? "true" : "false"); + printf("Cruise Set: %s\n\r", GetCruiseSet() ? "true" : "false"); + printf("One Pedal Enable: %s\n\r", + GetOnePedalEnable() ? "true" : "false"); + printf("Regen Enable: %s\n\r", GetRegenEnable() ? "true" : "false"); + printf("Pedal Brake Percent: %d\n\r", GetBrakePedalPercent()); + printf("Pedal Accel Percent: %d\n\r", GetAccelPedalPercent()); + printf("Current Gear: %s\n\r", gear_string[GetGear()]); + PrintFloat("Current Setpoint: ", GetCurrentSetpoint()); printf("\n\r"); // Delay of 5 seconds - OSTimeDlyHMSM(0, 0, 5, 0, OS_OPT_TIME_HMSM_STRICT, &err); - if (err != OS_ERR_NONE){ - assertOSError(err); + OSTimeDlyHMSM(0, 0, 5, 0, OS_OPT_TIME_HMSM_STRICT, &err); // NOLINT + if (err != OS_ERR_NONE) { + ASSERT_OS_ERROR(err); } + +#ifdef MOCKING + break; +#endif } } \ No newline at end of file diff --git a/Apps/Src/PedalToPercent.c b/Apps/Src/PedalToPercent.c index 87646432a..53a87970a 100644 --- a/Apps/Src/PedalToPercent.c +++ b/Apps/Src/PedalToPercent.c @@ -1,111 +1,20 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file PedalToPercent.c - * @brief - * + * @brief + * */ /* Converts accelerator pedal percentage to a decimal */ -const float pedalToPercent[] = { - 0.00f, - 0.01f, - 0.02f, - 0.03f, - 0.04f, - 0.05f, - 0.06f, - 0.07f, - 0.08f, - 0.09f, - 0.1f, - 0.11f, - 0.12f, - 0.13f, - 0.14f, - 0.15f, - 0.16f, - 0.17f, - 0.18f, - 0.19f, - 0.2f, - 0.21f, - 0.22f, - 0.23f, - 0.24f, - 0.25f, - 0.26f, - 0.27f, - 0.28f, - 0.29f, - 0.3f, - 0.31f, - 0.32f, - 0.33f, - 0.34f, - 0.35f, - 0.36f, - 0.37f, - 0.38f, - 0.39f, - 0.4f, - 0.41f, - 0.42f, - 0.43f, - 0.44f, - 0.45f, - 0.46f, - 0.47f, - 0.48f, - 0.49f, - 0.5f, - 0.51f, - 0.52f, - 0.53f, - 0.54f, - 0.55f, - 0.56f, - 0.57f, - 0.58f, - 0.59f, - 0.6f, - 0.61f, - 0.62f, - 0.63f, - 0.64f, - 0.65f, - 0.66f, - 0.67f, - 0.68f, - 0.69f, - 0.7f, - 0.71f, - 0.72f, - 0.73f, - 0.74f, - 0.75f, - 0.76f, - 0.77f, - 0.78f, - 0.79f, - 0.8f, - 0.81f, - 0.82f, - 0.83f, - 0.84f, - 0.85f, - 0.86f, - 0.87f, - 0.88f, - 0.89f, - 0.9f, - 0.91f, - 0.92f, - 0.93f, - 0.94f, - 0.95f, - 0.96f, - 0.97f, - 0.98f, - 0.99f, - 1.0f, +const float kPedalToPercent[] = { + 0.00F, 0.01F, 0.02F, 0.03F, 0.04F, 0.05F, 0.06F, 0.07F, 0.08F, 0.09F, 0.1F, + 0.11F, 0.12F, 0.13F, 0.14F, 0.15F, 0.16F, 0.17F, 0.18F, 0.19F, 0.2F, 0.21F, + 0.22F, 0.23F, 0.24F, 0.25F, 0.26F, 0.27F, 0.28F, 0.29F, 0.3F, 0.31F, 0.32F, + 0.33F, 0.34F, 0.35F, 0.36F, 0.37F, 0.38F, 0.39F, 0.4F, 0.41F, 0.42F, 0.43F, + 0.44F, 0.45F, 0.46F, 0.47F, 0.48F, 0.49F, 0.5F, 0.51F, 0.52F, 0.53F, 0.54F, + 0.55F, 0.56F, 0.57F, 0.58F, 0.59F, 0.6F, 0.61F, 0.62F, 0.63F, 0.64F, 0.65F, + 0.66F, 0.67F, 0.68F, 0.69F, 0.7F, 0.71F, 0.72F, 0.73F, 0.74F, 0.75F, 0.76F, + 0.77F, 0.78F, 0.79F, 0.8F, 0.81F, 0.82F, 0.83F, 0.84F, 0.85F, 0.86F, 0.87F, + 0.88F, 0.89F, 0.9F, 0.91F, 0.92F, 0.93F, 0.94F, 0.95F, 0.96F, 0.97F, 0.98F, + 0.99F, 1.0F, }; diff --git a/Apps/Src/ReadCarCAN.c b/Apps/Src/ReadCarCAN.c deleted file mode 100644 index 64897dd4b..000000000 --- a/Apps/Src/ReadCarCAN.c +++ /dev/null @@ -1,489 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file ReadCarCAN.c - * @brief - * - */ - -#include "ReadCarCAN.h" -#include "UpdateDisplay.h" -#include "Contactors.h" -#include "Minions.h" -#include "os.h" -#include "os_cfg_app.h" -#include "Display.h" - -// Length of the array and motor PBC saturation buffers -#define SAT_BUF_LENGTH 5 - -// The Array/Motor Controller Saturation Threshold is used to determine if Controls has -// received a sufficient number of BPS's HV Array/Plus-Minus Enable Messages. -// BPS Array and Plus/Minus saturation threshold is halfway between 0 and max saturation value. -#define ARRAY_SATURATION_THRESHOLD (((SAT_BUF_LENGTH + 1) * SAT_BUF_LENGTH) / 4) -#define PLUS_MINUS_SATURATION_THRESHOLD (((SAT_BUF_LENGTH + 1) * SAT_BUF_LENGTH) / 4) - -// Timer delay constants -#define CAN_WATCH_TMR_DLY_MS 500u // 500 ms -#define CAN_WATCH_TMR_DLY_TMR_TS ((CAN_WATCH_TMR_DLY_MS * OS_CFG_TMR_TASK_RATE_HZ) / (1000u)) // 1000 for ms -> s conversion - -// Precharge Delay times in milliseconds -#define PRECHARGE_PLUS_MINUS_DELAY 100u // 100 ms, as this the smallest time delay that the RTOS can work with -#define PRECHARGE_ARRAY_DELAY 100u // 100 ms -#define ARRAY_PRECHARGE_BYPASS_DLY_TMR_TS ((PRECHARGE_ARRAY_DELAY * OS_CFG_TMR_TASK_RATE_HZ) / (1000u)) -#define MOTOR_CONTROLLER_PRECHARGE_BYPASS_DLY_TMR_TS ((PRECHARGE_PLUS_MINUS_DELAY * OS_CFG_TMR_TASK_RATE_HZ) / (1000u)) - -// High Voltage BPS Contactor bit mapping -#define HV_ARRAY_CONTACTOR_BIT 1 //0b001 -#define HV_MINUS_CONTACTOR_BIT 2 //0b010 -#define HV_PLUS_CONTACTOR_BIT 4 //0b100 - -// Saturation messages -#define DISABLE_SATURATION_MSG -1 -#define ENABLE_SATURATION_MSG 1 - -// State of Charge scalar to scale it to correct fixed point -#define SOC_SCALER 1000000 - -// CAN watchdog timer variable -static OS_TMR canWatchTimer; - -// Array precharge bypass contactor delay timer variable -static OS_TMR arrayPBCDlyTimer; - -// Motor controller precharge bypass contactor delay timer variable -static OS_TMR motorControllerPBCDlyTimer; - -// NOTE: This should not be written to anywhere other than ReadCarCAN. If the need arises, a mutex to protect it must be added. -// Indicates whether or not regenerative braking / charging is enabled. -static bool chargeEnable = false; // Enable (High message) of BPS high voltage (HV) array contactor - -// BPS HV Array saturation buffer variables -static int8_t HVArrayChargeMsgBuffer[SAT_BUF_LENGTH]; -static int8_t HVArrayMsgSaturation = 0; -static uint8_t HVArrayOldestMsgIdx = 0; - -// BPS HV Motor Controller saturation buffer variables -static int8_t HVPlusMinusChargeMsgBuffer[SAT_BUF_LENGTH]; -static int8_t HVPlusMinusChargeMsgSaturation = 0; -static uint8_t HVPlusMinusMotorOldestMsgIdx = 0; - -// Array ignition (IGN_1) and Motor Controller ignition (IGN_2) pin status -static bool arrIgnStatus = false; -static bool mcIgnStatus = false; - -// Boolean to indicate precharge status for Array Precharge Bypass Contactor (PBC) and Motor Controller PBC -static bool arrPBCComplete = false; -static bool mcPBCComplete = false; - -// State of Charge (SOC) and supplemental battery pack voltage (SBPV) value intialization -static uint8_t SOC = 0; -static uint32_t SBPV = 0; - -// Error assertion function prototype -static void assertReadCarCANError(ReadCarCAN_error_code_t rcc_err); - -// Getter function for charge enable, indicating that battery charging is allowed -bool ChargeEnable_Get(void){ - return chargeEnable; -} - -/** - * @brief Nested function as the same function needs to be executed however the timer requires different parameters - * @param p_tmr pointer to the timer that calls this function, passed by timer - * @param p_arg pointer to the argument passed by timer -*/ -static void callbackCANWatchdog(void *p_tmr, void *p_arg){ - assertReadCarCANError(READCARCAN_ERR_MISSED_MSG); -} - -/** - * @brief Callback function for the precharge delay timer. Waits for precharge and then sets arrPBCComplete to true. - * @param p_tmr pointer to the timer that calls this function, passed by timer - * @param p_arg pointer to the argument passed by timer -*/ -static void setArrayBypassPrechargeComplete(void *p_tmr, void *p_arg){ - arrPBCComplete = true; -}; - -/** - * @brief Callback function for the precharge delay timer. Waits for precharge and then sets mcPBCComplete to true. - * @param p_tmr pointer to the timer that calls this function, passed by timer - * @param p_arg pointer to the argument passed by timer -*/ -static void setMotorControllerBypassPrechargeComplete(void *p_tmr, void *p_arg){ - mcPBCComplete = true; -}; - -/** - * @brief Disables Array Precharge Bypass Contactor (PBC) by asserting an error. Also updates display for Array PBC to be open. - * @param None -*/ -static void disableArrayPrechargeBypassContactor(void){ - // Assert error to disable regen and update saturation in callback function - assertReadCarCANError(READCARCAN_ERR_CHARGE_DISABLE); - // Turn off the array contactor display light - UpdateDisplay_SetArray(false); // Can assume contactor turned off or else this won't be reached -} - -/** - * @brief Turns array PBC on if conditional meets ignition status, saturation threshold, array PCB to be off, - * and a non-running precharge delay timer. - * @param None -*/ -static void updateArrayPrechargeBypassContactor(void){ - OS_ERR err = OS_ERR_NONE; - if((arrIgnStatus || mcIgnStatus) // Ignition is ON - && HVArrayMsgSaturation >= ARRAY_SATURATION_THRESHOLD // Saturation Threshold has be met - && (Contactors_Get(ARRAY_PRECHARGE_BYPASS_CONTACTOR) == OFF) - // Array PBC is OFF - && (OSTmrStateGet(&arrayPBCDlyTimer, &err) != OS_TMR_STATE_RUNNING)){ // and precharge is currently not happening - // Asserts error for OS timer state above if conditional was met - assertOSError(err); - // Wait to make sure precharge is finished and then restart array - OSTmrStart(&arrayPBCDlyTimer, &err); - } - // Asserts error for OS timer state above if conditional was not met - assertOSError(err); -} - - -/** - * @brief Turns array PBC on if conditional meets ignition status, saturation threshold, motor PBC to be off, - * and a non-running precharge delay timer. - * @param None -*/ -static void updateMCPBC(void){ - OS_ERR err = OS_ERR_NONE; - if(mcIgnStatus // Ignition is ON - && HVPlusMinusChargeMsgSaturation >= PLUS_MINUS_SATURATION_THRESHOLD // Saturation Threshold has be met - &&(Contactors_Get(MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR) == OFF) // Motor Controller PBC is OFF - && (OSTmrStateGet(&motorControllerPBCDlyTimer, &err) != OS_TMR_STATE_RUNNING)){ // and precharge is currently not happening - // Asserts error for OS timer state above if conditional was met - assertOSError(err); - // Wait to make sure precharge is finished and then restart array - OSTmrStart(&motorControllerPBCDlyTimer, &err); - } - // Asserts error for OS timer start above if conditional was not met - assertOSError(err); -} - -/** - * @brief adds new messages by overwriting old messages in the saturation buffer and then updates saturation - * @param messageState whether bps message was enable (1) or disable (-1) -*/ -static void updateHVArraySaturation(int8_t messageState){ - - // Replace oldest message with new charge message and update index for oldest message - HVArrayChargeMsgBuffer[HVArrayOldestMsgIdx] = messageState; - HVArrayOldestMsgIdx = (HVArrayOldestMsgIdx + 1) % SAT_BUF_LENGTH; - - // Calculate the new saturation value by assigning weightings from 1 to buffer length - // in order of oldest to newest - int newSaturation = 0; - for (uint8_t i = 0; i < SAT_BUF_LENGTH; i++){ - newSaturation += HVArrayChargeMsgBuffer[(HVArrayOldestMsgIdx + i) % SAT_BUF_LENGTH] * (i + 1); - } - HVArrayMsgSaturation = newSaturation; - - if(messageState == -1){ - chargeEnable = false; - }else if(HVArrayMsgSaturation >= ARRAY_SATURATION_THRESHOLD){ - chargeEnable = true; - updateArrayPrechargeBypassContactor(); - } - -} - -/** - * @brief adds new messages by overwriting old messages in the saturation buffer and then updates saturation - * @param messageState whether bps message was enable (1) or disable (-1) -*/ -static void updateHVPlusMinusSaturation(int8_t messageState){ - - // Replace oldest message with new charge message and update index for oldest message - HVPlusMinusChargeMsgBuffer[HVPlusMinusMotorOldestMsgIdx] = messageState; - HVPlusMinusMotorOldestMsgIdx = (HVPlusMinusMotorOldestMsgIdx + 1) % SAT_BUF_LENGTH; - - // Calculate the new saturation value by assigning weightings from 1 to buffer length - // in order of oldest to newest - int newSaturation = 0; - for (uint8_t i = 0; i < SAT_BUF_LENGTH; i++){ - newSaturation += HVPlusMinusChargeMsgBuffer[(HVPlusMinusMotorOldestMsgIdx + i) % SAT_BUF_LENGTH] * (i + 1); - } - HVPlusMinusChargeMsgSaturation = newSaturation; - - if(messageState == 1){ - updateMCPBC(); - } -} - -/** - * @brief Helper to turn arrayPBCOn if arrayBypassPrecharge is completed and charging is enabled - * @param None -*/ - void attemptTurnArrayPBCOn(void){ - if(arrPBCComplete && chargeEnable){ - Contactors_Set(ARRAY_PRECHARGE_BYPASS_CONTACTOR, ON, true); // Turn on - UpdateDisplay_SetArray(true); - arrPBCComplete = false; - } - } - -/** - * @brief Helper to turn motorControllerPBCOn if motorControllerBypassPrecharge is completed and threshold is reached - * @param None -*/ - void attemptTurnMotorControllerPBCOn(void){ - if(mcPBCComplete){ - Contactors_Set(MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR, ON, true); - UpdateDisplay_SetMotor(true); - } - } - -/** - * @brief Helper to turn motorControllerPBCOff if ignition is not turned to motor or motor controller threshold isn't reached. - * @param None -*/ - void turnMotorControllerPBCOff(void){ - Contactors_Set(MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR, OFF, true); - UpdateDisplay_SetMotor(false); - } - - -/** - * @brief Turns array and motor controller PBC ON/OFF based on ignition and precharge status - * @param None -*/ - void updatePrechargeContactors(void){ - - arrIgnStatus = (!Minions_Read(IGN_1)); - mcIgnStatus = (!Minions_Read(IGN_2)); - - // Logic helper in cases both are off or (impossible) on - bool bothStatusOff = !mcIgnStatus && !arrIgnStatus; - bool bothStatusOn = mcIgnStatus && arrIgnStatus; - - if(bothStatusOff || bothStatusOn){ - assertReadCarCANError(READCARCAN_ERR_DISABLE_CONTACTORS_MSG); // Turn Array and Motor Controller PBC off using error assert - - }else if(!mcIgnStatus && arrIgnStatus){ - attemptTurnArrayPBCOn(); // Turn Array PBC On, if permitted - turnMotorControllerPBCOff(); // Turn Motor Controller PBC Off - - }else if(mcIgnStatus && !arrIgnStatus){ - attemptTurnArrayPBCOn(); // Turn Array PBC On, if permitted - if(HVPlusMinusChargeMsgSaturation >= PLUS_MINUS_SATURATION_THRESHOLD){ // Turn Motor Controller PBC On, if threshold is reached - attemptTurnMotorControllerPBCOn(); - }else{ - turnMotorControllerPBCOff(); - } - } - - // Set precharge complete variable to false if precharge happens again - arrPBCComplete = false; - mcPBCComplete = false; -} - -void Task_ReadCarCAN(void *p_arg){ - OS_ERR err; - - // data struct for CAN message - CANDATA_t dataBuf; - - // Create the CAN Watchdog (periodic) timer, which disconnects the array and disables regenerative braking - // if we do not get a CAN message with the ID Charge_Enable within the desired interval. - OSTmrCreate( - &canWatchTimer, - "CAN Watch Timer", - CAN_WATCH_TMR_DLY_TMR_TS, // Initial delay equal to the period since 0 doesn't seem to work - CAN_WATCH_TMR_DLY_TMR_TS, - OS_OPT_TMR_PERIODIC, - callbackCANWatchdog, - NULL, - &err - ); - assertOSError(err); - - OSTmrCreate( - &arrayPBCDlyTimer, - "Array Bypass Precharge Delay Timer", - 0, - ARRAY_PRECHARGE_BYPASS_DLY_TMR_TS, - OS_OPT_TMR_ONE_SHOT, - setArrayBypassPrechargeComplete, - NULL, - &err - ); - assertOSError(err); - - OSTmrCreate( - &motorControllerPBCDlyTimer, - "Motor Controller Bypass Precharge Delay Timer", - 0, - MOTOR_CONTROLLER_PRECHARGE_BYPASS_DLY_TMR_TS, - OS_OPT_TMR_ONE_SHOT, - setMotorControllerBypassPrechargeComplete, - NULL, - &err - ); - assertOSError(err); - - // Start CAN Watchdog timer - OSTmrStart(&canWatchTimer, &err); - assertOSError(err); - - // Fills buffers with disable messages - // NOTE: If the buffer becomes bigger than of type int8_t, memset will not work and - // would need to be reimplemented. - memset(HVArrayChargeMsgBuffer, DISABLE_SATURATION_MSG, sizeof(HVArrayChargeMsgBuffer)); - memset(HVPlusMinusChargeMsgBuffer, DISABLE_SATURATION_MSG, sizeof(HVPlusMinusChargeMsgBuffer)); - - while(1){ - - updatePrechargeContactors(); // Sets array and motor controller PBC if all conditions (PBC Status, Threshold, Precharge Complete) permit - - // BPS sent a message - ErrorStatus status = CANbus_Read(&dataBuf, true, CARCAN); - if(status != SUCCESS){ - continue; - } - - switch(dataBuf.ID){ // Switch case based on BPS msg received - case BPS_TRIP: { // BPS has a fault and we need to enter fault state - - // kill contactors and enter a nonrecoverable fault - assertReadCarCANError(READCARCAN_ERR_BPS_TRIP); - } - case BPS_CONTACTOR: { - - OSTmrStart(&canWatchTimer, &err); // Restart CAN Watchdog timer for BPS Contactor msg - assertOSError(err); - - // Retrieving HV contactor statuses using bit mapping - // Bitwise to get HV Plus and Minus, and then &&ing to ensure both are on - bool HVPlusMinusStatus = (bool)((dataBuf.data[0] & HV_PLUS_CONTACTOR_BIT) && (dataBuf.data[0] & HV_MINUS_CONTACTOR_BIT)); - // Bitwise to get HV Array - bool HVArrayStatus = (bool)(dataBuf.data[0] & HV_ARRAY_CONTACTOR_BIT); - - // Update HV Array and HV Plus/Minus saturations based on the respective statuses - HVArrayStatus ? updateHVArraySaturation(ENABLE_SATURATION_MSG) : disableArrayPrechargeBypassContactor(); - HVPlusMinusStatus ? updateHVPlusMinusSaturation(ENABLE_SATURATION_MSG) : updateHVPlusMinusSaturation(DISABLE_SATURATION_MSG); - - break; // End of BPS Contactor Status Updates - } - - case SUPPLEMENTAL_VOLTAGE: { - SBPV = (*(uint16_t *) &dataBuf.data); - UpdateDisplay_SetSBPV(SBPV); // Receive value in mV - break; - } - case STATE_OF_CHARGE:{ - SOC = (*(uint32_t*) &dataBuf.data)/(SOC_SCALER); // Convert to integer percent - UpdateDisplay_SetSOC(SOC); - break; - } - default: { - break; // Unhandled CAN message IDs, do nothing - } - } - } -} - -/** - * @brief error handler callback for disabling charging, - * kills contactor and turns off display - */ -static void handler_ReadCarCAN_chargeDisable(void) { - // Fills buffers with disable messages - memset(HVArrayChargeMsgBuffer, DISABLE_SATURATION_MSG, sizeof(HVArrayChargeMsgBuffer)); - - // mark regen as disabled and update saturation - updateHVArraySaturation(DISABLE_SATURATION_MSG); - - // Kill contactor using a direct write to avoid blocking calls when the scheduler is locked - BSP_GPIO_Write_Pin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, false); - - // Check that the contactor was successfully turned off - bool ret = (bool)Contactors_Get(ARRAY_PRECHARGE_BYPASS_CONTACTOR); - - if(ret) { // Contactor failed to turn off; display the evac screen and infinite loop - Display_Evac(SOC, SBPV); - while(1){;} - } -} - -/** - * @brief error handler callback for disabling charging, - * kills contactor and turns off display - */ -static void handler_ReadCarCAN_contactorsDisable(void) { - - // Mark regen as disabled and update saturation - updateHVArraySaturation(DISABLE_SATURATION_MSG); - updateHVPlusMinusSaturation(DISABLE_SATURATION_MSG); - - // Kill contactor using a direct write to avoid blocking calls when the scheduler is locked - BSP_GPIO_Write_Pin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, false); - BSP_GPIO_Write_Pin(CONTACTORS_PORT, MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN, false); - - // Fills buffers with disable messages - memset(HVArrayChargeMsgBuffer, DISABLE_SATURATION_MSG, sizeof(HVArrayChargeMsgBuffer)); - memset(HVPlusMinusChargeMsgBuffer, DISABLE_SATURATION_MSG, sizeof(HVPlusMinusChargeMsgBuffer)); - - // Updates the saturation with disable - updateHVArraySaturation(DISABLE_SATURATION_MSG); - updateHVPlusMinusSaturation(DISABLE_SATURATION_MSG); - - // Check that the contactor was successfully turned off - bool ret = (bool)Contactors_Get(ARRAY_PRECHARGE_BYPASS_CONTACTOR) || (bool)Contactors_Get(MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR); - - if(ret) { // Contactor failed to turn off; display the evac screen and infinite loop - Display_Evac(SOC, SBPV); - while(1){;} - } -} - -/** - * @brief error handler function to display the evac screen if we get a BPS trip message. - * Callbacks happen after displaying the fault, so this screen won't get overwritten - */ -static void handler_ReadCarCAN_BPSTrip(void) { - chargeEnable = false; // Not really necessary but makes inspection less confusing - Display_Evac(SOC, SBPV); // Display evacuation screen -} - - -/** - * @brief error assertion function for ReadCarCAN, used to disable charging and handle BPS trip messages - * Stores the error code and calls assertTaskError with the appropriate parameters and callback handler - * @param rcc_err error code to specify the issue encountered - */ -static void assertReadCarCANError(ReadCarCAN_error_code_t rcc_err){ - Error_ReadCarCAN = (error_code_t) rcc_err; // Store error code for inspection - - switch (rcc_err) { - case READCARCAN_ERR_NONE: - break; - - case READCARCAN_ERR_CHARGE_DISABLE: // Received a charge disable msg and need to turn off array contactor - throwTaskError(Error_ReadCarCAN, handler_ReadCarCAN_chargeDisable, OPT_LOCK_SCHED, OPT_RECOV); - break; - - case READCARCAN_ERR_MISSED_MSG: // Missed message- turn off array and motor controller PBC - throwTaskError(Error_ReadCarCAN, handler_ReadCarCAN_contactorsDisable, OPT_LOCK_SCHED, OPT_RECOV); - break; - - case READCARCAN_ERR_DISABLE_CONTACTORS_MSG: // Ignition turned to off or turned to last two simultaneously - throwTaskError(Error_ReadCarCAN, handler_ReadCarCAN_contactorsDisable, OPT_LOCK_SCHED, OPT_RECOV); - break; - - case READCARCAN_ERR_BPS_TRIP: // Received a BPS trip msg (0 or 1), need to shut down car and infinite loop - throwTaskError(Error_ReadCarCAN, handler_ReadCarCAN_BPSTrip, OPT_LOCK_SCHED, OPT_NONRECOV); - break; - - default: - break; - } - - Error_ReadCarCAN = READCARCAN_ERR_NONE; // Clear the error after handling it -} \ No newline at end of file diff --git a/Apps/Src/ReadCarCan.c b/Apps/Src/ReadCarCan.c new file mode 100644 index 000000000..5b0868d5f --- /dev/null +++ b/Apps/Src/ReadCarCan.c @@ -0,0 +1,556 @@ +/** + * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file ReadCarCAN.c + * @brief + * + */ + +#include "ReadCarCan.h" + +#include "CanBus.h" +#include "Contactors.h" +#include "Display.h" +#include "Minions.h" +#include "Tasks.h" +#include "UpdateDisplay.h" +#include "common.h" +#include "os.h" +#include "os_cfg_app.h" + +// Length of the array and motor PBC saturation buffers +#define SAT_BUF_LENGTH 5 + +// The Array/Motor Controller Saturation Threshold is used to determine if +// Controls has +// received a sufficient number of BPS's HV Array/Plus-Minus Enable +// Messages. BPS Array and Plus/Minus saturation threshold is halfway +// between 0 and max saturation value. +#define ARRAY_SATURATION_THRESHOLD (((SAT_BUF_LENGTH + 1) * SAT_BUF_LENGTH) / 4) +#define PLUS_MINUS_SATURATION_THRESHOLD \ + (((SAT_BUF_LENGTH + 1) * SAT_BUF_LENGTH) / 4) + +// Timer delay constants +#define CAN_WATCH_TMR_DLY_MS 500u // 500 ms +#define CAN_WATCH_TMR_DLY_TMR_TS \ + ((CAN_WATCH_TMR_DLY_MS * OS_CFG_TMR_TASK_RATE_HZ) / \ + (1000u)) // 1000 for ms -> s conversion + +// Precharge Delay times in milliseconds +#define PRECHARGE_PLUS_MINUS_DELAY \ + 100u // 100 ms, as this the smallest time delay that the RTOS can work with +#define PRECHARGE_ARRAY_DELAY 100u // 100 ms +#define ARRAY_PRECHARGE_BYPASS_DLY_TMR_TS \ + ((PRECHARGE_ARRAY_DELAY * OS_CFG_TMR_TASK_RATE_HZ) / (1000u)) +#define MOTOR_CONTROLLER_PRECHARGE_BYPASS_DLY_TMR_TS \ + ((PRECHARGE_PLUS_MINUS_DELAY * OS_CFG_TMR_TASK_RATE_HZ) / (1000u)) + +// High Voltage BPS Contactor bit mapping +#define HV_ARRAY_CONTACTOR_BIT 1 // 0b001 +#define HV_MINUS_CONTACTOR_BIT 2 // 0b010 +#define HV_PLUS_CONTACTOR_BIT 4 // 0b100 + +// Saturation messages +#define DISABLE_SATURATION_MSG (-1) +#define ENABLE_SATURATION_MSG 1 + +// State of Charge scalar to scale it to correct fixed point +#define SOC_SCALER 1000000 + +// CAN watchdog timer variable +static OS_TMR can_watch_timer; + +// Array precharge bypass contactor delay timer variable +static OS_TMR array_pbc_dly_timer; + +// Motor controller precharge bypass contactor delay timer variable +static OS_TMR motor_controller_pbc_dly_timer; + +// NOTE: This should not be written to anywhere other than ReadCarCAN. If the +// need arises, a mutex to protect it must be added. Indicates whether or not +// regenerative braking / charging is enabled. +static bool charge_enable = + false; // Enable (High message) of BPS high voltage (HV) array contactor + +// BPS HV Array saturation buffer variables +static int8_t hv_array_charge_msg_buffer[SAT_BUF_LENGTH]; +static int8_t hv_array_msg_saturation = 0; +static uint8_t hv_array_oldest_msg_idx = 0; + +// BPS HV Motor Controller saturation buffer variables +static int8_t hv_plus_minus_charge_msg_buffer[SAT_BUF_LENGTH]; +static int8_t hv_plus_minus_charge_msg_saturation = 0; +static uint8_t hv_plus_minus_motor_oldest_msg_idx = 0; + +// Array ignition (kIgn1) and Motor Controller ignition (kIgn2) pin status +static bool arr_ign_status = false; +static bool mc_ign_status = false; + +// Boolean to indicate precharge status for Array Precharge Bypass Contactor +// (PBC) and Motor Controller PBC +static bool arr_pbc_complete = false; +static bool mc_pbc_complete = false; + +// State of Charge (SOC) and supplemental battery pack voltage (SBPV) value +// intialization +static uint8_t soc = 0; +static uint32_t sbpv = 0; + +// Error assertion function prototype +static void assertReadCarCANError(ReadCarCanErrorCode rcc_err); + +// Getter function for charge enable, indicating that battery charging is +// allowed +bool ChargeEnableGet(void) { return charge_enable; } + +/** + * @brief Nested function as the same function needs to be executed however the + * timer requires different parameters + * @param p_tmr pointer to the timer that calls this function, passed by timer + * @param p_arg pointer to the argument passed by timer + */ +static void callbackCANWatchdog(void *p_tmr, void *p_arg) { + assertReadCarCANError(kReadCarCanErrMissedMsg); +} + +/** + * @brief Callback function for the precharge delay timer. Waits for precharge + * and then sets arrPBCComplete to true. + * @param p_tmr pointer to the timer that calls this function, passed by timer + * @param p_arg pointer to the argument passed by timer + */ +static void setArrayBypassPrechargeComplete(void *p_tmr, void *p_arg) { + arr_pbc_complete = true; +}; + +/** + * @brief Callback function for the precharge delay timer. Waits for precharge + * and then sets mcPBCComplete to true. + * @param p_tmr pointer to the timer that calls this function, passed by timer + * @param p_arg pointer to the argument passed by timer + */ +static void setMotorControllerBypassPrechargeComplete(void *p_tmr, + void *p_arg) { + mc_pbc_complete = true; +}; + +/** + * @brief Disables Array Precharge Bypass Contactor (PBC) by asserting an error. + * Also updates display for Array PBC to be open. + * @param None + */ +static void disableArrayPrechargeBypassContactor(void) { + // Assert error to disable regen and update saturation in callback function + assertReadCarCANError(kReadCarCanErrChargeDisable); + // Turn off the array contactor display light + UpdateDisplaySetArray(false); // Can assume contactor turned off or else + // this won't be reached +} + +/** + * @brief Turns array PBC on if conditional meets ignition status, saturation + * threshold, array PCB to be off, and a non-running precharge delay timer. + * @param None + */ +static void updateArrayPrechargeBypassContactor(void) { + OS_ERR err = OS_ERR_NONE; + if ((arr_ign_status || mc_ign_status) // Ignition is ON + && hv_array_msg_saturation >= + ARRAY_SATURATION_THRESHOLD // Saturation Threshold has be met + && (ContactorsGet(kArrayPrechargeBypassContactor) == OFF) + // Array PBC is OFF + && + (OSTmrStateGet(&array_pbc_dly_timer, &err) != + OS_TMR_STATE_RUNNING)) { // and precharge is currently not happening + // Asserts error for OS timer state above if conditional was met + ASSERT_OS_ERROR(err); + // Wait to make sure precharge is finished and then restart array + OSTmrStart(&array_pbc_dly_timer, &err); + } + // Asserts error for OS timer state above if conditional was not met + ASSERT_OS_ERROR(err); +} + +/** + * @brief Turns array PBC on if conditional meets ignition status, saturation + * threshold, motor PBC to be off, and a non-running precharge delay timer. + * @param None + */ +static void updateMCPBC(void) { + OS_ERR err = OS_ERR_NONE; + if (mc_ign_status // Ignition is ON + && + hv_plus_minus_charge_msg_saturation >= + PLUS_MINUS_SATURATION_THRESHOLD // Saturation Threshold has be met + && (ContactorsGet(kMotorControllerPrechargeBypassContactor) == + OFF) // Motor Controller PBC is OFF + && + (OSTmrStateGet(&motor_controller_pbc_dly_timer, &err) != + OS_TMR_STATE_RUNNING)) { // and precharge is currently not happening + // Asserts error for OS timer state above if conditional was met + ASSERT_OS_ERROR(err); + // Wait to make sure precharge is finished and then restart array + OSTmrStart(&motor_controller_pbc_dly_timer, &err); + } + // Asserts error for OS timer start above if conditional was not met + ASSERT_OS_ERROR(err); +} + +/** + * @brief adds new messages by overwriting old messages in the saturation buffer + * and then updates saturation + * @param messageState whether bps message was enable (1) or disable (-1) + */ +static void updateHVArraySaturation(int8_t message_state) { + // Replace oldest message with new charge message and update index for + // oldest message + hv_array_charge_msg_buffer[hv_array_oldest_msg_idx] = message_state; + hv_array_oldest_msg_idx = (hv_array_oldest_msg_idx + 1) % SAT_BUF_LENGTH; + + // Calculate the new saturation value by assigning weightings from 1 to + // buffer length in order of oldest to newest + int new_saturation = 0; + for (uint8_t i = 0; i < SAT_BUF_LENGTH; i++) { + new_saturation += + hv_array_charge_msg_buffer[(hv_array_oldest_msg_idx + i) % + SAT_BUF_LENGTH] * + (i + 1); + } + hv_array_msg_saturation = (int8_t)new_saturation; + + if (message_state == -1) { + charge_enable = false; + } else if (hv_array_msg_saturation >= ARRAY_SATURATION_THRESHOLD) { + charge_enable = true; + updateArrayPrechargeBypassContactor(); + } +} + +/** + * @brief adds new messages by overwriting old messages in the saturation buffer + * and then updates saturation + * @param messageState whether bps message was enable (1) or disable (-1) + */ +static void updateHVPlusMinusSaturation(int8_t message_state) { + // Replace oldest message with new charge message and update index for + // oldest message + hv_plus_minus_charge_msg_buffer[hv_plus_minus_motor_oldest_msg_idx] = + message_state; + hv_plus_minus_motor_oldest_msg_idx = + (hv_plus_minus_motor_oldest_msg_idx + 1) % SAT_BUF_LENGTH; + + // Calculate the new saturation value by assigning weightings from 1 to + // buffer length in order of oldest to newest + int new_saturation = 0; + for (uint8_t i = 0; i < SAT_BUF_LENGTH; i++) { + new_saturation += + hv_plus_minus_charge_msg_buffer + [(hv_plus_minus_motor_oldest_msg_idx + i) % SAT_BUF_LENGTH] * + (i + 1); + } + hv_plus_minus_charge_msg_saturation = (int8_t)new_saturation; + + if (message_state == 1) { + updateMCPBC(); + } +} + +/** + * @brief Helper to turn arrayPBCOn if arrayBypassPrecharge is completed and + * charging is enabled + * @param None + */ +void AttemptTurnArrayPbcOn(void) { + if (arr_pbc_complete && charge_enable) { + ContactorsSet(kArrayPrechargeBypassContactor, ON, true); // Turn on + UpdateDisplaySetArray(true); + arr_pbc_complete = false; + } +} + +/** + * @brief Helper to turn motorControllerPBCOn if motorControllerBypassPrecharge + * is completed and threshold is reached + * @param None + */ +void AttemptTurnMotorControllerPbcOn(void) { + if (mc_pbc_complete) { + ContactorsSet(kMotorControllerPrechargeBypassContactor, ON, true); + UpdateDisplaySetMotor(true); + } +} + +/** + * @brief Helper to turn motorControllerPBCOff if ignition is not turned to + * motor or motor controller threshold isn't reached. + * @param None + */ +void TurnMotorControllerPbcOff(void) { + ContactorsSet(kMotorControllerPrechargeBypassContactor, OFF, true); + UpdateDisplaySetMotor(false); +} + +/** + * @brief Turns array and motor controller PBC ON/OFF based on ignition and + * precharge status + * @param None + */ +void UpdatePrechargeContactors(void) { + arr_ign_status = MinionsRead(kIgn1); + mc_ign_status = MinionsRead(kIgn2); + + // Logic helper in cases both are off or (impossible) on + bool both_status_off = !mc_ign_status && !arr_ign_status; + bool both_status_on = mc_ign_status && arr_ign_status; + + if (both_status_off || both_status_on) { + assertReadCarCANError( + kReadCarCanErrDisableContactorsMsg); // Turn Array and Motor + // Controller PBC off using + // error assert + + } else if (!mc_ign_status && arr_ign_status) { + AttemptTurnArrayPbcOn(); // Turn Array PBC On, if permitted + TurnMotorControllerPbcOff(); // Turn Motor Controller PBC Off + + } else if (mc_ign_status && !arr_ign_status) { + AttemptTurnArrayPbcOn(); // Turn Array PBC On, if permitted + if (hv_plus_minus_charge_msg_saturation >= + PLUS_MINUS_SATURATION_THRESHOLD) { // Turn Motor Controller PBC On, + // if threshold is reached + AttemptTurnMotorControllerPbcOn(); + } else { + TurnMotorControllerPbcOff(); + } + } + + // Set precharge complete variable to false if precharge happens again + arr_pbc_complete = false; + mc_pbc_complete = false; +} + +void TaskReadCarCan(void *p_arg) { + OS_ERR err = 0; + + // data struct for CAN message + CanData data_buf; + + // Create the CAN Watchdog (periodic) timer, which disconnects the array and + // disables regenerative braking if we do not get a CAN message with the ID + // Charge_Enable within the desired interval. + OSTmrCreate(&can_watch_timer, "CAN Watch Timer", + CAN_WATCH_TMR_DLY_TMR_TS, // Initial delay equal to the period + // since 0 doesn't seem to work + CAN_WATCH_TMR_DLY_TMR_TS, OS_OPT_TMR_PERIODIC, + callbackCANWatchdog, NULL, &err); + ASSERT_OS_ERROR(err); + + OSTmrCreate(&array_pbc_dly_timer, "Array Bypass Precharge Delay Timer", 0, + ARRAY_PRECHARGE_BYPASS_DLY_TMR_TS, OS_OPT_TMR_ONE_SHOT, + setArrayBypassPrechargeComplete, NULL, &err); + ASSERT_OS_ERROR(err); + + OSTmrCreate(&motor_controller_pbc_dly_timer, + "Motor Controller Bypass Precharge Delay Timer", 0, + MOTOR_CONTROLLER_PRECHARGE_BYPASS_DLY_TMR_TS, + OS_OPT_TMR_ONE_SHOT, setMotorControllerBypassPrechargeComplete, + NULL, &err); + ASSERT_OS_ERROR(err); + + // Start CAN Watchdog timer + OSTmrStart(&can_watch_timer, &err); + ASSERT_OS_ERROR(err); + + // Fills buffers with disable messages + // NOTE: If the buffer becomes bigger than of type int8_t, memset will not + // work and would need to be reimplemented. + memset(hv_array_charge_msg_buffer, DISABLE_SATURATION_MSG, + sizeof(hv_array_charge_msg_buffer)); + memset(hv_plus_minus_charge_msg_buffer, DISABLE_SATURATION_MSG, + sizeof(hv_plus_minus_charge_msg_buffer)); + + while (1) { + UpdatePrechargeContactors(); // Sets array and motor controller PBC if + // all conditions (PBC Status, Threshold, + // Precharge Complete) permit + + // BPS sent a message + ErrorStatus status = CanBusRead(&data_buf, true, CARCAN); + if (status != SUCCESS) { + continue; + } + + switch (data_buf.id) { // Switch case based on BPS msg received + case kBpsTrip: { // BPS has a fault and we need to enter fault + // state + + // kill contactors and enter a nonrecoverable fault + assertReadCarCANError(kReadCarCanErrBpsTrip); + } + case kBpsContactor: { + OSTmrStart( + &can_watch_timer, + &err); // Restart CAN Watchdog timer for BPS Contactor msg + ASSERT_OS_ERROR(err); + + // Retrieving HV contactor statuses using bit mapping + // Bitwise to get HV Plus and Minus, and then &&ing to ensure + // both are on + bool hv_plus_minus_status = + (bool)((data_buf.data[0] & HV_PLUS_CONTACTOR_BIT) && + (data_buf.data[0] & HV_MINUS_CONTACTOR_BIT)); + // Bitwise to get HV Array + bool hv_array_status = + (bool)(data_buf.data[0] & HV_ARRAY_CONTACTOR_BIT); + + // Update HV Array and HV Plus/Minus saturations based on the + // respective statuses + hv_array_status ? updateHVArraySaturation(ENABLE_SATURATION_MSG) + : disableArrayPrechargeBypassContactor(); + hv_plus_minus_status + ? updateHVPlusMinusSaturation(ENABLE_SATURATION_MSG) + : updateHVPlusMinusSaturation(DISABLE_SATURATION_MSG); + + break; // End of BPS Contactor Status Updates + } + + case kSupplementalVoltage: { + sbpv = (*(uint16_t *)&data_buf.data); + UpdateDisplaySetSbpv(sbpv); // Receive value in mV + break; + } + case kStateOfCharge: { + soc = (*(uint32_t *)&data_buf.data) / + (SOC_SCALER); // Convert to integer percent + UpdateDisplaySetSoc(soc); + break; + } + default: { + break; // Unhandled CAN message IDs, do nothing + } + } + +#ifdef MOCKING + break; +#endif + } +} + +/** + * @brief error handler callback for disabling charging, + * kills contactor and turns off display + */ +static void handlerReadCarCanChargeDisable(void) { + // Fills buffers with disable messages + memset(hv_array_charge_msg_buffer, DISABLE_SATURATION_MSG, + sizeof(hv_array_charge_msg_buffer)); + + // mark regen as disabled and update saturation + updateHVArraySaturation(DISABLE_SATURATION_MSG); + + // Kill contactor using a direct write to avoid blocking calls when the + // scheduler is locked + BspGpioWritePin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, false); + + // Check that the contactor was successfully turned off + bool ret = (bool)ContactorsGet(kArrayPrechargeBypassContactor); + + if (ret) { // Contactor failed to turn off; display the evac screen and + // infinite loop + DisplayEvac(soc, sbpv); +#ifndef MOCKING + while (1) {} +#endif + } +} + +/** + * @brief error handler callback for disabling charging, + * kills contactor and turns off display + */ +static void handlerReadCarCanContactorsDisable(void) { + // Mark regen as disabled and update saturation + updateHVArraySaturation(DISABLE_SATURATION_MSG); + updateHVPlusMinusSaturation(DISABLE_SATURATION_MSG); + + // Kill contactor using a direct write to avoid blocking calls when the + // scheduler is locked + BspGpioWritePin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, false); + BspGpioWritePin(CONTACTORS_PORT, MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN, + false); + + // Fills buffers with disable messages + memset(hv_array_charge_msg_buffer, DISABLE_SATURATION_MSG, + sizeof(hv_array_charge_msg_buffer)); + memset(hv_plus_minus_charge_msg_buffer, DISABLE_SATURATION_MSG, + sizeof(hv_plus_minus_charge_msg_buffer)); + + // Updates the saturation with disable + updateHVArraySaturation(DISABLE_SATURATION_MSG); + updateHVPlusMinusSaturation(DISABLE_SATURATION_MSG); + + // Check that the contactor was successfully turned off + bool ret = (bool)ContactorsGet(kArrayPrechargeBypassContactor) || + (bool)ContactorsGet(kMotorControllerPrechargeBypassContactor); + + if (ret) { // Contactor failed to turn off; display the evac screen and + // infinite loop + DisplayEvac(soc, sbpv); +#ifndef MOCKING + while (1) {} +#endif + } +} + +/** + * @brief error handler function to display the evac screen if we get a BPS trip + * message. Callbacks happen after displaying the fault, so this screen won't + * get overwritten + */ +static void handlerReadCarCanBpsTrip(void) { + charge_enable = + false; // Not really necessary but makes inspection less confusing + DisplayEvac(soc, sbpv); // Display evacuation screen +} + +/** + * @brief error assertion function for ReadCarCAN, used to disable charging and + * handle BPS trip messages Stores the error code and calls assertTaskError with + * the appropriate parameters and callback handler + * @param rcc_err error code to specify the issue encountered + */ +static void assertReadCarCANError(ReadCarCanErrorCode rcc_err) { + error_read_car_can = (ErrorCode)rcc_err; // Store error code for inspection + + switch (rcc_err) { + case kReadCarCanErrNone: + break; + + case kReadCarCanErrChargeDisable: // Received a charge disable msg and + // need to turn off array contactor + ThrowTaskError(error_read_car_can, handlerReadCarCanChargeDisable, + kOptLockSched, kOptRecov); + break; + + case kReadCarCanErrDisableContactorsMsg: + case kReadCarCanErrMissedMsg: // Missed message- turn off array and + // motor controller PBC Ignition turned + // to off or turned to last two + // simultaneously + ThrowTaskError(error_read_car_can, + handlerReadCarCanContactorsDisable, kOptLockSched, + kOptRecov); + break; + + case kReadCarCanErrBpsTrip: // Received a BPS trip msg (0 or 1), need + // to shut down car and infinite loop + ThrowTaskError(error_read_car_can, handlerReadCarCanBpsTrip, + kOptLockSched, kOptRecov); + break; + + default: + break; + } + + error_read_car_can = + kReadCarCanErrNone; // Clear the error after handling it +} \ No newline at end of file diff --git a/Apps/Src/ReadTritium.c b/Apps/Src/ReadTritium.c old mode 100755 new mode 100644 index 6b1055ce6..e83b1b3af --- a/Apps/Src/ReadTritium.c +++ b/Apps/Src/ReadTritium.c @@ -1,169 +1,193 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file ReadTritium.c - * @brief - * + * @brief + * */ #include "ReadTritium.h" -#include "CANbus.h" + +#include + +#include "CanBus.h" +#include "SendCarCan.h" #include "UpdateDisplay.h" -#include "SendCarCAN.h" #include "os_cfg_app.h" -#include -//status limit flag masks -#define MASK_MOTOR_TEMP_LIMIT (1<<6) //check if motor temperature is limiting the motor +// status limit flag masks +#define MASK_MOTOR_TEMP_LIMIT \ + (1 << 6) // check if motor temperature is limiting the motor #define MAX_CAN_LEN 8 -#define RESTART_THRESHOLD 3 // Number of times to restart before asserting a nonrecoverable error -#define MOTOR_TIMEOUT_SECS 1 // Timeout for several missed motor messages +#define RESTART_THRESHOLD \ + 3 // Number of times to restart before asserting a nonrecoverable error +#define MOTOR_TIMEOUT_SECS 1 // Timeout for several missed motor messages #define MOTOR_TIMEOUT_TICKS (MOTOR_TIMEOUT_SECS * OS_CFG_TMR_TASK_RATE_HZ) +TritiumErrorCode motor_fault_bitmap = + kNone; // initialized to no error, changed when the motor asserts an error +static float motor_rpm = 0; +static float motor_velocity = 0; -tritium_error_code_t Motor_FaultBitmap = T_NONE; //initialized to no error, changed when the motor asserts an error -static float Motor_RPM = 0; -static float Motor_Velocity = 0; - -static OS_TMR MotorWatchdog; +static OS_TMR motor_watchdog; // Function prototypes -static void assertTritiumError(tritium_error_code_t motor_err); +static void assertTritiumError(TritiumErrorCode motor_err); // Callback for motor watchdog static void motorWatchdog(void *tmr, void *p_arg) { // Attempt to restart 3 times, then fail - assertTritiumError(T_MOTOR_WATCHDOG_TRIP); + assertTritiumError(kMotorWatchdogTrip); } +void TaskReadTritium(void *p_arg) { + OS_ERR err = 0; + CanData data_buf = {0}; -void Task_ReadTritium(void *p_arg){ - OS_ERR err; - CANDATA_t dataBuf = {0}; + // Timer doesn't seem to trigger without initial delay? Might be an RTOS bug + static bool watchdog_created = false; - static bool watchdogCreated = false; + while (1) { + ErrorStatus status = CanBusRead(&data_buf, true, MOTORCAN); - while (1){ - ErrorStatus status = CANbus_Read(&dataBuf, true, MOTORCAN); + if (status == SUCCESS) { + if (!watchdog_created) { + OSTmrCreate(&motor_watchdog, "Motor watchdog", + MOTOR_TIMEOUT_TICKS, MOTOR_TIMEOUT_TICKS, + OS_OPT_TMR_PERIODIC, motorWatchdog, NULL, &err); + ASSERT_OS_ERROR(err); - if (status == SUCCESS){ - if(!watchdogCreated){ // Timer doesn't seem to trigger without initial delay? Might be an RTOS bug - OSTmrCreate(&MotorWatchdog, "Motor watchdog", MOTOR_TIMEOUT_TICKS, MOTOR_TIMEOUT_TICKS, OS_OPT_TMR_PERIODIC, motorWatchdog, NULL, &err); - assertOSError(err); + OSTmrStart(&motor_watchdog, &err); + ASSERT_OS_ERROR(err); - OSTmrStart(&MotorWatchdog, &err); - assertOSError(err); + watchdog_created = true; + } - watchdogCreated = true; + switch (data_buf.id) { + case kMotorStatus: { + // motor status error flags is in bytes 4-5 + motor_fault_bitmap = *( + (uint16_t *)(&data_buf + .data[4])); // Storing error flags + // into Motor_FaultBitmap + assertTritiumError(motor_fault_bitmap); + break; + } + + case kVelocity: { + OSTmrStart(&motor_watchdog, &err); // Reset the watchdog + ASSERT_OS_ERROR(err); + memcpy(&motor_rpm, &data_buf.data[0], sizeof(float)); + memcpy(&motor_velocity, &data_buf.data[4], sizeof(float)); + + // Motor RPM is in bytes 0-3 + motor_rpm = *((float *)(&data_buf.data[0])); + + // Car kVelocity (in m/s) is in bytes 4-7 + motor_velocity = *((float *)(&data_buf.data[4])); + uint32_t car_velocity = (uint32_t)motor_velocity; + + car_velocity = + ((car_velocity * 100) * + 3600); // Converting from m/s to m/h, // NOLINT + // using fixed point factor of 100 + car_velocity = ((car_velocity / 160934) * // NOLINT + 10); // NOLINT // Converting from m/h to + // mph, multiplying by 10 to make + // value "larger" for displaying + + UpdateDisplaySetVelocity(car_velocity); + } + + default: { + break; // for cases not handled currently + } } - switch(dataBuf.ID){ - case MOTOR_STATUS:{ - // motor status error flags is in bytes 4-5 - Motor_FaultBitmap = *((uint16_t*)(&dataBuf.data[4])); //Storing error flags into Motor_FaultBitmap - assertTritiumError(Motor_FaultBitmap); - break; - } - - case VELOCITY:{ - OSTmrStart(&MotorWatchdog, &err); // Reset the watchdog - assertOSError(err); - memcpy(&Motor_RPM, &dataBuf.data[0], sizeof(float)); - memcpy(&Motor_Velocity, &dataBuf.data[4], sizeof(float)); - - //Motor RPM is in bytes 0-3 - Motor_RPM = *((float*)(&dataBuf.data[0])); - - //Car Velocity (in m/s) is in bytes 4-7 - Motor_Velocity = *((float*)(&dataBuf.data[4])); - uint32_t Car_Velocity = Motor_Velocity; - - Car_Velocity = ((Car_Velocity * 100) * 3600); //Converting from m/s to m/h, using fixed point factor of 100 - Car_Velocity = ((Car_Velocity / 160934) * 10); //Converting from m/h to mph, multiplying by 10 to make value "larger" for displaying - - UpdateDisplay_SetVelocity(Car_Velocity); - - } - - default:{ - break; //for cases not handled currently - } - - } - - SendCarCAN_Put(dataBuf); // Forward message on CarCAN for telemetry - } - } + SendCarCanPut(data_buf); // Forward message on CarCAN for telemetry + } +#ifdef MOCKING + break; +#endif + } } -static void restartMotorController(void){ - CANDATA_t resetmsg = {0}; - resetmsg.ID = MOTOR_RESET; - CANbus_Send(resetmsg, true, MOTORCAN); +static void restartMotorController(void) { + CanData resetmsg = {0}; + resetmsg.id = kMotorReset; + CanBusSend(resetmsg, true, MOTORCAN); } - -float Motor_RPM_Get(){ //getter function for motor RPM - return Motor_RPM; +float MotorRpmGet() { // getter function for motor RPM + return motor_rpm; } -float Motor_Velocity_Get(){ //getter function for motor velocity - return Motor_Velocity; +float MotorVelocityGet() { // getter function for motor velocity + return motor_velocity; } - /** * Error handler functions - * Passed as callback functions to the main throwTaskError function by assertTritiumError -*/ + * Passed as callback functions to the main ThrowTaskError function by + * assertTritiumError + */ /** - * @brief A callback function to be run by the main throwTaskError function for hall sensor errors - * restart the motor if the number of hall errors is still less than the MOTOR_RESTART_THRESHOLD. - */ -static inline void handler_ReadTritium_HallError(void) { - restartMotorController(); + * @brief A callback function to be run by the main ThrowTaskError function for + * hall sensor errors restart the motor if the number of hall errors is still + * less than the MOTOR_RESTART_THRESHOLD. + */ +static inline void handlerReadTritiumHallError(void) { + restartMotorController(); } - /** * @brief Assert a Tritium error by checking Motor_FaultBitmap * and asserting the error with its handler callback if one exists. - * Can result in restarting the motor (for hall sensor errors while less than MOTOR_RESTART_THRESHOLD) - * or locking the scheduler and entering a nonrecoverable fault (all other cases) + * Can result in restarting the motor (for hall sensor errors while less than + * MOTOR_RESTART_THRESHOLD) or locking the scheduler and entering a + * nonrecoverable fault (all other cases) * @param motor_err Bitmap with motor error codes to check */ -static void assertTritiumError(tritium_error_code_t motor_err){ - static uint8_t hall_fault_cnt = 0; //trip counter, doesn't ever reset - static uint8_t motor_fault_cnt = 0; - - Error_ReadTritium = (error_code_t)motor_err; // Store error codes for inspection info - if(motor_err == T_NONE) return; // No error, return - // NOTE: If we had >1 recoverable errors, - // Hall sensor error is the only recoverable error, so any other error // make sure a combination of them wouldn't - // or combination of errors includes at least one that is nonrecoverable // accidentally fall into this nonrecoverable bucket - if(motor_err != T_HALL_SENSOR_ERR && motor_err != T_MOTOR_WATCHDOG_TRIP){ - // Assert a nonrecoverable error with no callback function- nonrecoverable will kill the motor and infinite loop - throwTaskError(Error_ReadTritium, NULL, OPT_LOCK_SCHED, OPT_NONRECOV); - return; - } - - // If it's purely a hall sensor error, try to restart the motor a few times and then fail out - - if(motor_err == T_HALL_SENSOR_ERR && ++hall_fault_cnt > RESTART_THRESHOLD){ // Threshold has been exceeded - // Assert a nonrecoverable error that will kill the motor, display a fault screen, and infinite loop - throwTaskError(Error_ReadTritium, NULL, OPT_LOCK_SCHED, OPT_NONRECOV); - return; - } - - //try to restart the motor a few times and then fail out - if(motor_err == T_MOTOR_WATCHDOG_TRIP && ++motor_fault_cnt > RESTART_THRESHOLD){ - // Assert a nonrecoverable error that will kill the motor, display a fault screen, and infinite loop - throwTaskError(Error_ReadTritium, NULL, OPT_LOCK_SCHED, OPT_NONRECOV); - return; - } - - // Threshold hasn't been exceeded, so assert a recoverable error with the motor restart callback function - throwTaskError(Error_ReadTritium, handler_ReadTritium_HallError, OPT_NO_LOCK_SCHED, OPT_RECOV); - - Error_ReadTritium = T_NONE; // Clear the error after handling it +static void assertTritiumError(TritiumErrorCode motor_err) { + static uint8_t hall_fault_cnt = 0; // trip counter, doesn't ever reset + static uint8_t motor_fault_cnt = 0; + + error_read_tritium = + (ErrorCode)motor_err; // Store error codes for inspection info + if (motor_err == kNone) { + return; // No error, return + } + if (motor_err != kHallSensorErr && motor_err != kMotorWatchdogTrip) { + // Assert a nonrecoverable error with no callback function- + // nonrecoverable will kill the motor and infinite loop + ThrowTaskError(error_read_tritium, NULL, kOptLockSched, kOptNonrecov); + return; + } + + // If it's purely a hall sensor error, try to restart the motor a few times + // and then fail out + + if (motor_err == kHallSensorErr && + ++hall_fault_cnt > RESTART_THRESHOLD) { // Threshold has been exceeded + // Assert a nonrecoverable error that will kill the motor, display a + // fault screen, and infinite loop + ThrowTaskError(error_read_tritium, NULL, kOptLockSched, kOptNonrecov); + return; + } + + // try to restart the motor a few times and then fail out + if (motor_err == kMotorWatchdogTrip && + ++motor_fault_cnt > RESTART_THRESHOLD) { + // Assert a nonrecoverable error that will kill the motor, display a + // fault screen, and infinite loop + ThrowTaskError(error_read_tritium, NULL, kOptLockSched, kOptNonrecov); + return; + } + + // Threshold hasn't been exceeded, so assert a recoverable error with the + // motor restart callback function + ThrowTaskError(error_read_tritium, handlerReadTritiumHallError, + kOptNoLockSched, kOptRecov); + + error_read_tritium = kNone; // Clear the error after handling it } diff --git a/Apps/Src/SendCarCAN.c b/Apps/Src/SendCarCAN.c deleted file mode 100644 index 0272b8b6d..000000000 --- a/Apps/Src/SendCarCAN.c +++ /dev/null @@ -1,179 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file SendCarCAN.c - * @brief Function implementations for the SendCarCAN application. - * - * This contains functions relevant to placing CAN messages in a CarCAN queue and periodically sending - * those messages in the SendCarCAN task. - * - */ - -#include "common.h" -#include "os_cfg_app.h" -#include "CANbus.h" -#include "Minions.h" -#include "Contactors.h" -#include "Pedals.h" -#include "Tasks.h" -#include "SendCarCAN.h" -#include "SendTritium.h" - -#define IO_STATE_DLY_MS 250u - -#define SENDCARCAN_MSG_SKIP_CTR 3 - -// Task_PutIOState -OS_TCB putIOState_TCB; -CPU_STK putIOState_Stk[TASK_SEND_CAR_CAN_STACK_SIZE]; - -//fifo -#define FIFO_TYPE CANDATA_t -#define FIFO_SIZE 50 -#define FIFO_NAME SendCarCAN_Q -#include "fifo.h" - -static SendCarCAN_Q_t CANFifo; - -static OS_SEM CarCAN_Sem4; -static OS_MUTEX CarCAN_Mtx; - -static void Task_PutIOState(void *p_arg); - -/** - * @brief return the space left in SendCarCAN_Q for debug purposes -*/ -#ifdef DEBUG -uint8_t get_SendCarCAN_Q_Space(void) { - return (CANFifo.get - CANFifo.put - 1) % (sizeof CANFifo.buffer / sizeof CANFifo.buffer[0]); -} -#endif - -/** - * @brief Wrapper to put new message in the CAN queue -*/ -void SendCarCAN_Put(CANDATA_t message){ - OS_ERR err; - CPU_TS ticks; - bool success = false; - - static uint8_t carcan_ctr = 0; - - if(carcan_ctr > SENDCARCAN_MSG_SKIP_CTR){ - OSMutexPend(&CarCAN_Mtx, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); - assertOSError(err); - - success = SendCarCAN_Q_put(&CANFifo, message); - - OSMutexPost(&CarCAN_Mtx, OS_OPT_POST_NONE, &err); - assertOSError(err); - - carcan_ctr = 0; - } - carcan_ctr++; - - - if(success) { - OSSemPost(&CarCAN_Sem4, OS_OPT_POST_1, &err); - assertOSError(err); - } -} - -/** - * @brief Initialize SendCarCAN -*/ -void SendCarCAN_Init(void) { - OS_ERR err; - - OSMutexCreate(&CarCAN_Mtx, "CarCAN_Mtx", &err); - assertOSError(err); - - OSSemCreate(&CarCAN_Sem4, "CarCAN_Sem4", 0, &err); - assertOSError(err); - - SendCarCAN_Q_renew(&CANFifo); -} - -/** - * @brief Grabs the latest messages from the queue and sends over CarCAN -*/ -void Task_SendCarCAN(void *p_arg){ - OS_ERR err; - CPU_TS ticks; - - CANDATA_t message; - memset(&message, 0, sizeof message); - - // PutIOState - OSTaskCreate( - (OS_TCB*)&putIOState_TCB, - (CPU_CHAR*)"PutIOState", - (OS_TASK_PTR)Task_PutIOState, - (void*)NULL, - (OS_PRIO)TASK_PUT_IOSTATE_PRIO, - (CPU_STK*)putIOState_Stk, - (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, - (CPU_STK_SIZE)TASK_SEND_CAR_CAN_STACK_SIZE, - (OS_MSG_QTY)0, - (OS_TICK)0, - (void*)NULL, - (OS_OPT)(OS_OPT_TASK_STK_CLR), - (OS_ERR*)&err - ); - assertOSError(err); - - while (1) { - - // Check if there's something to send in the queue (either IOState or Car state from sendTritium) - OSSemPend(&CarCAN_Sem4, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); - assertOSError(err); - - OSMutexPend(&CarCAN_Mtx, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); - assertOSError(err); - - bool res = SendCarCAN_Q_get(&CANFifo, &message); - - OSMutexPost(&CarCAN_Mtx, OS_OPT_POST_NONE, &err); - assertOSError(err); - - if(res) CANbus_Send(message, true, CARCAN); - } -} - -static void putIOState(void){ - CANDATA_t message; - memset(&message, 0, sizeof message); - message.ID = IO_STATE; - - // Get pedal information - message.data[0] = Pedals_Read(ACCELERATOR); - message.data[1] = Pedals_Read(BRAKE); - - // Get minion information - for(pin_t pin = 0; pin < NUM_PINS; pin++){ - bool pinState = Minions_Read(pin); - message.data[2] |= pinState << pin; - } - - // Get contactor info - for(contactor_t contactor = 0; contactor < NUM_CONTACTORS; contactor++){ - bool contactorState = (Contactors_Get(contactor) == ON) ? true : false; - message.data[3] |= contactorState << contactor; - } - - // Tell BPS if the array contactor should be on - message.data[3] |= (!Minions_Read(IGN_1) || !Minions_Read(IGN_2)) << 2; - - CANbus_Send(message, true, CARCAN); -} - -/** - * @brief sends IO information over CarCAN every IO_STATE_DLY_MS -*/ -static void Task_PutIOState(void *p_arg) { - OS_ERR err; - while (1) { - putIOState(); - OSTimeDlyHMSM(0, 0, 0, IO_STATE_DLY_MS, OS_OPT_TIME_HMSM_STRICT, &err); - assertOSError(err); - } -} diff --git a/Apps/Src/SendCarCan.c b/Apps/Src/SendCarCan.c new file mode 100644 index 000000000..8ff50ae7b --- /dev/null +++ b/Apps/Src/SendCarCan.c @@ -0,0 +1,182 @@ +/** + * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file SendCarCAN.c + * @brief Function implementations for the SendCarCAN application. + * + * This contains functions relevant to placing CAN messages in a CarCAN queue + * and periodically sending those messages in the SendCarCAN task. This contains + * functions relevant to placing CAN messages in a CarCAN queue and periodically + * sending those messages in the SendCarCAN task. + * + */ + +#include "SendCarCan.h" + +#include "CanBus.h" +#include "Contactors.h" +#include "Minions.h" +#include "Pedals.h" +#include "SendTritium.h" +#include "Tasks.h" +#include "common.h" +#include "os_cfg_app.h" + +#define IO_STATE_DLY_MS 250u + +#define SENDCARCAN_MSG_SKIP_CTR 3 + +// Task_PutIOState +OS_TCB put_io_state_tcb; +CPU_STK put_io_state_stk[TASK_SEND_CAR_CAN_STACK_SIZE]; + +// fifo +#define FIFO_TYPE CanData +#define FIFO_SIZE 50 +#define FIFO_NAME Queue +#include "fifo.h" + +static Queue can_fifo; + +static OS_SEM car_can_sem4; +static OS_MUTEX car_can_mtx; + +static void taskPutIoState(void *p_arg); + +/** + * @brief return the space left in Queue for debug purposes + */ +#ifdef DEBUG +uint8_t GetSendCarCanQueueSpace(void) { + return (can_fifo.get - can_fifo.put - 1) % + (sizeof can_fifo.buffer / sizeof can_fifo.buffer[0]); +} +#endif + +/** + * @brief Wrapper to put new message in the CAN queue + */ +void SendCarCanPut(CanData message) { + OS_ERR err = OS_ERR_NONE; + CPU_TS ticks = 0; + bool success = false; + + static uint8_t carcan_ctr = 0; + + if (carcan_ctr > SENDCARCAN_MSG_SKIP_CTR) { + OSMutexPend(&car_can_mtx, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); + ASSERT_OS_ERROR(err); + + success = QueuePut(&can_fifo, message); + + OSMutexPost(&car_can_mtx, OS_OPT_POST_NONE, &err); + ASSERT_OS_ERROR(err); + + carcan_ctr = 0; + } + carcan_ctr++; + + if (success) { + OSSemPost(&car_can_sem4, OS_OPT_POST_1, &err); + ASSERT_OS_ERROR(err); + } +} + +/** + * @brief Initialize SendCarCAN + */ +void SendCarCanInit(void) { + OS_ERR err = 0; + + OSMutexCreate(&car_can_mtx, "CarCAN_Mtx", &err); + ASSERT_OS_ERROR(err); + + OSSemCreate(&car_can_sem4, "CarCAN_Sem4", 0, &err); + ASSERT_OS_ERROR(err); + + QueueRenew(&can_fifo); +} + +/** + * @brief Grabs the latest messages from the queue and sends over CarCAN + */ +void TaskSendCarCan(void *p_arg) { + OS_ERR err = 0; + CPU_TS ticks = 0; + + CanData message; + memset(&message, 0, sizeof message); + + // PutIOState + OSTaskCreate((OS_TCB *)&put_io_state_tcb, (CPU_CHAR *)"PutIOState", + (OS_TASK_PTR)taskPutIoState, (void *)NULL, + (OS_PRIO)TASK_PUT_IOSTATE_PRIO, (CPU_STK *)put_io_state_stk, + (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, + (CPU_STK_SIZE)TASK_SEND_CAR_CAN_STACK_SIZE, (OS_MSG_QTY)0, + (OS_TICK)0, (void *)NULL, (OS_OPT)(OS_OPT_TASK_STK_CLR), + (OS_ERR *)&err); + ASSERT_OS_ERROR(err); + + while (1) { + // Check if there's something to send in the queue (either IOState or + // Car state from sendTritium) + OSSemPend(&car_can_sem4, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); + ASSERT_OS_ERROR(err); + + OSMutexPend(&car_can_mtx, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); + ASSERT_OS_ERROR(err); + + bool res = QueueGet(&can_fifo, &message); + + OSMutexPost(&car_can_mtx, OS_OPT_POST_NONE, &err); + ASSERT_OS_ERROR(err); + + if (res) { + CanBusSend(message, true, CARCAN); + } +#ifdef MOCKING + break; +#endif + } +} + +static void putIOState(void) { + CanData message; + memset(&message, 0, sizeof message); + message.id = kIoState; + + // Get pedal information + message.data[0] = PedalsRead(kAccelerator); + message.data[1] = PedalsRead(kBrake); + + // Get minion information + for (Pin pin = 0; pin < kNumPins; pin++) { + bool pin_state = MinionsRead(pin); + message.data[2] |= pin_state << pin; + } + + // Get contactor info + for (Contactor contactor = 0; contactor < kNumContactors; contactor++) { + bool contactor_state = (ContactorsGet(contactor) == ON) ? true : false; + message.data[3] |= contactor_state << contactor; + } + + // Tell BPS if the array contactor should be on + message.data[3] |= (MinionsRead(kIgn1) || MinionsRead(kIgn2)) << 2; + + CanBusSend(message, true, CARCAN); +} + +/** + * @brief sends IO information over CarCAN every IO_STATE_DLY_MS + */ +static void taskPutIoState(void *p_arg) { + OS_ERR err = 0; + while (1) { + putIOState(); + OSTimeDlyHMSM(0, 0, 0, IO_STATE_DLY_MS, OS_OPT_TIME_HMSM_STRICT, &err); + ASSERT_OS_ERROR(err); +#ifdef MOCKING + break; +#endif + } +} diff --git a/Apps/Src/SendTritium.c b/Apps/Src/SendTritium.c index 9f6f85307..414271860 100644 --- a/Apps/Src/SendTritium.c +++ b/Apps/Src/SendTritium.c @@ -2,149 +2,151 @@ * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file SendTritium.c * @brief Function implementations for the SendTritium application. - * - * This contains functions relevant to updating the velocity and current setpoitns - * of the Tritium motor controller. The implementation includes a normal current - * controlled mode, a one-pedal driving mode (with regenerative braking), and cruise control. - * The logic is determined through a finite state machine implementation. - * - * If the macro SENDTRITIUM_EXPOSE_VARS is defined prior to including SendTritium.h, - * relevant setters will be exposed as externs for unit testing - * and hardware inputs won't be read and motor commands won't be sent over MotorCAN. - * If the macro SENDTRITIUM_PRINT_MES is also defined prior to including SendTritium.h, - * debug info will be printed via UART. + * + * This contains functions relevant to updating the velocity and current + * setpoitns of the Tritium motor controller. The implementation includes a + * normal current controlled mode, a one-pedal driving mode (with regenerative + * braking), and cruise control. The logic is determined through a finite state + * machine implementation. + * + * If the macro SENDTRITIUM_EXPOSE_VARS is defined prior to including + * SendTritium.h, relevant setters will be exposed as externs for unit testing + * and hardware inputs won't be read and motor commands won't be sent over + * MotorCAN. If the macro SENDTRITIUM_PRINT_MES is also defined prior to + * including SendTritium.h, debug info will be printed via UART. */ -#include "Pedals.h" -#include "ReadCarCAN.h" -#include "Minions.h" #include "SendTritium.h" + +#include "CanBus.h" +#include "CanConfig.h" +#include "Minions.h" +#include "Pedals.h" +#include "ReadCarCan.h" #include "ReadTritium.h" -#include "SendCarCAN.h" -#include "CANbus.h" +#include "SendCarCan.h" #include "UpdateDisplay.h" -#include "CANConfig.h" #include "common.h" // Macros -#define MAX_VELOCITY 20000.0f // rpm (unobtainable value) +#define MAX_VELOCITY 20000.0f // rpm (unobtainable value) -#define MIN_CRUISE_VELOCITY mpsToRpm(20.0f) // rpm -#define MAX_GEARSWITCH_VELOCITY mpsToRpm(8.0f) // rpm +#define MIN_CRUISE_VELOCITY MpsToRpm(20.0f) // rpm +#define MAX_GEARSWITCH_VELOCITY MpsToRpm(8.0f) // rpm #define BRAKE_PEDAL_THRESHOLD 50 // percent -#define ACCEL_PEDAL_THRESHOLD 10 // percent +#define ACCEL_PEDAL_THRESHOLD 10 // percent -#define ONEPEDAL_BRAKE_THRESHOLD 25 // percent -#define ONEPEDAL_NEUTRAL_THRESHOLD 35 // percent +#define ONEPEDAL_BRAKE_THRESHOLD 25 // percent +#define ONEPEDAL_NEUTRAL_THRESHOLD 35 // percent -#define PEDAL_MIN 0 // percent -#define PEDAL_MAX 100 // percent -#define CURRENT_SP_MIN 0 // percent -#define CURRENT_SP_MAX 100 // percent +#define PEDAL_MIN 0 // percent +#define PEDAL_MAX 100 // percent +#define CURRENT_SP_MIN 0 // percent +#define CURRENT_SP_MAX 100 // percent -#define GEAR_FAULT_THRESHOLD 3 // number of times gear fault can occur before it is considered a fault +#define GEAR_FAULT_THRESHOLD \ + 3 // number of times gear fault can occur before it is considered a fault // Inputs -static bool cruiseEnable = false; -static bool cruiseSet = false; -static bool onePedalEnable = false; -static bool regenEnable = false; +static bool cruise_enable = false; +static bool cruise_set = false; +static bool one_pedal_enable = false; +static bool regen_enable = false; -static uint8_t brakePedalPercent = 0; -static uint8_t accelPedalPercent = 0; +static uint8_t brake_pedal_percent = 0; +static uint8_t accel_pedal_percent = 0; -static Gear_t gear = NEUTRAL_GEAR; +static Gear gear = kNeutralGear; // Outputs -float currentSetpoint = 0; -float velocitySetpoint = 0; -float cruiseVelSetpoint = 0; +float current_setpoint = 0; +float velocity_setpoint = 0; +float cruise_vel_setpoint = 0; // Current observed velocity -static float velocityObserved = 0; +static float velocity_observed = 0; +#ifndef SENDTRITIUM_EXPOSE_VARS // Counter for sending setpoints to motor -static uint8_t motorMsgCounter = 0; +static uint8_t motor_msg_counter = 0; // Debouncing counters -static uint8_t onePedalCounter = 0; -static uint8_t cruiseEnableCounter = 0; -static uint8_t cruiseSetCounter = 0; +static uint8_t one_pedal_counter = 0; +static uint8_t cruise_enable_counter = 0; +static uint8_t cruise_set_counter = 0; // Button states -static bool onePedalButton = false; -static bool onePedalPrevious = false; +static bool one_pedal_button = false; +static bool one_pedal_previous = false; -static bool cruiseEnableButton = false; -static bool cruiseEnablePrevious = false; +static bool cruise_enable_button = false; +static bool cruise_enable_previous = false; +#endif // FSM -static TritiumState_t prevState; // Previous state -static TritiumState_t state; // Current state - -// Getter functions for local variables in SendTritium.c -GETTER(bool, cruiseEnable) -GETTER(bool, cruiseSet) -GETTER(bool, onePedalEnable) -GETTER(bool, regenEnable) -GETTER(uint8_t, brakePedalPercent) -GETTER(uint8_t, accelPedalPercent) -GETTER(Gear_t, gear) -GETTER(TritiumState_t, state) -GETTER(float, velocityObserved) -GETTER(float, cruiseVelSetpoint) -GETTER(float, currentSetpoint) -GETTER(float, velocitySetpoint) - -// Setter functions for local variables in SendTritium.c +static TritiumState prev_state; // Previous state +static TritiumState state; // Current state + +bool GetCruiseEnable(void) { return cruise_enable; } +bool GetCruiseSet(void) { return cruise_set; } +bool GetOnePedalEnable(void) { return one_pedal_enable; } +bool GetRegenEnable(void) { return regen_enable; } +uint8_t GetBrakePedalPercent(void) { return brake_pedal_percent; } +uint8_t GetAccelPedalPercent(void) { return accel_pedal_percent; } +Gear GetGear(void) { return gear; } +TritiumState GetState(void) { return state; } +float GetVelocityObserved(void) { return velocity_observed; } +float GetCruiseVelSetpoint(void) { return cruise_vel_setpoint; } +float GetCurrentSetpoint(void) { return current_setpoint; } +float GetVelocitySetpoint(void) { return velocity_setpoint; } + #ifdef SENDTRITIUM_EXPOSE_VARS -SETTER(bool, cruiseEnable) -SETTER(bool, cruiseSet) -SETTER(bool, onePedalEnable) -SETTER(bool, regenEnable) -SETTER(uint8_t, brakePedalPercent) -SETTER(uint8_t, accelPedalPercent) -SETTER(Gear_t, gear) -SETTER(TritiumState_t, state) -SETTER(float, velocityObserved) -SETTER(float, cruiseVelSetpoint) -SETTER(float, currentSetpoint) -SETTER(float, velocitySetpoint) +void SetCruiseEnable(bool value) { cruise_enable = value; } +void SetCruiseSet(bool value) { cruise_set = value; } +void SetOnePedalEnable(bool value) { one_pedal_enable = value; } +void SetRegenEnable(bool value) { regen_enable = value; } +void SetBrakePedalPercent(uint8_t value) { brake_pedal_percent = value; } +void SetAccelPedalPercent(uint8_t value) { accel_pedal_percent = value; } +void SetGear(Gear value) { gear = value; } +void SetState(TritiumState value) { state = value; } +void SetVelocityObserved(float value) { velocity_observed = value; } +void SetCruiseVelSetpoint(float value) { cruise_vel_setpoint = value; } +void SetCurrentSetpoint(float value) { current_setpoint = value; } +void SetVelocitySetpoint(float value) { velocity_setpoint = value; } #endif // Handler & Decider Declarations -static void ForwardDriveHandler(void); -static void ForwardDriveDecider(void); -static void NeutralDriveHandler(void); -static void NeutralDriveDecider(void); -static void ReverseDriveHandler(void); -static void ReverseDriveDecider(void); -static void RecordVelocityHandler(void); -static void RecordVelocityDecider(void); -static void PoweredCruiseHandler(void); -static void PoweredCruiseDecider(void); -static void CoastingCruiseHandler(void); -static void CoastingCruiseDecider(void); -static void BrakeHandler(void); -static void BrakeDecider(void); -static void OnePedalDriveHandler(void); -static void OnePedalDriveDecider(void); -static void AccelerateCruiseHandler(void); -static void AccelerateCruiseDecider(void); +static void forwardDriveHandler(void); +static void forwardDriveDecider(void); +static void neutralDriveHandler(void); +static void neutralDriveDecider(void); +static void reverseDriveHandler(void); +static void reverseDriveDecider(void); +static void recordVelocityHandler(void); +static void recordVelocityDecider(void); +static void poweredCruiseHandler(void); +static void poweredCruiseDecider(void); +static void coastingCruiseHandler(void); +static void coastingCruiseDecider(void); +static void brakeHandler(void); +static void brakeDecider(void); +static void onePedalDriveHandler(void); +static void onePedalDriveDecider(void); +static void accelerateCruiseHandler(void); +static void accelerateCruiseDecider(void); // FSM -static const TritiumState_t FSM[9] = { - {FORWARD_DRIVE, &ForwardDriveHandler, &ForwardDriveDecider}, - {NEUTRAL_DRIVE, &NeutralDriveHandler, &NeutralDriveDecider}, - {REVERSE_DRIVE, &ReverseDriveHandler, &ReverseDriveDecider}, - {RECORD_VELOCITY, &RecordVelocityHandler, &RecordVelocityDecider}, - {POWERED_CRUISE, &PoweredCruiseHandler, &PoweredCruiseDecider}, - {COASTING_CRUISE, &CoastingCruiseHandler, &CoastingCruiseDecider}, - {BRAKE_STATE, &BrakeHandler, &BrakeDecider}, - {ONEPEDAL, &OnePedalDriveHandler, &OnePedalDriveDecider}, - {ACCELERATE_CRUISE, &AccelerateCruiseHandler, &AccelerateCruiseDecider} -}; +static const TritiumState kFsm[9] = { + {kForwardDrive, &forwardDriveHandler, &forwardDriveDecider}, + {kNeutralDrive, &neutralDriveHandler, &neutralDriveDecider}, + {kReverseDrive, &reverseDriveHandler, &reverseDriveDecider}, + {kRecordVelocity, &recordVelocityHandler, &recordVelocityDecider}, + {kPoweredCruise, &poweredCruiseHandler, &poweredCruiseDecider}, + {kCoastingCruise, &coastingCruiseHandler, &coastingCruiseDecider}, + {kBrakeState, &brakeHandler, &brakeDecider}, + {kOnePedal, &onePedalDriveHandler, &onePedalDriveDecider}, + {kAccelerateCruise, &accelerateCruiseHandler, &accelerateCruiseDecider}}; // Helper Functions @@ -152,69 +154,71 @@ static const TritiumState_t FSM[9] = { * @brief Converts integer percentage to float percentage * @param percent integer percentage from 0-100 * @returns float percentage from 0.0-1.0 -*/ -extern const float pedalToPercent[]; -static float percentToFloat(uint8_t percent){ - if(percent > 100){ - return 1.0f; + */ +extern const float kPedalToPercent[]; +static float percentToFloat(uint8_t percent) { + if (percent > 100) { + return 1.0F; } - return pedalToPercent[percent]; + return kPedalToPercent[percent]; } #ifdef SENDTRITIUM_PRINT_MES + +#define STATE_NAME_STR_SIZE 20 + /** * @brief Dumps info to UART during testing -*/ -static void getName(char* nameStr, uint8_t stateNameNum){ - switch(stateNameNum){ - case FORWARD_DRIVE: - strcpy(nameStr, "FORWARD_DRIVE"); + */ +static void getName(char* name_str, uint8_t state_name_num) { + switch (state_name_num) { + case kForwardDrive: + strcpy(name_str, "FORWARD_DRIVE"); break; - case NEUTRAL_DRIVE: - strcpy(nameStr, "NEUTRAL_DRIVE"); + case kNeutralDrive: + strcpy(name_str, "NEUTRAL_DRIVE"); break; - case REVERSE_DRIVE: - strcpy(nameStr, "REVERSE_DRIVE"); + case kReverseDrive: + strcpy(name_str, "REVERSE_DRIVE"); break; - case RECORD_VELOCITY: - strcpy(nameStr, "RECORD_VELOCITY"); + case kRecordVelocity: + strcpy(name_str, "RECORD_VELOCITY"); break; - case POWERED_CRUISE: - strcpy(nameStr, "POWERED_CRUISE"); + case kPoweredCruise: + strcpy(name_str, "POWERED_CRUISE"); break; - case COASTING_CRUISE: - strcpy(nameStr, "COASTING_CRUISE"); + case kCoastingCruise: + strcpy(name_str, "COASTING_CRUISE"); break; - case BRAKE_STATE: - strcpy(nameStr, "BRAKE_STATE"); + case kBrakeState: + strcpy(name_str, "BRAKE_STATE"); break; - case ONEPEDAL: - strcpy(nameStr, "ONEPEDAL"); + case kOnePedal: + strcpy(name_str, "ONEPEDAL"); break; - case ACCELERATE_CRUISE: - strcpy(nameStr, "ACCELERATE_CRUISE"); + case kAccelerateCruise: + strcpy(name_str, "ACCELERATE_CRUISE"); break; default: - strcpy(nameStr, "UNKNOWN"); + strcpy(name_str, "UNKNOWN"); break; } - return; } -static void dumpInfo(){ +static void dumpInfo() { printf("-------------------\n\r"); - char stateName[20]; - getName(stateName, state.name); - printf("State: %s\n\r", stateName); - printf("cruiseEnable: %d\n\r", cruiseEnable); - printf("cruiseSet: %d\n\r", cruiseSet); - printf("onePedalEnable: %d\n\r", onePedalEnable); - printf("brakePedalPercent: %d\n\r", brakePedalPercent); - printf("accelPedalPercent: %d\n\r", accelPedalPercent); + char state_name[STATE_NAME_STR_SIZE]; + getName(state_name, state.name); + printf("State: %s\n\r", state_name); + printf("cruiseEnable: %d\n\r", cruise_enable); + printf("cruiseSet: %d\n\r", cruise_set); + printf("onePedalEnable: %d\n\r", one_pedal_enable); + printf("brakePedalPercent: %d\n\r", brake_pedal_percent); + printf("accelPedalPercent: %d\n\r", accel_pedal_percent); printf("gear: %d\n\r", (uint8_t)gear); - print_float("currentSetpoint: ", currentSetpoint); - print_float("velocitySetpoint: ", velocitySetpoint); - print_float("velocityObserved: ", velocityObserved); + PrintFloat("currentSetpoint: ", current_setpoint); + PrintFloat("velocitySetpoint: ", velocity_setpoint); + PrintFloat("velocityObserved: ", velocity_observed); printf("-------------------\n\r"); } #endif @@ -222,416 +226,472 @@ static void dumpInfo(){ #ifndef SENDTRITIUM_EXPOSE_VARS /** * @brief Reads inputs from the system -*/ -static void readInputs(){ - + */ +static void readInputs() { // Update pedals - brakePedalPercent = Pedals_Read(BRAKE); - accelPedalPercent = Pedals_Read(ACCELERATOR); - + brake_pedal_percent = PedalsRead(kBrake); + accel_pedal_percent = PedalsRead(kAccelerator); + // Update regen enable - regenEnable = ChargeEnable_Get(); + regen_enable = ChargeEnableGet(); // Update buttons - if(Minions_Read(REGEN_SW) && onePedalCounter < DEBOUNCE_PERIOD){onePedalCounter++;} - else if(onePedalCounter > 0){onePedalCounter--;} + if (MinionsRead(kRegenSw) && one_pedal_counter < DEBOUNCE_PERIOD) { + one_pedal_counter++; + } else if (one_pedal_counter > 0) { + one_pedal_counter--; + } + + if (MinionsRead(kCruzEn) && cruise_enable_counter < DEBOUNCE_PERIOD) { + cruise_enable_counter++; + } else if (cruise_enable_counter > 0) { + cruise_enable_counter--; + } - if(Minions_Read(CRUZ_EN) && cruiseEnableCounter < DEBOUNCE_PERIOD){cruiseEnableCounter++;} - else if(cruiseEnableCounter > 0){cruiseEnableCounter--;} + if (MinionsRead(kCruzSt) && cruise_set_counter < DEBOUNCE_PERIOD) { + cruise_set_counter++; + } else if (cruise_set_counter > 0) { + cruise_set_counter--; + } - if(Minions_Read(CRUZ_ST) && cruiseSetCounter < DEBOUNCE_PERIOD){cruiseSetCounter++;} - else if(cruiseSetCounter > 0){cruiseSetCounter--;} - // Update gears - bool forwardSwitch = Minions_Read(FOR_SW); - bool reverseSwitch = Minions_Read(REV_SW); - bool forwardGear = (forwardSwitch && !reverseSwitch); - bool reverseGear = (!forwardSwitch && reverseSwitch); - bool neutralGear = (!forwardSwitch && !reverseSwitch); + bool forward_switch = MinionsRead(kForSw); + bool reverse_switch = MinionsRead(kRevSw); + bool forward_gear = (forward_switch && !reverse_switch); + bool reverse_gear = (!forward_switch && reverse_switch); + bool neutral_gear = (!forward_switch && !reverse_switch); - uint8_t gearFault = (uint8_t) forwardGear + (uint8_t) reverseGear + (uint8_t) neutralGear; - static uint8_t gearFaultCnt = 0; + uint8_t gear_fault = + (uint8_t)forward_gear + (uint8_t)reverse_gear + (uint8_t)neutral_gear; + static uint8_t gear_fault_cnt = 0; - if(gearFault != 1){ + if (gear_fault != 1) { // Fault behavior - if(gearFaultCnt > GEAR_FAULT_THRESHOLD) state = FSM[NEUTRAL_DRIVE]; - else gearFaultCnt++; - } - else{ - gearFaultCnt = 0; + if (gear_fault_cnt > GEAR_FAULT_THRESHOLD) { + state = kFsm[kNeutralDrive]; + } else { + gear_fault_cnt++; + } + } else { + gear_fault_cnt = 0; } - if(neutralGear) gear = NEUTRAL_GEAR; - else if(forwardGear) gear = FORWARD_GEAR; - else if(reverseGear) gear = REVERSE_GEAR; - else gear = NEUTRAL_GEAR; + if (forward_gear) { + gear = kForwardGear; + } else if (reverse_gear) { + gear = kReverseGear; + } else { + gear = kNeutralGear; + } // Debouncing - if(onePedalCounter == DEBOUNCE_PERIOD){onePedalButton = true;} - else if(onePedalCounter == 0){onePedalButton = false;} + if (one_pedal_counter == DEBOUNCE_PERIOD) { + one_pedal_button = true; + } else if (one_pedal_counter == 0) { + one_pedal_button = false; + } - if(cruiseEnableCounter == DEBOUNCE_PERIOD){cruiseEnableButton = true;} - else if(cruiseEnableCounter == 0){cruiseEnableButton = false;} + if (cruise_enable_counter == DEBOUNCE_PERIOD) { + cruise_enable_button = true; + } else if (cruise_enable_counter == 0) { + cruise_enable_button = false; + } - if(cruiseSetCounter == DEBOUNCE_PERIOD){cruiseSet = true;} - else if(cruiseSetCounter == 0){cruiseSet = false;} + if (cruise_set_counter == DEBOUNCE_PERIOD) { + cruise_set = true; + } else if (cruise_set_counter == 0) { + cruise_set = false; + } // Toggle - if(onePedalButton != onePedalPrevious && onePedalPrevious){onePedalEnable = !onePedalEnable;} - if(!regenEnable) onePedalEnable = false; - onePedalPrevious = onePedalButton; - - if(cruiseEnableButton != cruiseEnablePrevious && cruiseEnablePrevious){cruiseEnable = !cruiseEnable;} - cruiseEnablePrevious = cruiseEnableButton; - + if (one_pedal_button != one_pedal_previous && one_pedal_previous) { + one_pedal_enable = !one_pedal_enable; + } + if (!regen_enable) { + one_pedal_enable = false; + } + one_pedal_previous = one_pedal_button; + + if (cruise_enable_button != cruise_enable_previous && + cruise_enable_previous) { + cruise_enable = !cruise_enable; + } + cruise_enable_previous = cruise_enable_button; + // Get observed velocity - velocityObserved = Motor_RPM_Get(); + velocity_observed = MotorRpmGet(); } #endif /** - * @brief Linearly map range of integers to another range of integers. + * @brief Linearly map range of integers to another range of integers. * in_min to in_max is mapped to out_min to out_max. * @param input input integer value * @param in_min minimum value of input range * @param in_max maximum value of input range * @param out_min minimum value of output range - * @param out_max maximum value of output range + * @param out_max maximum value of output range * @returns integer value from out_min to out_max -*/ -static uint8_t map(uint8_t input, uint8_t in_min, uint8_t in_max, uint8_t out_min, uint8_t out_max){ - if(in_min >= in_max) in_max = in_min; // The minimum of the input range should never be greater than the maximum of the input range - - if(input <= in_min){ + */ +static uint8_t map(uint8_t input, uint8_t in_min, uint8_t in_max, + uint8_t out_min, uint8_t out_max) { + if (in_min >= in_max) { + in_max = in_min; // The minimum of the input range should never be + // greater than the maximum of the input range + } + + if (input <= in_min) { // Lower bound the input to the minimum possible output return out_min; - } else if(input >= in_max){ + } + if (input >= in_max) { // Upper bound the input to the maximum output return out_max; - } else{ - // Linear mapping between ranges - uint8_t offset_in = input - in_min; // If input went from A -> B, it now goes from 0 -> B-A - uint8_t in_range = in_max - in_min; // Input range - uint8_t out_range = out_max - out_min; // Output range - uint8_t offset_out = out_min; - return (offset_in * out_range)/in_range + offset_out; // slope = out_range/in_range. y=mx+b so output=slope*offset_in+offset_out - } + } // Linear mapping between ranges + uint8_t offset_in = + input - in_min; // If input went from A -> B, it now goes from 0 -> B-A + uint8_t in_range = in_max - in_min; // Input range + uint8_t out_range = out_max - out_min; // Output range + uint8_t offset_out = out_min; + return (offset_in * out_range) / in_range + + offset_out; // slope = out_range/in_range. y=mx+b so + // output=slope*offset_in+offset_out } - /** - * @brief Put the CONTROL_MODE message onto the CarCAN bus, detailing + * @brief Put the kControlMode message onto the CarCAN bus, detailing * the current mode of control. -*/ -static void putControlModeCAN(){ - CANDATA_t message; + */ +static void putControlModeCAN() { + CanData message; memset(&message, 0, sizeof(message)); - message.ID = CONTROL_MODE; + message.id = kControlMode; message.data[0] = state.name; - SendCarCAN_Put(message); + SendCarCanPut(message); } // State Handlers & Deciders /** - * @brief Forward Drive State Handler. Accelerator is mapped directly + * @brief Forward Drive State Handler. Accelerator is mapped directly * to current setpoint at positive velocity. -*/ -static void ForwardDriveHandler(){ - if(prevState.name != state.name){ - UpdateDisplay_SetCruiseState(DISP_DISABLED); - UpdateDisplay_SetRegenState(DISP_DISABLED); - UpdateDisplay_SetGear(DISP_FORWARD); - } - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = percentToFloat(map(accelPedalPercent, ACCEL_PEDAL_THRESHOLD, PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); + */ +static void forwardDriveHandler() { + if (prev_state.name != state.name) { + UpdateDisplaySetCruiseState(DISP_DISABLED); + UpdateDisplaySetRegenState(DISP_DISABLED); + UpdateDisplaySetGear(DISP_FORWARD); + } + velocity_setpoint = MAX_VELOCITY; + current_setpoint = + percentToFloat(map(accel_pedal_percent, ACCEL_PEDAL_THRESHOLD, + PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); } /** * @brief Forward Drive State Decider. Determines transitions out of * forward drive state (brake, record velocity, one pedal, neutral drive). -*/ -static void ForwardDriveDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - }else if(cruiseSet && cruiseEnable && velocityObserved >= MIN_CRUISE_VELOCITY){ - state = FSM[RECORD_VELOCITY]; - }else if(onePedalEnable){ - state = FSM[ONEPEDAL]; - }else if(gear == NEUTRAL_GEAR || gear == REVERSE_GEAR){ - state = FSM[NEUTRAL_DRIVE]; + */ +static void forwardDriveDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (cruise_set && cruise_enable && + velocity_observed >= MIN_CRUISE_VELOCITY) { + state = kFsm[kRecordVelocity]; + } else if (one_pedal_enable) { + state = kFsm[kOnePedal]; + } else if (gear == kNeutralGear || gear == kReverseGear) { + state = kFsm[kNeutralDrive]; } } /** * @brief Neutral Drive State Handler. No current is sent to the motor. -*/ -static void NeutralDriveHandler(){ - if(prevState.name != state.name){ - UpdateDisplay_SetCruiseState(DISP_DISABLED); - UpdateDisplay_SetRegenState(DISP_DISABLED); - UpdateDisplay_SetGear(DISP_NEUTRAL); - } - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = 0.0f; - - cruiseEnable = false; - onePedalEnable = false; + */ +static void neutralDriveHandler() { + if (prev_state.name != state.name) { + UpdateDisplaySetCruiseState(DISP_DISABLED); + UpdateDisplaySetRegenState(DISP_DISABLED); + UpdateDisplaySetGear(DISP_NEUTRAL); + } + velocity_setpoint = MAX_VELOCITY; + current_setpoint = 0.0F; + + cruise_enable = false; + one_pedal_enable = false; } /** * @brief Neutral Drive State Decider. Determines transitions out of * neutral drive state (brake, forward drive, reverse drive). -*/ -static void NeutralDriveDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - }else if(gear == FORWARD_GEAR && velocityObserved >= -MAX_GEARSWITCH_VELOCITY){ - state = FSM[FORWARD_DRIVE]; - }else if(gear == REVERSE_GEAR && velocityObserved <= MAX_GEARSWITCH_VELOCITY){ - state = FSM[REVERSE_DRIVE]; + */ +static void neutralDriveDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (gear == kForwardGear && + velocity_observed >= -MAX_GEARSWITCH_VELOCITY) { + state = kFsm[kForwardDrive]; + } else if (gear == kReverseGear && + velocity_observed <= MAX_GEARSWITCH_VELOCITY) { + state = kFsm[kReverseDrive]; } } /** - * @brief Reverse Drive State Handler. Accelerator is mapped directly to + * @brief Reverse Drive State Handler. Accelerator is mapped directly to * current setpoint (at negative velocity). -*/ -static void ReverseDriveHandler(){ - if(prevState.name != state.name){ - UpdateDisplay_SetCruiseState(DISP_DISABLED); - UpdateDisplay_SetRegenState(DISP_DISABLED); - UpdateDisplay_SetGear(DISP_REVERSE); - } - velocitySetpoint = -MAX_VELOCITY; - currentSetpoint = percentToFloat(map(accelPedalPercent, ACCEL_PEDAL_THRESHOLD, PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); - cruiseEnable = false; - onePedalEnable = false; + */ +static void reverseDriveHandler() { + if (prev_state.name != state.name) { + UpdateDisplaySetCruiseState(DISP_DISABLED); + UpdateDisplaySetRegenState(DISP_DISABLED); + UpdateDisplaySetGear(DISP_REVERSE); + } + velocity_setpoint = -MAX_VELOCITY; + current_setpoint = + percentToFloat(map(accel_pedal_percent, ACCEL_PEDAL_THRESHOLD, + PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); + cruise_enable = false; + one_pedal_enable = false; } /** * @brief Reverse Drive State Decider. Determines transitions out of * reverse drive state (brake, neutral drive). -*/ -static void ReverseDriveDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - } - else if(gear == NEUTRAL_GEAR || gear == FORWARD_GEAR){ - state = FSM[NEUTRAL_DRIVE]; + */ +static void reverseDriveDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (gear == kNeutralGear || gear == kForwardGear) { + state = kFsm[kNeutralDrive]; } } /** - * @brief Record Velocity State. While pressing the cruise set button, + * @brief Record kVelocity State. While pressing the cruise set button, * the car will record the observed velocity into velocitySetpoint. -*/ -static void RecordVelocityHandler(){ - if(prevState.name != state.name){ - UpdateDisplay_SetCruiseState(DISP_ACTIVE); - UpdateDisplay_SetRegenState(DISP_DISABLED); - UpdateDisplay_SetGear(DISP_FORWARD); + */ +static void recordVelocityHandler() { + if (prev_state.name != state.name) { + UpdateDisplaySetCruiseState(DISP_ACTIVE); + UpdateDisplaySetRegenState(DISP_DISABLED); + UpdateDisplaySetGear(DISP_FORWARD); } // put car in neutral while recording velocity (while button is held) - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = 0; - cruiseVelSetpoint = velocityObserved; + velocity_setpoint = MAX_VELOCITY; + current_setpoint = 0; + cruise_vel_setpoint = velocity_observed; } /** - * @brief Record Velocity State Decider. Determines transitions out of record velocity - * state (brake, neutral drive, one pedal, forward drive, powered cruise). -*/ -static void RecordVelocityDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - }else if(gear == NEUTRAL_GEAR || gear == REVERSE_GEAR){ - state = FSM[NEUTRAL_DRIVE]; - }else if(onePedalEnable){ - cruiseEnable = false; - state = FSM[ONEPEDAL]; - }else if(!cruiseEnable){ - state = FSM[FORWARD_DRIVE]; - }else if(cruiseEnable && !cruiseSet){ - state = FSM[POWERED_CRUISE]; + * @brief Record kVelocity State Decider. Determines transitions out of record + * velocity state (brake, neutral drive, one pedal, forward drive, powered + * cruise). + */ +static void recordVelocityDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (gear == kNeutralGear || gear == kReverseGear) { + state = kFsm[kNeutralDrive]; + } else if (one_pedal_enable) { + cruise_enable = false; + state = kFsm[kOnePedal]; + } else if (!cruise_enable) { + state = kFsm[kForwardDrive]; + } else if (cruise_enable && !cruise_set) { + state = kFsm[kPoweredCruise]; } } /** - * @brief Powered Cruise State. Continue to travel at the recorded velocity as long as - * Observed Velocity <= Velocity Setpoint -*/ -static void PoweredCruiseHandler(){ - velocitySetpoint = cruiseVelSetpoint; - currentSetpoint = 1.0f; + * @brief Powered Cruise State. Continue to travel at the recorded velocity as + * long as Observed kVelocity <= kVelocity Setpoint + */ +static void poweredCruiseHandler() { + velocity_setpoint = cruise_vel_setpoint; + current_setpoint = 1.0F; } /** - * @brief Powered Cruise State Decider. Determines transitions out of powered - * cruise state (brake, neutral drive, one pedal, forward drive, record velocity, - * accelerate cruise, coasting cruise). -*/ -static void PoweredCruiseDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - }else if(gear == NEUTRAL_GEAR || gear == REVERSE_GEAR){ - state = FSM[NEUTRAL_DRIVE]; - }else if(onePedalEnable){ - cruiseEnable = false; - state = FSM[ONEPEDAL]; - }else if(!cruiseEnable){ - state = FSM[FORWARD_DRIVE]; - }else if(cruiseSet && velocityObserved >= MIN_CRUISE_VELOCITY){ - state = FSM[RECORD_VELOCITY]; - }else if(accelPedalPercent >= ACCEL_PEDAL_THRESHOLD){ - state = FSM[ACCELERATE_CRUISE]; - }else if(velocityObserved > cruiseVelSetpoint){ - state = FSM[COASTING_CRUISE]; + * @brief Powered Cruise State Decider. Determines transitions out of powered + * cruise state (brake, neutral drive, one pedal, forward drive, record + * velocity, accelerate cruise, coasting cruise). + */ +static void poweredCruiseDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (gear == kNeutralGear || gear == kReverseGear) { + state = kFsm[kNeutralDrive]; + } else if (one_pedal_enable) { + cruise_enable = false; + state = kFsm[kOnePedal]; + } else if (!cruise_enable) { + state = kFsm[kForwardDrive]; + } else if (cruise_set && velocity_observed >= MIN_CRUISE_VELOCITY) { + state = kFsm[kRecordVelocity]; + } else if (accel_pedal_percent >= ACCEL_PEDAL_THRESHOLD) { + state = kFsm[kAccelerateCruise]; + } else if (velocity_observed > cruise_vel_setpoint) { + state = kFsm[kCoastingCruise]; } } /** - * @brief Coasting Cruise State. We do not want to utilize motor braking - * in cruise control mode due to safety issues. Coast the motor (go into neutral) - * if we want to slow down. -*/ -static void CoastingCruiseHandler(){ - velocitySetpoint = cruiseVelSetpoint; - currentSetpoint = 0; + * @brief Coasting Cruise State. We do not want to utilize motor braking + * in cruise control mode due to safety issues. Coast the motor (go into + * neutral) if we want to slow down. + */ +static void coastingCruiseHandler() { + velocity_setpoint = cruise_vel_setpoint; + current_setpoint = 0; } /** - * @brief Coasting Cruise State Decider. Determines transitions out of coasting - * cruise state (brake, neutral drive, one pedal, forward drive, record velocity, - * accelerate cruise, powered cruise). -*/ -static void CoastingCruiseDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - }else if(gear == NEUTRAL_GEAR || gear == REVERSE_GEAR){ - state = FSM[NEUTRAL_DRIVE]; - }else if(onePedalEnable){ - cruiseEnable = false; - state = FSM[ONEPEDAL]; - }else if(!cruiseEnable){ - state = FSM[FORWARD_DRIVE]; - }else if(cruiseSet && velocityObserved >= MIN_CRUISE_VELOCITY){ - state = FSM[RECORD_VELOCITY]; - }else if(accelPedalPercent >= ACCEL_PEDAL_THRESHOLD){ - state = FSM[ACCELERATE_CRUISE]; - }else if(velocityObserved <= cruiseVelSetpoint){ - state = FSM[POWERED_CRUISE]; + * @brief Coasting Cruise State Decider. Determines transitions out of coasting + * cruise state (brake, neutral drive, one pedal, forward drive, record + * velocity, accelerate cruise, powered cruise). + */ +static void coastingCruiseDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (gear == kNeutralGear || gear == kReverseGear) { + state = kFsm[kNeutralDrive]; + } else if (one_pedal_enable) { + cruise_enable = false; + state = kFsm[kOnePedal]; + } else if (!cruise_enable) { + state = kFsm[kForwardDrive]; + } else if (cruise_set && velocity_observed >= MIN_CRUISE_VELOCITY) { + state = kFsm[kRecordVelocity]; + } else if (accel_pedal_percent >= ACCEL_PEDAL_THRESHOLD) { + state = kFsm[kAccelerateCruise]; + } else if (velocity_observed <= cruise_vel_setpoint) { + state = kFsm[kPoweredCruise]; } } /** - * @brief Accelerate Cruise State. In the event that the driver needs to accelerate in cruise - * mode, we will accelerate to the pedal percentage. Upon release of the accelerator - * pedal, we will return to cruise mode at the previously recorded velocity. -*/ -static void AccelerateCruiseHandler(){ - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = percentToFloat(map(accelPedalPercent, ACCEL_PEDAL_THRESHOLD, PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); + * @brief Accelerate Cruise State. In the event that the driver needs to + * accelerate in cruise mode, we will accelerate to the pedal percentage. Upon + * release of the accelerator pedal, we will return to cruise mode at the + * previously recorded velocity. + */ +static void accelerateCruiseHandler() { + velocity_setpoint = MAX_VELOCITY; + current_setpoint = + percentToFloat(map(accel_pedal_percent, ACCEL_PEDAL_THRESHOLD, + PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); } /** - * @brief Accelerate Cruise State Decider. Determines transitions out of accelerate - * cruise state (brake, neutral drive, one pedal, forward drive, record velocity, - * coasting cruise). -*/ -static void AccelerateCruiseDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - }else if(gear == NEUTRAL_GEAR || gear == REVERSE_GEAR){ - state = FSM[NEUTRAL_DRIVE]; - }else if(onePedalEnable){ - cruiseEnable = false; - state = FSM[ONEPEDAL]; - }else if(!cruiseEnable){ - state = FSM[FORWARD_DRIVE]; - }else if(cruiseSet && velocityObserved >= MIN_CRUISE_VELOCITY){ - state = FSM[RECORD_VELOCITY]; - }else if(accelPedalPercent < ACCEL_PEDAL_THRESHOLD){ - state = FSM[COASTING_CRUISE]; + * @brief Accelerate Cruise State Decider. Determines transitions out of + * accelerate cruise state (brake, neutral drive, one pedal, forward drive, + * record velocity, coasting cruise). + */ +static void accelerateCruiseDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (gear == kNeutralGear || gear == kReverseGear) { + state = kFsm[kNeutralDrive]; + } else if (one_pedal_enable) { + cruise_enable = false; + state = kFsm[kOnePedal]; + } else if (!cruise_enable) { + state = kFsm[kForwardDrive]; + } else if (cruise_set && velocity_observed >= MIN_CRUISE_VELOCITY) { + state = kFsm[kRecordVelocity]; + } else if (accel_pedal_percent < ACCEL_PEDAL_THRESHOLD) { + state = kFsm[kCoastingCruise]; } } /** - * @brief One Pedal Drive State. When in one pedal drive, if the accelerator percentage is lower - * than ONEPEDAL_BRAKE_THRESHOLD, the car will utilize motor braking to slow down. If accelerator - * percentage is in the neutral zone, the car will coast. If accelerator percentage is above - * the NEUTRAL_THRESHOLD, the car will accelerate as normal. -*/ -static void OnePedalDriveHandler(){ - if(prevState.name != state.name){ - UpdateDisplay_SetCruiseState(DISP_DISABLED); - UpdateDisplay_SetGear(DISP_FORWARD); - } - if(accelPedalPercent <= ONEPEDAL_BRAKE_THRESHOLD){ + * @brief One Pedal Drive State. When in one pedal drive, if the accelerator + * percentage is lower than ONEPEDAL_BRAKE_THRESHOLD, the car will utilize motor + * braking to slow down. If accelerator percentage is in the neutral zone, the + * car will coast. If accelerator percentage is above the NEUTRAL_THRESHOLD, the + * car will accelerate as normal. + */ +static void onePedalDriveHandler() { + if (prev_state.name != state.name) { + UpdateDisplaySetCruiseState(DISP_DISABLED); + UpdateDisplaySetGear(DISP_FORWARD); + } + if (accel_pedal_percent <= ONEPEDAL_BRAKE_THRESHOLD) { // Regen brake: Map 0 -> brake to 100 -> 0 - velocitySetpoint = 0; - currentSetpoint = percentToFloat(map(accelPedalPercent, PEDAL_MIN, ONEPEDAL_BRAKE_THRESHOLD, CURRENT_SP_MAX, CURRENT_SP_MIN)); - Minions_Write(BRAKELIGHT, true); - UpdateDisplay_SetRegenState(DISP_ACTIVE); - }else if(ONEPEDAL_BRAKE_THRESHOLD < accelPedalPercent && accelPedalPercent <= ONEPEDAL_NEUTRAL_THRESHOLD){ + velocity_setpoint = 0; + current_setpoint = percentToFloat(map(accel_pedal_percent, PEDAL_MIN, + ONEPEDAL_BRAKE_THRESHOLD, + CURRENT_SP_MAX, CURRENT_SP_MIN)); + MinionsWrite(kBrakeLight, true); + UpdateDisplaySetRegenState(DISP_ACTIVE); + } else if (ONEPEDAL_BRAKE_THRESHOLD < accel_pedal_percent && + accel_pedal_percent <= ONEPEDAL_NEUTRAL_THRESHOLD) { // Neutral: coast - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = 0; - Minions_Write(BRAKELIGHT, false); - UpdateDisplay_SetRegenState(DISP_ENABLED); - }else if(ONEPEDAL_NEUTRAL_THRESHOLD < accelPedalPercent){ + velocity_setpoint = MAX_VELOCITY; + current_setpoint = 0; + MinionsWrite(kBrakeLight, false); + UpdateDisplaySetRegenState(DISP_ENABLED); + } else if (ONEPEDAL_NEUTRAL_THRESHOLD < accel_pedal_percent) { // Accelerate: Map neutral -> 100 to 0 -> 100 - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = percentToFloat(map(accelPedalPercent, ONEPEDAL_NEUTRAL_THRESHOLD, PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); - Minions_Write(BRAKELIGHT, false); - UpdateDisplay_SetRegenState(DISP_ENABLED); + velocity_setpoint = MAX_VELOCITY; + current_setpoint = + percentToFloat(map(accel_pedal_percent, ONEPEDAL_NEUTRAL_THRESHOLD, + PEDAL_MAX, CURRENT_SP_MIN, CURRENT_SP_MAX)); + MinionsWrite(kBrakeLight, false); + UpdateDisplaySetRegenState(DISP_ENABLED); } } /** - * @brief One Pedal Drive State Decider. Determines transitions out of one pedal + * @brief One Pedal Drive State Decider. Determines transitions out of one pedal * drive state (brake, record velocity, neutral drive). -*/ -static void OnePedalDriveDecider(){ - if(brakePedalPercent >= BRAKE_PEDAL_THRESHOLD){ - state = FSM[BRAKE_STATE]; - }else if(cruiseSet && cruiseEnable && velocityObserved >= MIN_CRUISE_VELOCITY){ - state = FSM[RECORD_VELOCITY]; - Minions_Write(BRAKELIGHT, false); - }else if(gear == NEUTRAL_GEAR || gear == REVERSE_GEAR){ - state = FSM[NEUTRAL_DRIVE]; - Minions_Write(BRAKELIGHT, false); + */ +static void onePedalDriveDecider() { + if (brake_pedal_percent >= BRAKE_PEDAL_THRESHOLD) { + state = kFsm[kBrakeState]; + } else if (cruise_set && cruise_enable && + velocity_observed >= MIN_CRUISE_VELOCITY) { + state = kFsm[kRecordVelocity]; + MinionsWrite(kBrakeLight, false); + } else if (gear == kNeutralGear || gear == kReverseGear) { + state = kFsm[kNeutralDrive]; + MinionsWrite(kBrakeLight, false); } } /** - * @brief Brake State. When brake pedal is pressed, physical brakes will be active. - * Put motor in neutral to prevent motor braking while physical brakes are engaged. - * Additionally, disable all cruise control and one pedal functionality. -*/ -static void BrakeHandler(){ - if(prevState.name != state.name){ - UpdateDisplay_SetCruiseState(DISP_DISABLED); - UpdateDisplay_SetRegenState(DISP_DISABLED); - UpdateDisplay_SetGear(DISP_FORWARD); - } - velocitySetpoint = MAX_VELOCITY; - currentSetpoint = 0; - cruiseEnable = false; - onePedalEnable = false; - Minions_Write(BRAKELIGHT, true); + * @brief Brake State. When brake pedal is pressed, physical brakes will be + * active. Put motor in neutral to prevent motor braking while physical brakes + * are engaged. Additionally, disable all cruise control and one pedal + * functionality. + */ +static void brakeHandler() { + if (prev_state.name != state.name) { + UpdateDisplaySetCruiseState(DISP_DISABLED); + UpdateDisplaySetRegenState(DISP_DISABLED); + UpdateDisplaySetGear(DISP_FORWARD); + } + velocity_setpoint = MAX_VELOCITY; + current_setpoint = 0; + cruise_enable = false; + one_pedal_enable = false; + MinionsWrite(kBrakeLight, true); } /** - * @brief Brake State Decider. Determines transitions out of brake state (forward drive, - * neutral drive). -*/ -static void BrakeDecider(){ - if(brakePedalPercent < BRAKE_PEDAL_THRESHOLD){ - if(gear == FORWARD_GEAR) state = FSM[FORWARD_DRIVE]; - else if(gear == NEUTRAL_GEAR || gear == REVERSE_GEAR) state = FSM[NEUTRAL_DRIVE]; - Minions_Write(BRAKELIGHT, false); + * @brief Brake State Decider. Determines transitions out of brake state + * (forward drive, neutral drive). + */ +static void brakeDecider() { + if (brake_pedal_percent < BRAKE_PEDAL_THRESHOLD) { + if (gear == kForwardGear) { + state = kFsm[kForwardDrive]; + } else if (gear == kNeutralGear || gear == kReverseGear) { + state = kFsm[kNeutralDrive]; + } + MinionsWrite(kBrakeLight, false); } } @@ -639,57 +699,62 @@ static void BrakeDecider(){ /** * @brief Follows the FSM to update the velocity of the car -*/ -void Task_SendTritium(void *p_arg){ - OS_ERR err; + */ +void TaskSendTritium(void* p_arg) { + OS_ERR err = 0; // Initialize current state to FORWARD_DRIVE - state = FSM[NEUTRAL_DRIVE]; - prevState = FSM[NEUTRAL_DRIVE]; - - #ifndef SENDTRITIUM_EXPOSE_VARS - CANDATA_t driveCmd = { - .ID=MOTOR_DRIVE, - .idx=0, - .data={0.0f, 0.0f}, + state = kFsm[kNeutralDrive]; + prev_state = kFsm[kNeutralDrive]; + +#ifndef SENDTRITIUM_EXPOSE_VARS + CanData drive_cmd = { + .id = kMotorDrive, + .idx = 0, + .data = {0}, }; - #endif +#endif - while(1){ - prevState = state; + while (1) { + prev_state = state; - state.stateHandler(); // do what the current state does - #ifndef SENDTRITIUM_EXPOSE_VARS - readInputs(); // read inputs from the system - UpdateDisplay_SetAccel(accelPedalPercent); - #endif - state.stateDecider(); // decide what the next state is + state.stateHandler(); // do what the current state does +#ifndef SENDTRITIUM_EXPOSE_VARS + readInputs(); // read inputs from the system + UpdateDisplaySetAccel(accel_pedal_percent); +#endif + state.stateDecider(); // decide what the next state is - // Disable velocity controlled mode by always overwriting velocity to the maximum - // in the appropriate direction. - velocitySetpoint = (velocitySetpoint>0)?MAX_VELOCITY:-MAX_VELOCITY; + // Disable velocity controlled mode by always overwriting velocity to + // the maximum in the appropriate direction. + velocity_setpoint = + (velocity_setpoint > 0) ? MAX_VELOCITY : -MAX_VELOCITY; - // Drive - #ifdef SENDTRITIUM_PRINT_MES +// Drive +#ifdef SENDTRITIUM_PRINT_MES dumpInfo(); - #endif - #ifndef SENDTRITIUM_EXPOSE_VARS - if(MOTOR_MSG_COUNTER_THRESHOLD == motorMsgCounter){ - memcpy(&driveCmd.data[4], ¤tSetpoint, sizeof(float)); - memcpy(&driveCmd.data[0], &velocitySetpoint, sizeof(float)); - CANbus_Send(driveCmd, CAN_NON_BLOCKING, MOTORCAN); - motorMsgCounter = 0; - }else{ - motorMsgCounter++; +#endif +#ifndef SENDTRITIUM_EXPOSE_VARS + if (MOTOR_MSG_COUNTER_THRESHOLD == motor_msg_counter) { + memcpy(&drive_cmd.data[4], ¤t_setpoint, sizeof(float)); + memcpy(&drive_cmd.data[0], &velocity_setpoint, sizeof(float)); + CanBusSend(drive_cmd, CAN_NON_BLOCKING, MOTORCAN); + motor_msg_counter = 0; + } else { + motor_msg_counter++; } - #endif +#endif - putControlModeCAN(); + putControlModeCAN(); // Delay of MOTOR_MSG_PERIOD ms OSTimeDlyHMSM(0, 0, 0, MOTOR_MSG_PERIOD, OS_OPT_TIME_HMSM_STRICT, &err); - if (err != OS_ERR_NONE){ - assertOSError(err); + if (err != OS_ERR_NONE) { + ASSERT_OS_ERROR(err); } + +#ifdef MOCKING + break; +#endif } } diff --git a/Apps/Src/Tasks.c b/Apps/Src/Tasks.c index af6382e1d..5af73d707 100644 --- a/Apps/Src/Tasks.c +++ b/Apps/Src/Tasks.c @@ -1,171 +1,192 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Tasks.c - * @brief - * + * @brief + * */ #include "Tasks.h" -#include "os.h" -#include "CANbus.h" + +#include "CanBus.h" #include "Contactors.h" #include "Display.h" #include "Minions.h" #include "Pedals.h" +#include "ReadCarCan.h" #include "ReadTritium.h" -#include "ReadCarCAN.h" #include "UpdateDisplay.h" - +#include "os.h" /** * TCBs */ -OS_TCB Init_TCB; -OS_TCB SendTritium_TCB; -OS_TCB ReadCarCAN_TCB; -OS_TCB UpdateDisplay_TCB; -OS_TCB ReadTritium_TCB; -OS_TCB SendCarCAN_TCB; -OS_TCB DebugDump_TCB; -OS_TCB CommandLine_TCB; +OS_TCB init_tcb; +OS_TCB send_tritium_tcb; +OS_TCB read_car_can_tcb; +OS_TCB update_display_tcb; +OS_TCB read_tritium_tcb; +OS_TCB send_car_can_tcb; +OS_TCB debug_dump_tcb; +OS_TCB command_line_tcb; -task_trace_t PrevTasks; +TaskTrace prev_tasks; /** * Stacks */ -CPU_STK Init_Stk[TASK_INIT_STACK_SIZE]; -CPU_STK SendTritium_Stk[TASK_SEND_TRITIUM_STACK_SIZE]; -CPU_STK ReadCarCAN_Stk[TASK_READ_CAR_CAN_STACK_SIZE]; -CPU_STK UpdateDisplay_Stk[TASK_UPDATE_DISPLAY_STACK_SIZE]; -CPU_STK ReadTritium_Stk[TASK_READ_TRITIUM_STACK_SIZE]; -CPU_STK SendCarCAN_Stk[TASK_SEND_CAR_CAN_STACK_SIZE]; -CPU_STK DebugDump_Stk[TASK_DEBUG_DUMP_STACK_SIZE]; -CPU_STK CommandLine_Stk[TASK_COMMAND_LINE_STACK_SIZE]; - -// Variables to store error codes, stored and cleared in task error assert functions -error_code_t Error_ReadCarCAN = /*READCARCAN_ERR_NONE*/ 0; // TODO: change this back to the error -error_code_t Error_ReadTritium = T_NONE; // Initialized to no error -error_code_t Error_UpdateDisplay = UPDATEDISPLAY_ERR_NONE; - -extern const pinInfo_t PININFO_LUT[]; // For GPIO writes. Externed from Minions Driver C file. +CPU_STK init_stk[TASK_INIT_STACK_SIZE]; +CPU_STK send_tritium_stk[TASK_SEND_TRITIUM_STACK_SIZE]; +CPU_STK read_car_can_stk[TASK_READ_CAR_CAN_STACK_SIZE]; +CPU_STK update_display_stk[TASK_UPDATE_DISPLAY_STACK_SIZE]; +CPU_STK read_tritium_stk[TASK_READ_TRITIUM_STACK_SIZE]; +CPU_STK send_car_can_stk[TASK_SEND_CAR_CAN_STACK_SIZE]; +CPU_STK debug_dump_stk[TASK_DEBUG_DUMP_STACK_SIZE]; +CPU_STK command_line_stk[TASK_COMMAND_LINE_STACK_SIZE]; + +// Variables to store error codes, stored and cleared in task error assert +// functions +ErrorCode error_read_car_can = kReadCarCanErrNone; +ErrorCode error_read_tritium = kNone; // Initialized to no error +ErrorCode error_update_display = kUpdateDisplayErrNone; + +extern const PinInfo + kPininfoLut[]; // For GPIO writes. Externed from Minions Driver C file. /** * Error assertion-related functions -*/ - -void _assertOSError(OS_ERR err) -{ - if (err != OS_ERR_NONE) - { - EmergencyContactorOpen(); // Turn off contactors and turn on the brakelight to indicate an emergency - Display_Error(err); // Display the location and error code - while(1){;} //nonrecoverable + */ +void AssertOsError(volatile OS_ERR err) { + OS_ERR err2 = 0; + if (err != OS_ERR_NONE) { + OSSchedLock(&err2); + EmergencyContactorOpen(); // Turn off contactors and turn on the + // brakelight to indicate an emergency + DisplayFault(err); // Display the location and error code + printf("%d\n\r", err); +#ifndef MOCKING + while (1) {} // nonrecoverable +#endif } } /** - * @brief Assert a task error by locking the scheduler (if necessary), displaying a fault screen, - * and jumping to the error's specified callback function. - * Called by task-specific error-assertion functions that are also responsible for setting the error variable. + * @brief Assert a task error by locking the scheduler (if necessary), + * displaying a fault screen, and jumping to the error's specified callback + * function. Called by task-specific error-assertion functions that are also + * responsible for setting the error variable. * @param errorCode the enum for the specific error that happened - * @param errorCallback a callback function to a handler for that specific error, - * @param lockSched whether or not to lock the scheduler to ensure the error is handled immediately. Only applicable for recoverable errors- nonrecoverable errors will always lock - * @param nonrecoverable whether or not to kill the motor, display the fault screen, and enter an infinite while loop -*/ -void throwTaskError(error_code_t errorCode, callback_t errorCallback, error_scheduler_lock_opt_t lockSched, error_recov_opt_t nonrecoverable) { - OS_ERR err; - - if (errorCode == 0) { // Exit if there is no error + * @param errorCallback a callback function to a handler for that specific + * error, + * @param lockSched whether or not to lock the scheduler to ensure the error is + * handled immediately. Only applicable for recoverable errors- nonrecoverable + * errors will always lock + * @param nonrecoverable whether or not to kill the motor, display the fault + * screen, and enter an infinite while loop + */ +void ThrowTaskError(ErrorCode error_code, Callback error_callback, + ErrorSchedulerLockOpt lock_sched, + ErrorRecovOpt nonrecoverable) { + OS_ERR err = 0; + + if (error_code == 0) { // Exit if there is no error return; } - if (lockSched == OPT_LOCK_SCHED || nonrecoverable == OPT_NONRECOV) { // Prevent other tasks from interrupting the handling of important (includes all nonrecoverable) errors + if (lock_sched == kOptLockSched || + nonrecoverable == + kOptNonrecov) { // Prevent other tasks from interrupting the + // handling of important (includes all + // nonrecoverable) errors OSSchedLock(&err); - assertOSError(err); + ASSERT_OS_ERROR(err); } - if (nonrecoverable == OPT_NONRECOV) { + if (nonrecoverable == kOptNonrecov) { EmergencyContactorOpen(); - Display_Error(errorCode); // Needs to happen before callback so that tasks can change the screen + DisplayFault(error_code); // Needs to happen before callback so that + // tasks can change the screen // (ex: readCarCAN and evac screen for BPS trip) - UpdateDisplay_ClearQueue(); // Clear message queue to ensure no other commands overwrite the error screen + printf("%d\n\r", error_code); + UpdateDisplayClearQueue(); // Clear message queue to ensure no other + // commands overwrite the error screen } - - if (errorCallback != NULL) { - errorCallback(); // Run a handler for this error that was specified in another task file + if (error_callback != NULL) { + error_callback(); // Run a handler for this error that was specified in + // another task file } - - - if (nonrecoverable == OPT_NONRECOV) { // Enter an infinite while loop - while(1) { - - #if DEBUG == 1 - // Print the error that caused this fault - // printf("\n\rCurrent Error Code: 0x%04x\n\r", errorCode); - - // // Print the errors for each applications with error data - // printf("\n\rAll application errors:\n\r"); - // printf("Error_ReadCarCAN: 0x%04x\n\r", Error_ReadCarCAN); - // printf("Error_ReadTritium: 0x%04x\n\r", Error_ReadTritium); - // printf("Error_UpdateDisplay: 0x%04x\n\r", Error_UpdateDisplay); - - // // Delay so that we're not constantly printing - // for (int i = 0; i < 9999999; i++) { - // } - #endif - - } + + if (nonrecoverable == kOptNonrecov) { // Enter an infinite while loop +#ifndef MOCKING + while (1) {} +#endif } - if (lockSched == OPT_LOCK_SCHED) { // Only happens on recoverable errors - OSSchedUnlock(&err); - // Don't err out if scheduler is still locked because of a timer callback - if (err != OS_ERR_SCHED_LOCKED || OSSchedLockNestingCtr > 1) { // But we don't plan to lock more than one level deep - assertOSError(err); + if (lock_sched == kOptLockSched) { // Only happens on recoverable errors + OSSchedUnlock(&err); + // Don't err out if scheduler is still locked because of a timer + // callback + if (err != OS_ERR_SCHED_LOCKED || + OSSchedLockNestingCtr > + 1) { // But we don't plan to lock more than one level deep + ASSERT_OS_ERROR(err); } - } } /** - * @brief For use in error handling: opens array and motor precharge bypass contactor - * and turns on additional brakelight to signal that a critical error happened. -*/ + * @brief For use in error handling: opens array and motor precharge bypass + * contactor and turns on additional brakelight to signal that a critical error + * happened. + */ void EmergencyContactorOpen() { // Array motor kill - BSP_GPIO_Write_Pin(CONTACTORS_PORT, MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN, OFF); - BSP_GPIO_Write_Pin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, OFF); + BspGpioWritePin(CONTACTORS_PORT, MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN, + OFF); + BspGpioWritePin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, OFF); // Turn additional brakelight on to indicate critical error - BSP_GPIO_Write_Pin(PININFO_LUT[BRAKELIGHT].port, PININFO_LUT[BRAKELIGHT].pinMask, true); + BspGpioWritePin(kPininfoLut[kBrakeLight].port, + kPininfoLut[kBrakeLight].pin_mask, true); } /** * @brief Hook that's called every context switch - * - * This function will append the task being switched out to the task trace if and only if: + * + * This function will append the task being switched out to the task trace if + * and only if: * 1. It's not a task created automatically by the RTOS - * 2. It's not the previously recorded task (a long running task interrupted by the - * tick task will only show up once) - * This function will overwrite tasks that have been in the trace for a while, keeping only - * the 8 most recent tasks + * 2. It's not the previously recorded task (a long running task + * interrupted by the tick task will only show up once) This function will + * overwrite tasks that have been in the trace for a while, keeping only the 8 + * most recent tasks */ -void App_OS_TaskSwHook(void) { +void AppOsTaskSwHook(void) { OS_TCB *cur = OSTCBCurPtr; - uint32_t idx = PrevTasks.index; - if (cur == &OSTickTaskTCB) return; // Ignore the tick task - if (cur == &OSIdleTaskTCB) return; // Ignore the idle task - if (cur == &OSTmrTaskTCB ) return; // Ignore the timer task - if (cur == &OSStatTaskTCB) return; // Ignore the stat task - if (cur == PrevTasks.tasks[idx]) return; // Don't record the same task again - if (++idx == TASK_TRACE_LENGTH) idx = 0; - PrevTasks.tasks[idx] = cur; - PrevTasks.index = idx; + uint32_t idx = prev_tasks.index; + if (cur == &OSTickTaskTCB) { + return; // Ignore the tick task + } + if (cur == &OSIdleTaskTCB) { + return; // Ignore the idle task + } + if (cur == &OSTmrTaskTCB) { + return; // Ignore the timer task + } + if (cur == &OSStatTaskTCB) { + return; // Ignore the stat task + } + if (cur == prev_tasks.tasks[idx]) { + return; // Don't record the same task again + } + if (++idx == TASK_TRACE_LENGTH) { + idx = 0; + } + prev_tasks.tasks[idx] = cur; + prev_tasks.index = idx; } -void TaskSwHook_Init(void) { - PrevTasks.index = TASK_TRACE_LENGTH - 1; // List starts out empty - OS_AppTaskSwHookPtr = App_OS_TaskSwHook; +void TaskSwHookInit(void) { + prev_tasks.index = TASK_TRACE_LENGTH - 1; // List starts out empty + OS_AppTaskSwHookPtr = AppOsTaskSwHook; } diff --git a/Apps/Src/UpdateDisplay.c b/Apps/Src/UpdateDisplay.c index 7da45f42b..c1b37a75e 100644 --- a/Apps/Src/UpdateDisplay.c +++ b/Apps/Src/UpdateDisplay.c @@ -2,92 +2,94 @@ * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file UpdateDisplay.c * @brief Function implementations for the display application. - * + * * This contains functions relevant to modifying states of specific - * components on our HMI design. The HMI has the ability to indicate + * components on our HMI design. The HMI has the ability to indicate * relevant information about system status to the driver. - * + * */ #include "UpdateDisplay.h" -#include "Minions.h" + #include +#include "Contactors.h" +#include "Display.h" +#include "Minions.h" +#include "Tasks.h" +#include "common.h" +#include "os.h" + +#define NUM_COMP_STRINGS 15 + /** * Creates queue for display commands. */ #define DISP_Q_SIZE 10 -#define FIFO_TYPE DisplayCmd_t +#define FIFO_TYPE DisplayCmd #define FIFO_SIZE DISP_Q_SIZE -#define FIFO_NAME disp_fifo +#define FIFO_NAME DispFifo #include "fifo.h" // For fault handling -#define RESTART_THRESHOLD 3 // number of times to reset before displaying the fault screen - -disp_fifo_t msg_queue; +#define RESTART_THRESHOLD \ + 3 // number of times to reset before displaying the fault screen -static OS_SEM DisplayQ_Sem4; // counting semaphore for queue message availability -static OS_MUTEX DisplayQ_Mutex; // mutex to ensure thread safety when writing/reading to queue +DispFifo msg_queue; +static OS_SEM + display_q_sem4; // counting semaphore for queue message availability +static OS_MUTEX display_q_mutex; // mutex to ensure thread safety when + // writing/reading to queue /** * Function prototypes -*/ + */ // check for and assert errors in UpdateDisplay -static void assertUpdateDisplayError(UpdateDisplayError_t err); - +static void assertUpdateDisplayError(UpdateDisplayError err); /** * Enum and corresponding array for easy component selection. */ -typedef enum{ - // Boolean components - ARRAY=0, - MOTOR, - // Non-boolean components - VELOCITY, - ACCEL_METER, - SOC, - SUPP_BATT, - CRUISE_ST, - REGEN_ST, - GEAR, - // Fault code components - OS_CODE, - FAULT_CODE -} Component_t; - -const char* compStrings[15]= { - // Boolean components - "arr", - "mot", - // Non-boolean components - "vel", - "accel", - "soc", - "supp", - "cruiseSt", - "rbsSt", - "gear", - // Fault code components - "oserr", - "faulterr" -}; - -UpdateDisplayError_t UpdateDisplay_Init(){ - OS_ERR err; - disp_fifo_renew(&msg_queue); - OSMutexCreate(&DisplayQ_Mutex, "Display mutex", &err); - assertOSError(err); - OSSemCreate(&DisplayQ_Sem4, "Display sem4", 0, &err); - assertOSError(err); - - UpdateDisplayError_t ret = UpdateDisplay_SetPage(INFO); - OSTimeDlyHMSM(0, 0, 0, 300, OS_OPT_TIME_HMSM_STRICT, &err); // Wait >215ms so errors will show on the display - assertOSError(err); - return ret; +typedef enum { + // Boolean components + kArray = 0, + kMotor, + // Non-boolean components + kVelocity, + kAccelMeter, + kSoc, + kSuppBatt, + kCruiseSt, + kRegenSt, + kGear, + // Fault code components + kOsCode, + kFaultCode +} Component; + +const char* comp_strings[NUM_COMP_STRINGS] = { + // Boolean components + "arr", "mot", + // Non-boolean components + "vel", "accel", "soc", "supp", "cruiseSt", "rbsSt", "gear", + // Fault code components + "oserr", "faulterr"}; + +UpdateDisplayError UpdateDisplayInit() { + OS_ERR err = 0; + DispFifoRenew(&msg_queue); + OSMutexCreate(&display_q_mutex, "Display mutex", &err); + ASSERT_OS_ERROR(err); + OSSemCreate(&display_q_sem4, "Display sem4", 0, &err); + ASSERT_OS_ERROR(err); + + UpdateDisplayError ret = UpdateDisplaySetPage(kInfo); + OSTimeDlyHMSM(0, 0, 0, 300, OS_OPT_TIME_HMSM_STRICT, // NOLINT + &err); // Wait >215ms so errors will show on the display + ASSERT_OS_ERROR(err); + return ret; } /** @@ -95,84 +97,80 @@ UpdateDisplayError_t UpdateDisplay_Init(){ * it to the display driver. Pends on semaphore and mutex to ensure that: * 1) queue has messages to send (signaled by semaphore) * 2) queue is not currently being written to by a separate thread (mutex) - * @returns UpdateDisplayError_t + * @returns UpdateDisplayError */ -static UpdateDisplayError_t UpdateDisplay_PopNext(){ - DisplayCmd_t cmd; - - OS_ERR err; - CPU_TS ticks; - - OSSemPend(&DisplayQ_Sem4, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); - assertOSError(err); - - OSMutexPend(&DisplayQ_Mutex, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); - assertOSError(err); - - bool result = disp_fifo_get(&msg_queue, &cmd); - OSMutexPost(&DisplayQ_Mutex, OS_OPT_POST_ALL, &err); - assertOSError(err); - - if(!result){ - assertUpdateDisplayError(UPDATEDISPLAY_ERR_FIFO_POP); - return UPDATEDISPLAY_ERR_FIFO_POP; - } - - // Assert a display driver error code if the send fails, else assert that there's no error - assertUpdateDisplayError(Display_Send(cmd) ? UPDATEDISPLAY_ERR_DRIVER : UPDATEDISPLAY_ERR_NONE); - return UPDATEDISPLAY_ERR_NONE; +static UpdateDisplayError updateDisplayPopNext() { + DisplayCmd cmd; + + OS_ERR err = 0; + CPU_TS ticks = 0; + + OSSemPend(&display_q_sem4, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); + ASSERT_OS_ERROR(err); + + OSMutexPend(&display_q_mutex, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); + ASSERT_OS_ERROR(err); + + bool result = DispFifoGet(&msg_queue, &cmd); + OSMutexPost(&display_q_mutex, OS_OPT_POST_ALL, &err); + ASSERT_OS_ERROR(err); + + if (!result) { + assertUpdateDisplayError(kUpdateDisplayErrFifoPop); + return kUpdateDisplayErrFifoPop; + } + + // Assert a display driver error code if the send fails, else assert that + // there's no error + assertUpdateDisplayError(DisplaySend(cmd) ? kUpdateDisplayErrDriver + : kUpdateDisplayErrNone); + return kUpdateDisplayErrNone; } /** * @brief Puts a new display message in the queue. Pends on mutex to ensure - * threadsafe memory access and signals semaphore upon successful fifo_put. - * @returns UpdateDisplayError_t + * threadsafe memory access and signals semaphore upon successful fifoPut. + * @returns UpdateDisplayError */ -static UpdateDisplayError_t UpdateDisplay_PutNext(DisplayCmd_t cmd){ - CPU_TS ticks; - OS_ERR err; - - OSMutexPend(&DisplayQ_Mutex, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); - assertOSError(err); - - bool success = disp_fifo_put(&msg_queue, cmd); - - OSMutexPost(&DisplayQ_Mutex, OS_OPT_POST_ALL, &err); - assertOSError(err); - - if(success){ - OSSemPost(&DisplayQ_Sem4, OS_OPT_POST_ALL, &err); - assertOSError(err); - } - else{ - assertUpdateDisplayError(UPDATEDISPLAY_ERR_FIFO_PUT); - return UPDATEDISPLAY_ERR_FIFO_PUT; - } - - return UPDATEDISPLAY_ERR_NONE; +static UpdateDisplayError updateDisplayPutNext(DisplayCmd cmd) { + CPU_TS ticks = 0; + OS_ERR err = 0; + + OSMutexPend(&display_q_mutex, 0, OS_OPT_PEND_BLOCKING, &ticks, &err); + ASSERT_OS_ERROR(err); + + bool success = DispFifoPut(&msg_queue, cmd); + + OSMutexPost(&display_q_mutex, OS_OPT_POST_ALL, &err); + ASSERT_OS_ERROR(err); + + if (success) { + OSSemPost(&display_q_sem4, OS_OPT_POST_ALL, &err); + ASSERT_OS_ERROR(err); + } else { + assertUpdateDisplayError(kUpdateDisplayErrFifoPut); + return kUpdateDisplayErrNone; + } + + return kUpdateDisplayErrNone; } /** * @brief Several elements on the display do not update their * state until a touch/click event is triggered. This includes the * blinkers, gear selector, cruise control and regen braking indicator. - * @returns UpdateDisplayError_t + * @returns UpdateDisplayError */ -static UpdateDisplayError_t UpdateDisplay_Refresh(){ - DisplayCmd_t refreshCmd = { - .compOrCmd = "click", - .attr = NULL, - .op = NULL, - .numArgs = 2, - .argTypes = {INT_ARG,INT_ARG}, - { - {.num=0}, - {.num=1} - } - }; - - UpdateDisplayError_t ret = UpdateDisplay_PutNext(refreshCmd); - return ret; +static UpdateDisplayError updateDisplayRefresh() { + DisplayCmd refresh_cmd = {.comp_or_cmd = "click", + .attr = NULL, + .op = NULL, + .num_args = 2, + .arg_types = {kIntArg, kIntArg}, + {{.num = 0}, {.num = 1}}}; + + UpdateDisplayError ret = updateDisplayPutNext(refresh_cmd); + return ret; } /** @@ -180,186 +178,191 @@ static UpdateDisplayError_t UpdateDisplay_Refresh(){ * Differentiates between timers, variables, and components to assign values. * @param comp component to set value of * @param val value - * @return UpdateDisplayError_t + * @return UpdateDisplayError */ -static UpdateDisplayError_t UpdateDisplay_SetComponent(Component_t comp, uint32_t val){ - UpdateDisplayError_t ret = UPDATEDISPLAY_ERR_NONE; - - // For components that are on/off - if(comp <= MOTOR && val <= 1){ - DisplayCmd_t visCmd = { - .compOrCmd = "vis", - .attr = NULL, - .op = NULL, - .numArgs = 2, - .argTypes = {STR_ARG,INT_ARG}, - { - {.str=(char*)compStrings[comp]}, - {.num=val} - } - }; - - ret = UpdateDisplay_PutNext(visCmd); - return ret; - } - // For components that have a non-boolean value - else if(comp > MOTOR){ - DisplayCmd_t setCmd = { - .compOrCmd = (char*)compStrings[comp], - .attr = "val", - .op = "=", - .numArgs = 1, - .argTypes = {INT_ARG}, - { - {.num=val} - } - }; - - ret = UpdateDisplay_PutNext(setCmd); - return ret; - } - else{ - assertUpdateDisplayError(UPDATEDISPLAY_ERR_PARSE_COMP); - return UPDATEDISPLAY_ERR_PARSE_COMP; - } - return UPDATEDISPLAY_ERR_NONE; +static UpdateDisplayError updateDisplaySetComponent(Component comp, + uint32_t val) { + UpdateDisplayError ret = kUpdateDisplayErrNone; + + // For components that are on/off + if (comp <= kMotor && val <= 1) { + DisplayCmd vis_cmd = { + .comp_or_cmd = "vis", + .attr = NULL, + .op = NULL, + .num_args = 2, + .arg_types = {kStrArg, kIntArg}, + {{.str = (char*)comp_strings[comp]}, {.num = val}}}; + + ret = updateDisplayPutNext(vis_cmd); + return ret; + } + // For components that have a non-boolean value + if (comp > kMotor) { + DisplayCmd set_cmd = {.comp_or_cmd = (char*)comp_strings[comp], + .attr = "val", + .op = "=", + .num_args = 1, + .arg_types = {kIntArg}, + {{.num = val}}}; + + ret = updateDisplayPutNext(set_cmd); + return ret; + } + assertUpdateDisplayError(kUpdateDisplayErrParseComp); + return kUpdateDisplayErrParseComp; + + return kUpdateDisplayErrNone; } -UpdateDisplayError_t UpdateDisplay_SetPage(Page_t page){ - DisplayCmd_t pgCmd = { - .compOrCmd = "page", - .attr = NULL, - .op = NULL, - .numArgs = 1, - .argTypes = {INT_ARG}, - { - {.num=page} - } - }; - - UpdateDisplayError_t ret = UpdateDisplay_PutNext(pgCmd); - return ret; +UpdateDisplayError UpdateDisplaySetPage(Page page) { + DisplayCmd pg_cmd = {.comp_or_cmd = "page", + .attr = NULL, + .op = NULL, + .num_args = 1, + .arg_types = {kIntArg}, + {{.num = page}}}; + + UpdateDisplayError ret = updateDisplayPutNext(pg_cmd); + return ret; } /* WRAPPERS */ -UpdateDisplayError_t UpdateDisplay_SetSOC(uint8_t percent){ // Integer percentage from 0-100 +UpdateDisplayError UpdateDisplaySetSoc( + uint8_t percent) { // Integer percentage from 0-100 - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(SOC, percent); - if(ret != UPDATEDISPLAY_ERR_NONE) return ret; + UpdateDisplayError ret = updateDisplaySetComponent(kSoc, percent); + if (ret != kUpdateDisplayErrNone) { + return ret; + } - ret = UpdateDisplay_Refresh(); - return ret; + ret = updateDisplayRefresh(); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetSBPV(uint32_t mv){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(SUPP_BATT, mv/100); - if(ret != UPDATEDISPLAY_ERR_NONE) return ret; +UpdateDisplayError UpdateDisplaySetSbpv(uint32_t mv) { + UpdateDisplayError ret = updateDisplaySetComponent(kSuppBatt, mv / 100); + if (ret != kUpdateDisplayErrNone) { + return ret; + } - ret = UpdateDisplay_Refresh(); - return ret; + ret = updateDisplayRefresh(); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetVelocity(uint32_t mphTenths){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(VELOCITY, mphTenths); - return ret; +UpdateDisplayError UpdateDisplaySetVelocity(uint32_t mph_tenths) { + UpdateDisplayError ret = updateDisplaySetComponent(kVelocity, mph_tenths); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetAccel(uint8_t percent){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(ACCEL_METER, percent); - return ret; +UpdateDisplayError UpdateDisplaySetAccel(uint8_t percent) { + UpdateDisplayError ret = updateDisplaySetComponent(kAccelMeter, percent); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetArray(bool state){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(ARRAY, (state)?1:0); - return ret; +UpdateDisplayError UpdateDisplaySetArray(bool state) { + UpdateDisplayError ret = updateDisplaySetComponent(kArray, (state) ? 1 : 0); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetMotor(bool state){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(MOTOR, (state)?1:0); - return ret; +UpdateDisplayError UpdateDisplaySetMotor(bool state) { + UpdateDisplayError ret = updateDisplaySetComponent(kMotor, (state) ? 1 : 0); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetGear(TriState_t gear){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(GEAR, (uint32_t)gear); - if(ret != UPDATEDISPLAY_ERR_NONE) return ret; +UpdateDisplayError UpdateDisplaySetGear(TriState gear) { + UpdateDisplayError ret = updateDisplaySetComponent(kGear, (uint32_t)gear); + if (ret != kUpdateDisplayErrNone) { + return ret; + } - ret = UpdateDisplay_Refresh(); - return ret; + ret = updateDisplayRefresh(); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetRegenState(TriState_t state){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(REGEN_ST, (uint32_t)state); - if(ret != UPDATEDISPLAY_ERR_NONE) return ret; - - ret = UpdateDisplay_Refresh(); - return ret; +UpdateDisplayError UpdateDisplaySetRegenState(TriState state) { + UpdateDisplayError ret = + updateDisplaySetComponent(kRegenSt, (uint32_t)state); + if (ret != kUpdateDisplayErrNone) { + return ret; + } + + ret = updateDisplayRefresh(); + return ret; } -UpdateDisplayError_t UpdateDisplay_SetCruiseState(TriState_t state){ - - UpdateDisplayError_t ret = UpdateDisplay_SetComponent(CRUISE_ST, (uint32_t)state); - if(ret != UPDATEDISPLAY_ERR_NONE) return ret; - - ret = UpdateDisplay_Refresh(); +UpdateDisplayError UpdateDisplaySetCruiseState(TriState state) { + UpdateDisplayError ret = + updateDisplaySetComponent(kCruiseSt, (uint32_t)state); + if (ret != kUpdateDisplayErrNone) { + return ret; + } + + ret = updateDisplayRefresh(); return ret; } /** - * @brief Clears the display message queue and sets the message counter semaphore value to 0 -*/ -void UpdateDisplay_ClearQueue(){ - OS_ERR err; - OSSemSet(&DisplayQ_Sem4, 0, &err); // Set the message queue semaphore value to 0 + * @brief Clears the display message queue and sets the message counter + * semaphore value to 0 + */ +void UpdateDisplayClearQueue() { + OS_ERR err = 0; + OSSemSet(&display_q_sem4, 0, + &err); // Set the message queue semaphore value to 0 if (err != OS_ERR_TASK_WAITING) { - assertOSError(err); // Don't fault if UpdateDisplay is waiting + ASSERT_OS_ERROR(err); // Don't fault if UpdateDisplay is waiting } - disp_fifo_renew(&msg_queue); // Clear the message queue - + DispFifoRenew(&msg_queue); // Clear the message queue } /** * @brief Loops through the display queue and sends all messages */ -void Task_UpdateDisplay(void *p_arg) { +void TaskUpdateDisplay(void* p_arg) { while (1) { - UpdateDisplay_PopNext(); + updateDisplayPopNext(); + +#ifdef MOCKING + break; +#endif } } /** * Error handler functions - * Passed as callback functions to the main throwTaskError function by assertUpdateDisplayError -*/ + * Passed as callback functions to the main ThrowTaskError function by + * assertUpdateDisplayError + */ /** - * @brief A handler callback function run by the main throwTaskError function + * @brief A handler callback function run by the main ThrowTaskError function * used if we haven't reached the restart limit and encounter an error - */ -static void handler_UpdateDisplay_Restart() { - UpdateDisplay_ClearQueue(); // Clear the message queue - Display_Reset(); // Try resetting to fix the display error + */ +static void handlerUpdateDisplayRestart() { + UpdateDisplayClearQueue(); // Clear the message queue + DisplayReset(); // Try resetting to fix the display error } /** * @brief Check for a display error and assert it if it exists. - * Stores the error code, calls the main assertion function - * and runs a callback function as a handler to restart the display and clear the queue. + * Stores the error code, calls the main assertion function + * and runs a callback function as a handler to restart the display and clear + * the queue. * @param err variable with display error codes */ - static void assertUpdateDisplayError(UpdateDisplayError_t err){ - Error_UpdateDisplay = (error_code_t)err; // Store the error code for inspection +static void assertUpdateDisplayError(UpdateDisplayError err) { + error_update_display = + (ErrorCode)err; // Store the error code for inspection - if (err == UPDATEDISPLAY_ERR_NONE) return; // No error, return + if (err == kUpdateDisplayErrNone) { + return; // No error, return + } // Otherwise try resetting the display using the restart callback - throwTaskError(Error_UpdateDisplay, handler_UpdateDisplay_Restart,OPT_NO_LOCK_SCHED, OPT_RECOV); + ThrowTaskError(error_update_display, handlerUpdateDisplayRestart, + kOptNoLockSched, kOptRecov); - Error_UpdateDisplay = UPDATEDISPLAY_ERR_NONE; // Clear the error after handling it + error_update_display = + kUpdateDisplayErrNone; // Clear the error after handling it } diff --git a/Apps/Src/common.c b/Apps/Src/common.c index 0ad5e1d01..f7d254a46 100644 --- a/Apps/Src/common.c +++ b/Apps/Src/common.c @@ -1,19 +1,25 @@ #include "common.h" -void print_float(char * str, float f) { - if(str) printf("%s", str); +#define MASK 0x80000000L - int32_t n = (int32_t)f; - f -= n; - f *= 100; - int32_t d = (f<0)?-f:f; - printf("%d.%02d\n\r", (int)n, (int)d); +void PrintFloat(char* str, float value) { + if (str) { + printf("%s", str); + } + + int32_t num = (int32_t)value; + value -= (float)num; + value *= 100; + int32_t dec = (int32_t)((value < 0) ? -value : value); + printf("%d.%02d\n\r", (int)num, (int)dec); } -void print_bin(char * str, uint32_t i){ - if(str) printf("%s", str); +void PrintBin(char* str, uint32_t value) { + if (str) { + printf("%s", str); + } - for(uint32_t mask=0x80000000L; mask > 0L; mask >>= 1){ - printf("%d\n\r",(mask & i)?1:0); + for (uint32_t mask = MASK; mask > 0L; mask >>= 1) { + printf("%d\n\r", (mask & value) ? 1 : 0); } } \ No newline at end of file diff --git a/Apps/Src/main.c b/Apps/Src/main.c index 62a8f33ba..b6ea9c342 100644 --- a/Apps/Src/main.c +++ b/Apps/Src/main.c @@ -1,169 +1,132 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file main.c - * @brief - * + * @brief + * */ -#include "common.h" -#include "config.h" -#include "Tasks.h" -#include "stm32f4xx.h" -#include "CANbus.h" -#include "CANConfig.h" +#include "BSP_UART.h" +#include "CanBus.h" +#include "CanConfig.h" #include "Contactors.h" #include "Display.h" #include "Minions.h" #include "Pedals.h" +#include "ReadCarCan.h" +#include "ReadTritium.h" +#include "SendCarCan.h" +#include "SendTritium.h" +#include "Tasks.h" #include "UpdateDisplay.h" -#include "SendCarCAN.h" +#include "common.h" +#include "config.h" +#include "stm32f4xx.h" int main(void) { // Disable interrupts __disable_irq(); - OS_ERR err; + OS_ERR err = 0; OSInit(&err); - TaskSwHook_Init(); + TaskSwHookInit(); - assertOSError(err); + ASSERT_OS_ERROR(err); // Initialize apps - OSTaskCreate( - (OS_TCB*)&Init_TCB, - (CPU_CHAR*)"Init", - (OS_TASK_PTR)Task_Init, - (void*)NULL, - (OS_PRIO)TASK_INIT_PRIO, - (CPU_STK*)Init_Stk, - (CPU_STK_SIZE)WATERMARK_STACK_LIMIT/10, - (CPU_STK_SIZE)TASK_INIT_STACK_SIZE, - (OS_MSG_QTY)0, - (OS_TICK)0, - (void*)NULL, - (OS_OPT)(OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP), - (OS_ERR*)&err - ); - assertOSError(err); + OSTaskCreate((OS_TCB *)&init_tcb, (CPU_CHAR *)"Init", (OS_TASK_PTR)TaskInit, + (void *)NULL, (OS_PRIO)TASK_INIT_PRIO, (CPU_STK *)init_stk, + (CPU_STK_SIZE)WATERMARK_STACK_LIMIT / 10, // NOLINT + (CPU_STK_SIZE)TASK_INIT_STACK_SIZE, (OS_MSG_QTY)0, (OS_TICK)0, + (void *)NULL, + (OS_OPT)(OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP), + (OS_ERR *)&err); + ASSERT_OS_ERROR(err); // Enable interrupts __enable_irq(); // Start OS OSStart(&err); - assertOSError(err); + ASSERT_OS_ERROR(err); - while(1); +#ifndef MOCKING + while (1) {} +#endif } -void Task_Init(void *p_arg){ - OS_ERR err; +void TaskInit(void *p_arg) { + OS_ERR err = 0; + + // Start systick + OS_CPU_SysTickInit(SystemCoreClock / (CPU_INT32U)OSCfg_TickRate_Hz); - // Start systick - OS_CPU_SysTickInit(SystemCoreClock / (CPU_INT32U) OSCfg_TickRate_Hz); - // Initialize drivers - Pedals_Init(); - BSP_UART_Init(UART_2); - CANbus_Init(CARCAN, carCANFilterList, NUM_CARCAN_FILTERS); - CANbus_Init(MOTORCAN, NULL, NUM_MOTORCAN_FILTERS); - Contactors_Init(); - Display_Init(); - Minions_Init(); + PedalsInit(); + BspUartInit(kUart2); + CanBusInit(CARCAN, car_can_filter_list, NUM_CARCAN_FILTERS); + CanBusInit(MOTORCAN, NULL, NUM_MOTORCAN_FILTERS); + ContactorsInit(); + DisplayInit(); + MinionsInit(); // Initialize applications - UpdateDisplay_Init(); - SendCarCAN_Init(); + UpdateDisplayInit(); + SendCarCanInit(); // Initialize ReadTritium - OSTaskCreate( - (OS_TCB*)&ReadTritium_TCB, - (CPU_CHAR*)"ReadTritium", - (OS_TASK_PTR)Task_ReadTritium, - (void*)NULL, - (OS_PRIO)TASK_READ_TRITIUM_PRIO, - (CPU_STK*)ReadTritium_Stk, - (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, - (CPU_STK_SIZE)TASK_READ_TRITIUM_STACK_SIZE, - (OS_MSG_QTY)0, - (OS_TICK)0, - (void*)NULL, - (OS_OPT)(OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP), - (OS_ERR*)&err - ); - assertOSError(err); + OSTaskCreate((OS_TCB *)&read_tritium_tcb, (CPU_CHAR *)"ReadTritium", + (OS_TASK_PTR)TaskReadTritium, (void *)NULL, + (OS_PRIO)TASK_READ_TRITIUM_PRIO, (CPU_STK *)read_tritium_stk, + (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, + (CPU_STK_SIZE)TASK_READ_TRITIUM_STACK_SIZE, (OS_MSG_QTY)0, + (OS_TICK)0, (void *)NULL, + (OS_OPT)(OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP), + (OS_ERR *)&err); + ASSERT_OS_ERROR(err); // Initialize SendTritium - OSTaskCreate( - (OS_TCB*)&SendTritium_TCB, - (CPU_CHAR*)"SendTritium", - (OS_TASK_PTR)Task_SendTritium, - (void*)NULL, - (OS_PRIO)TASK_SEND_TRITIUM_PRIO, - (CPU_STK*)SendTritium_Stk, - (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, - (CPU_STK_SIZE)TASK_SEND_TRITIUM_STACK_SIZE, - (OS_MSG_QTY)0, - (OS_TICK)0, - (void*)NULL, - (OS_OPT)(OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP), - (OS_ERR*)&err - ); - assertOSError(err); + OSTaskCreate((OS_TCB *)&send_tritium_tcb, (CPU_CHAR *)"SendTritium", + (OS_TASK_PTR)TaskSendTritium, (void *)NULL, + (OS_PRIO)TASK_SEND_TRITIUM_PRIO, (CPU_STK *)send_tritium_stk, + (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, + (CPU_STK_SIZE)TASK_SEND_TRITIUM_STACK_SIZE, (OS_MSG_QTY)0, + (OS_TICK)0, (void *)NULL, + (OS_OPT)(OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP), + (OS_ERR *)&err); + ASSERT_OS_ERROR(err); // Initialize ReadCarCAN - OSTaskCreate( - (OS_TCB*)&ReadCarCAN_TCB, - (CPU_CHAR*)"ReadCarCAN", - (OS_TASK_PTR)Task_ReadCarCAN, - (void*)NULL, - (OS_PRIO)TASK_READ_CAR_CAN_PRIO, - (CPU_STK*)ReadCarCAN_Stk, - (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, - (CPU_STK_SIZE)TASK_READ_CAR_CAN_STACK_SIZE, - (OS_MSG_QTY)0, - (OS_TICK)0, - (void*)NULL, - (OS_OPT)(OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP), - (OS_ERR*)&err - ); - assertOSError(err); + OSTaskCreate((OS_TCB *)&read_car_can_tcb, (CPU_CHAR *)"ReadCarCAN", + (OS_TASK_PTR)TaskReadCarCan, (void *)NULL, + (OS_PRIO)TASK_READ_CAR_CAN_PRIO, (CPU_STK *)read_car_can_stk, + (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, + (CPU_STK_SIZE)TASK_READ_CAR_CAN_STACK_SIZE, (OS_MSG_QTY)0, + (OS_TICK)0, (void *)NULL, + (OS_OPT)(OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP), + (OS_ERR *)&err); + ASSERT_OS_ERROR(err); // Initialize UpdateDisplay OSTaskCreate( - (OS_TCB*)&UpdateDisplay_TCB, - (CPU_CHAR*)"UpdateDisplay", - (OS_TASK_PTR)Task_UpdateDisplay, - (void*)NULL, - (OS_PRIO)TASK_UPDATE_DISPLAY_PRIO, - (CPU_STK*)UpdateDisplay_Stk, + (OS_TCB *)&update_display_tcb, (CPU_CHAR *)"UpdateDisplay", + (OS_TASK_PTR)TaskUpdateDisplay, (void *)NULL, + (OS_PRIO)TASK_UPDATE_DISPLAY_PRIO, (CPU_STK *)update_display_stk, (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, - (CPU_STK_SIZE)TASK_UPDATE_DISPLAY_STACK_SIZE, - (OS_MSG_QTY)0, - (OS_TICK)0, - (void*)NULL, - (OS_OPT)(OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP), - (OS_ERR*)&err - ); - assertOSError(err); - + (CPU_STK_SIZE)TASK_UPDATE_DISPLAY_STACK_SIZE, (OS_MSG_QTY)0, (OS_TICK)0, + (void *)NULL, (OS_OPT)(OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP), + (OS_ERR *)&err); + ASSERT_OS_ERROR(err); + // Initialize SendCarCAN - OSTaskCreate( - (OS_TCB*)&SendCarCAN_TCB, - (CPU_CHAR*)"SendCarCAN", - (OS_TASK_PTR)Task_SendCarCAN, - (void*)NULL, - (OS_PRIO)TASK_SEND_CAR_CAN_PRIO, - (CPU_STK*)SendCarCAN_Stk, - (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, - (CPU_STK_SIZE)TASK_SEND_CAR_CAN_STACK_SIZE, - (OS_MSG_QTY)0, - (OS_TICK)0, - (void*)NULL, - (OS_OPT)(OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP), - (OS_ERR*)&err - ); - assertOSError(err); + OSTaskCreate((OS_TCB *)&send_car_can_tcb, (CPU_CHAR *)"SendCarCAN", + (OS_TASK_PTR)TaskSendCarCan, (void *)NULL, + (OS_PRIO)TASK_SEND_CAR_CAN_PRIO, (CPU_STK *)send_car_can_stk, + (CPU_STK_SIZE)WATERMARK_STACK_LIMIT, + (CPU_STK_SIZE)TASK_SEND_CAR_CAN_STACK_SIZE, (OS_MSG_QTY)0, + (OS_TICK)0, (void *)NULL, + (OS_OPT)(OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP), + (OS_ERR *)&err); + ASSERT_OS_ERROR(err); OSTaskDel(NULL, &err); } diff --git a/BSP/Inc/BSP_ADC.h b/BSP/Inc/BSP_ADC.h index 33ccd47b4..ccedb41a5 100644 --- a/BSP/Inc/BSP_ADC.h +++ b/BSP/Inc/BSP_ADC.h @@ -3,51 +3,42 @@ * @file BSP_ADC.h * @brief Header file for the library to interact * with the Analog to Digital Converter (ADC) - * + * * @defgroup BSP_ADC * @addtogroup BSP_ADC * @{ */ -#ifndef __BSP_ADC_H -#define __BSP_ADC_H +#ifndef BSP_ADC_H +#define BSP_ADC_H -#include "bsp.h" #include "common.h" -#include "config.h" -#define MAX_CHANNELS 10 -#define ADC_PRECISION_BITS 12 -#define ADC_RANGE_MILLIVOLTS 3300 +#define BSP_ADC_PRECISION_BITS 12 -typedef enum -{ - Accelerator_ADC, - Brake_ADC, - NUMBER_OF_CHANNELS -} ADC_t; +typedef enum { kCh10, kCh11, kNumCh } Adc; /** * @brief Initialize the ADC module * @return None - */ -void BSP_ADC_Init(void); + */ +void BspAdcInit(void); /** * @brief Provides the ADC value of the channel at the specified index * @param hardwareDevice pedal enum that represents the specific device * @return Raw ADC value without conversion - */ -int16_t BSP_ADC_Get_Value(ADC_t hardwareDevice); + */ +int16_t BspAdcGetValue(Adc hardware_device); /** - * @brief Provides the ADC value in millivolts of the channel at the specified index + * @brief Provides the ADC value in millivolts of the channel at the specified + * index * @param hardwareDevice pedal enum that represents the specific device * @return ADC value in millivolts - */ -int16_t BSP_ADC_Get_Millivoltage(ADC_t hardwareDevice); + */ +int16_t BspAdcGetMillivoltage(Adc hardware_device); #endif - /* @} */ diff --git a/BSP/Inc/BSP_CAN.h b/BSP/Inc/BSP_CAN.h index 4163e0c2a..c9229e901 100644 --- a/BSP/Inc/BSP_CAN.h +++ b/BSP/Inc/BSP_CAN.h @@ -3,31 +3,37 @@ * @file BSP_CAN.h * @brief Header file for the library to interact * with both CAN lines in the car - * + * * @defgroup BSP_CAN * @addtogroup BSP_CAN * @{ */ -#ifndef __BSP_CAN_H -#define __BSP_CAN_H +#ifndef BSP_CAN_H +#define BSP_CAN_H #include "common.h" -#include "config.h" -#include -typedef enum {CAN_1=0, CAN_3, NUM_CAN} CAN_t; +#define BSP_CAN_DATA_LENGTH 8 +#define BSP_CAN_NUM_MAILBOX 3 + +typedef enum { kCan1 = 0, kCan3, kNumCan } Can; /** - * @brief Initializes the CAN module that communicates with the rest of the electrical system. + * @brief Initializes the CAN module that communicates with the rest of the + * electrical system. * @param bus : The bus to initialize. Should only be either CAN_1 or CAN_3. - * @param rxEvent : the function to execute when recieving a message. NULL for no action. - * @param txEnd : the function to execute after transmitting a message. NULL for no action. - * @param idWhitelist : the idWhitelist to use for message filtering. NULL for no filtering. + * @param rxEvent : the function to execute when recieving a message. NULL for + * no action. + * @param txEnd : the function to execute after transmitting a message. NULL + * for no action. + * @param idWhitelist : the idWhitelist to use for message filtering. NULL for + * no filtering. * @param idWhitelistSize : the size of the idWhitelist, if it is not NULL. * @return None */ -void BSP_CAN_Init(CAN_t bus, callback_t rxEvent, callback_t txEnd, uint16_t* idWhitelist, uint8_t idWhitelistSize); +void BspCanInit(Can bus, Callback rx_event, Callback tx_end, + uint16_t* id_whitelist, uint8_t id_whitelist_size); /** * @brief Writes a message to the specified CAN line @@ -38,19 +44,20 @@ void BSP_CAN_Init(CAN_t bus, callback_t rxEvent, callback_t txEnd, uint16_t* idW * @param len length of the message in bytes * @return number of bytes transmitted (0 if unsuccessful) */ -ErrorStatus BSP_CAN_Write(CAN_t bus, uint32_t id, uint8_t data[8], uint8_t len); + +ErrorStatus BspCanWrite(Can bus, uint32_t id, + const uint8_t data[BSP_CAN_DATA_LENGTH], uint8_t len); /** * @brief Reads the message on the specified CAN line - * @param id pointer to integer to store the + * @param id pointer to integer to store the * message ID that was read * @param data pointer to integer array to store * the message in bytes * @return number of bytes read (0 if unsuccessful) */ -ErrorStatus BSP_CAN_Read(CAN_t bus, uint32_t* id, uint8_t* data); +ErrorStatus BspCanRead(Can bus, uint32_t* id, uint8_t* data); #endif - /* @} */ diff --git a/BSP/Inc/BSP_GPIO.h b/BSP/Inc/BSP_GPIO.h index 66db068c4..c0be15384 100644 --- a/BSP/Inc/BSP_GPIO.h +++ b/BSP/Inc/BSP_GPIO.h @@ -3,55 +3,52 @@ * @file BSP_GPIO.h * @brief Header file for the library to interact * with the GPIO ports - * + * * @defgroup BSP_GPIO * @addtogroup BSP_GPIO * @{ */ -#ifndef __BSP_GPIO_H -#define __BSP_GPIO_H +#ifndef BSP_GPIO_H +#define BSP_GPIO_H #include "common.h" -#include "config.h" #include "stm32f4xx_gpio.h" -#include -#include -typedef enum {PORTA = 0, PORTB, PORTC, PORTD, NUM_PORTS} port_t; -typedef enum {INPUT = 0, OUTPUT} direction_t; +typedef enum { kPortA = 0, kPortB, kPortC, kPortD, kNumPorts } Port; +typedef enum { kInput = 0, kOutput } Direction; /** * @brief Initializes a GPIO port * @param port - port to initialize * @param mask - pins - * @param direction - input or output + * @param direction - input or output * @return None - */ -void BSP_GPIO_Init(port_t port, uint16_t mask, direction_t direction); + */ +void BspGpioInit(Port port, uint16_t mask, Direction direction); /** * @brief Reads value of the specified port * @param port to read * @return data of the port - */ -uint16_t BSP_GPIO_Read(port_t port); + */ +uint16_t BspGpioRead(Port port); /** - * @brief Writes data to a specified port + * @brief Writes data to a specified port * @param port port to write to - * @param data data to write + * @param data data to write * @return None - */ -void BSP_GPIO_Write(port_t port, uint16_t data); + */ +void BspGpioWrite(Port port, uint16_t data); /** * @brief Reads data from a specified pin (not applicalbe to output pins) * @param port The port to read from * @param pinmask Mask from stm header file that says which pin to read from * @return State of the pin - */ -uint8_t BSP_GPIO_Read_Pin(port_t port, uint16_t pinmask); + */ +uint8_t BspGpioReadPin(Port port, uint16_t pin_mask); /** * @brief Writes data to a specified pin @@ -59,18 +56,17 @@ uint8_t BSP_GPIO_Read_Pin(port_t port, uint16_t pinmask); * @param pinmask Mask from stm header file that says which pin to write too * @param state true=ON or false=OFF * @return None - */ -void BSP_GPIO_Write_Pin(port_t port, uint16_t pinmask, bool state); + */ +void BspGpioWritePin(Port port, uint16_t pin_mask, bool state); /** * @brief Returns state of output pin (not applicable to input pins) * @param port The port to get state from * @param pin The pin to get state from * @return 1 if pin is high, 0 if low - */ -uint8_t BSP_GPIO_Get_State(port_t port, uint16_t pin); + */ +uint8_t BspGpioGetState(Port port, uint16_t pin); #endif - /* @} */ diff --git a/BSP/Inc/BSP_OS.h b/BSP/Inc/BSP_OS.h deleted file mode 100644 index ab4bfcd87..000000000 --- a/BSP/Inc/BSP_OS.h +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file BSP_OS.h - * @brief - * - * @defgroup BSP_OS - * @addtogroup BSP_OS - * @{ - */ - -#ifndef BSP_OS_H -#define BSP_OS_H - -typedef struct { - callback_t pend; - callback_t post; -} bsp_os_t; - -#endif - - -/* @} */ diff --git a/BSP/Inc/BSP_SPI.h b/BSP/Inc/BSP_SPI.h deleted file mode 100644 index 27ad70d96..000000000 --- a/BSP/Inc/BSP_SPI.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file BSP_SPI.h - * @brief Header file for the library to interact - * over SPI with minion board(s) - * - * @defgroup BSP_SPI - * @addtogroup BSP_SPI - * @{ - */ - -#ifndef __BSP_SPI_H -#define __BSP_SPI_H - -#include "common.h" -#include "bsp.h" -#include "os.h" - - - -/** - * @brief Initializes the SPI communication - * to be used to communicate with - * minion board(s) - * @param None - * @return None - */ -void BSP_SPI_Init(void); - -/** - * @brief Transmits a message through SPI - * @param txBuf data to transmit - * @param txLen length of the data packet - * @return None - * Do not call from an ISR - */ -void BSP_SPI_Write(uint8_t* txBuf, uint8_t txLen); - -/** - * @brief Receives a message through SPI - * @param rxBuf buffer to store the received data - * @param rxLen length of the buffer - * @return None - * Do not call from an ISR - */ -void BSP_SPI_Read(uint8_t* rxBuf, uint8_t rxLen); - -#endif - - -/* @} */ diff --git a/BSP/Inc/BSP_UART.h b/BSP/Inc/BSP_UART.h index 15743921d..9cf74ef3b 100644 --- a/BSP/Inc/BSP_UART.h +++ b/BSP/Inc/BSP_UART.h @@ -1,48 +1,47 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file BSP_UART.h + * @file BSP_USART.h * @brief Header file for the library to interact - * with the UART line - * - * @defgroup BSP_UART - * @addtogroup BSP_UART + * with the USART line + * + * @defgroup BSP_USART + * @addtogroup BSP_USART * @{ */ -#ifndef __BSP_UART_H -#define __BSP_UART_H +#ifndef BSP_UART_H +#define BSP_UART_H #include "common.h" -#include -typedef enum {UART_2, UART_3, NUM_UART} UART_t; +typedef enum { kUart2, kUart3, kNumUart } Uart; + /** - * @brief Initializes the UART peripheral + * @brief Initializes the USART peripheral */ -void BSP_UART_Init(UART_t); +void BspUartInit(Uart); /** - * @brief Gets one line of ASCII text that was received - * from a specified UART device + * @brief Gets one line of ASCII text that was received + * from a specified USART device * @pre str should be at least 128bytes long. - * @param uart device selected + * @param usart device selected * @param str pointer to buffer string * @return number of bytes that was read */ -uint32_t BSP_UART_Read(UART_t uart, char *str); +uint32_t BspUartRead(Uart usart, char *str); /** - * @brief Transmits data to through a specific - * UART device (represented as a line of data + * @brief Transmits data to through a specific + * USART device (represented as a line of data * in csv file). - * @param uart device selected + * @param usart device selected * @param str pointer to buffer with data to send. * @param len size of buffer * @return number of bytes that were sent */ -uint32_t BSP_UART_Write(UART_t uart ,char *str, uint32_t len); +uint32_t BspUartWrite(Uart usart, char *str, uint32_t len); #endif - /* @} */ diff --git a/BSP/Inc/bsp.h b/BSP/Inc/bsp.h old mode 100755 new mode 100644 index f45456695..b93c54a67 --- a/BSP/Inc/bsp.h +++ b/BSP/Inc/bsp.h @@ -1,38 +1,22 @@ /** + * @file * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file bsp.h - * @brief - * + * @brief + * * @defgroup bsp * @addtogroup bsp * @{ */ -#ifndef __BSP_H -#define __BSP_H +#ifndef BSP_H +#define BSP_H + +#include #include "BSP_ADC.h" #include "BSP_CAN.h" -#include "BSP_UART.h" -#include "BSP_SPI.h" #include "BSP_GPIO.h" - -#include -#include - -#ifdef SIMULATOR -#define DATA_PATH(f) "BSP/Simulator/Hardware/Data/" f - -#define SWITCHES_CSV "Switches.csv" -#define CONTACTORS_CSV "Contactors.csv" -#define PEDALS_CSV "Pedals.csv" -#define UART_CSV "UART.csv" -#define CAN_CSV "CAN.csv" -#define SPI_CSV "SPI.csv" -#define LIGHTS_CSV "Lights.csv" -#define PRECHARGE_CSV "PreCharge.csv" -#define GPIO_CSV "GPIO.csv" -#endif +#include "BSP_UART.h" #endif diff --git a/BSP/STM32F413/Makefile b/BSP/STM32F413/Makefile index bfc0a49b9..df7764d07 100644 --- a/BSP/STM32F413/Makefile +++ b/BSP/STM32F413/Makefile @@ -113,23 +113,26 @@ C_INCLUDES = \ -I../../RTOS/uCOS-III-STM32F4/uC-LIB/ \ -I../../Tests/Inc/ \ -# compile gcc flags -ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections - -CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -Werror -fdata-sections -ffunction-sections - ifeq ($(DEBUG), 1) -CFLAGS += -g3 -gdwarf-2 -DDEBUG +C_DEFS += -g3 -gdwarf-2 -DDEBUG endif ifeq ($(MOTOR_LOOPBACK), 1) -CFLAGS += -DMOTOR_LOOPBACK +C_DEFS += -DMOTOR_LOOPBACK endif ifeq ($(CAR_LOOPBACK), 1) -CFLAGS += -DCAR_LOOPBACK +C_DEFS += -DCAR_LOOPBACK endif +FILETOTEST = $(shell echo '$(FILE)' | tr '[:lower:]' '[:upper:]') #Uses shell to make TEST file uppercase to define a macro +C_DEFS += -DDEBUG_$(FILETOTEST) #Defines a macro DEBUG_ + +# compile gcc flags +ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections + +CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -Werror -fdata-sections -ffunction-sections + # Generate dependency information CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" @@ -184,6 +187,42 @@ $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) $(BUILD_DIR): mkdir $@ +####################################### +# clang +####################################### +CLANGINPUTS = \ +$(wildcard ../../Apps/Inc/*) \ +$(wildcard ../../Apps/Src/*) \ +$(wildcard ../../Drivers/Inc/*) \ +$(wildcard ../../Drivers/Src/*) \ +$(wildcard ../../BSP/Inc/*) \ +$(wildcard ../../BSP/STM32F413/Src/BSP_*.c) \ +$(wildcard ../../BSP/STM32F413/Src/retarget.c) \ + +####################################### +# tidy +####################################### +TIDYFLAGS = --config-file=../../.clang-tidy +TIDYCFLAGS = $(C_DEFS) +TIDYCFLAGS += -m32 + +tidy: + clang-tidy-17 $(TIDYFLAGS) $(CLANGINPUTS) --fix -- $(C_INCLUDES) $(TIDYCFLAGS) + +tidy-check: + clang-tidy-17 $(TIDYFLAGS) $(CLANGINPUTS) --warnings-as-errors=* -- $(C_INCLUDES) $(TIDYCFLAGS) + +####################################### +# format +####################################### +FORMATFLAGS = --config-file=../../.clang-format + +format: + clang-format-17 -i $(CLANGINPUTS) + +format-check: + clang-format-17 -i --Werror --dry-run $(CLANGINPUTS) + ####################################### # clean up ####################################### diff --git a/BSP/STM32F413/Src/BSP_ADC.c b/BSP/STM32F413/Src/BSP_ADC.c index f49dac17b..2cc562700 100644 --- a/BSP/STM32F413/Src/BSP_ADC.c +++ b/BSP/STM32F413/Src/BSP_ADC.c @@ -1,90 +1,106 @@ /* Copyright (c) 2020 UT Longhorn Racing Solar */ #include "BSP_ADC.h" + #include "stm32f4xx.h" -static volatile uint16_t ADCresults[2]; - -static void ADC_InitDMA(void) { - // Start the clock for the DMA - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); - - // Create the DMA structure - DMA_InitTypeDef DMA_InitStruct; - - DMA_InitStruct.DMA_Channel = DMA_Channel_0; - DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR); - DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t) &ADCresults; - DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory; - DMA_InitStruct.DMA_BufferSize = 2; - DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; - DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; - DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; - DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; - DMA_InitStruct.DMA_Priority = DMA_Priority_High; - DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable; - DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; - DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single; - DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; - DMA_Init(DMA2_Stream0, &DMA_InitStruct); - - // Enable DMA2 stream 0 - DMA_Cmd(DMA2_Stream0, ENABLE); +#define NUM_ADC 2 +#define DMA_BUFFER_SIZE 2 +#define ADC10_RANK 1 +#define ADC11_RANK 2 + +#define ADC_RANGE_MILLIVOLTS 3300 + +static volatile uint16_t adc_results[NUM_ADC]; + +static void adcInitDma(void) { + // Start the clock for the DMA + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); + + // Create the DMA structure + DMA_InitTypeDef dma_init_struct; + + dma_init_struct.DMA_Channel = DMA_Channel_0; + dma_init_struct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; + dma_init_struct.DMA_Memory0BaseAddr = (uint32_t)&adc_results; + dma_init_struct.DMA_DIR = DMA_DIR_PeripheralToMemory; + dma_init_struct.DMA_BufferSize = DMA_BUFFER_SIZE; + dma_init_struct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + dma_init_struct.DMA_MemoryInc = DMA_MemoryInc_Enable; + dma_init_struct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; + dma_init_struct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; + dma_init_struct.DMA_Mode = DMA_Mode_Circular; + dma_init_struct.DMA_Priority = DMA_Priority_High; + dma_init_struct.DMA_FIFOMode = DMA_FIFOMode_Disable; + dma_init_struct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; + dma_init_struct.DMA_MemoryBurst = DMA_MemoryBurst_Single; + dma_init_struct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + DMA_Init(DMA2_Stream0, &dma_init_struct); + + // Enable DMA2 stream 0 + DMA_Cmd(DMA2_Stream0, ENABLE); } /** - * @brief Initializes the ADC module. This is to measure the hall effect sensors - * on the Current Monitor Board. + * @brief Initializes the ADC module. This is to measure the hall effect + * sensors on the Current Monitor Board. * @param None * @return None */ -void BSP_ADC_Init(void) { - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // Enable the ADC clock - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); // Enable the PC clock for port C - - ADC_InitDMA(); - - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; // Using pin PC0 and PC1 - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN; // Analog Input - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // High impedence - GPIO_Init(GPIOC,&GPIO_InitStruct); - - // ADC Common Init - ADC_CommonInitTypeDef ADC_CommonStruct; - ADC_CommonStruct.ADC_Mode = ADC_Mode_Independent; - ADC_CommonStruct.ADC_Prescaler = ADC_Prescaler_Div2; - ADC_CommonStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; - ADC_CommonStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; - ADC_CommonInit(&ADC_CommonStruct); - - // Set up to use DMA so that multiple channels can be used - ADC_InitTypeDef ADC_InitStruct; // Initialization structure - ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; // High resolution - ADC_InitStruct.ADC_ScanConvMode = ENABLE; // So we can go through all the channels - ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; // Cycle the channels - ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; - ADC_InitStruct.ADC_ExternalTrigConv = DISABLE; - ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; - ADC_InitStruct.ADC_NbrOfConversion = 2; // We have two channels that we need to read - - ADC_Init(ADC1, &ADC_InitStruct); - - // Configure the channels - // Apparently channel 2 has priority, or is at least read first. - // If you change the priorities, be prepared to have the order in the array change. - ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_480Cycles); // Accelerator - ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_480Cycles); // Brake - - ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); - - ADC_DMACmd(ADC1, ENABLE); - - // Enable ADC1 - ADC_Cmd(ADC1, ENABLE); - - ADC_SoftwareStartConv(ADC1); +void BspAdcInit(void) { + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, + ENABLE); // Enable the ADC clock + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, + ENABLE); // Enable the PC clock for port C + + adcInitDma(); + + GPIO_InitTypeDef gpio_init_struct; + gpio_init_struct.GPIO_Pin = + GPIO_Pin_0 | GPIO_Pin_1; // Using pin PC0 and PC1 + gpio_init_struct.GPIO_Mode = GPIO_Mode_AN; // Analog Input + gpio_init_struct.GPIO_PuPd = GPIO_PuPd_NOPULL; // High impedence + GPIO_Init(GPIOC, &gpio_init_struct); + + // ADC Common Init + ADC_CommonInitTypeDef adc_common_struct; + adc_common_struct.ADC_Mode = ADC_Mode_Independent; + adc_common_struct.ADC_Prescaler = ADC_Prescaler_Div2; + adc_common_struct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; + adc_common_struct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; + ADC_CommonInit(&adc_common_struct); + + // Set up to use DMA so that multiple channels can be used + ADC_InitTypeDef adc_init_struct; // Initialization structure + adc_init_struct.ADC_Resolution = ADC_Resolution_12b; // High resolution + adc_init_struct.ADC_ScanConvMode = + ENABLE; // So we can go through all the channels + adc_init_struct.ADC_ContinuousConvMode = ENABLE; // Cycle the channels + adc_init_struct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; + adc_init_struct.ADC_ExternalTrigConv = DISABLE; + adc_init_struct.ADC_DataAlign = ADC_DataAlign_Right; + adc_init_struct.ADC_NbrOfConversion = + NUM_ADC; // We have two channels that we need to read + + ADC_Init(ADC1, &adc_init_struct); + + // Configure the channels + // Apparently channel 2 has priority, or is at least read first. + // If you change the priorities, be prepared to have the order in the array + // change. + ADC_RegularChannelConfig(ADC1, ADC_Channel_10, ADC10_RANK, + ADC_SampleTime_480Cycles); // Accelerator + ADC_RegularChannelConfig(ADC1, ADC_Channel_11, ADC11_RANK, + ADC_SampleTime_480Cycles); // Brake + + ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); + + ADC_DMACmd(ADC1, ENABLE); + + // Enable ADC1 + ADC_Cmd(ADC1, ENABLE); + + ADC_SoftwareStartConv(ADC1); } /** @@ -92,12 +108,11 @@ void BSP_ADC_Init(void) { * @param None * @return millivoltage value ADC measurement */ -int16_t BSP_ADC_Get_Value(ADC_t hardwareDevice) { - +int16_t BspAdcGetValue(Adc hardware_device) { // Get ADC raw data - uint16_t data = ADCresults[hardwareDevice]; - - return (int16_t) data; + uint16_t data = adc_results[hardware_device]; + + return (int16_t)data; } /** @@ -105,11 +120,10 @@ int16_t BSP_ADC_Get_Value(ADC_t hardwareDevice) { * @param None * @return millivoltage value ADC measurement */ -int16_t BSP_ADC_Get_Millivoltage(ADC_t hardwareDevice) { - +int16_t BspAdcGetMillivoltage(Adc hardware_device) { // Get ADC raw data - int16_t data = (int16_t) ADCresults[hardwareDevice]; - + int16_t data = (int16_t)adc_results[hardware_device]; + // Convert to millivoltage - return (ADC_RANGE_MILLIVOLTS * data) >> ADC_PRECISION_BITS; + return (int16_t)((ADC_RANGE_MILLIVOLTS * data) >> BSP_ADC_PRECISION_BITS); } diff --git a/BSP/STM32F413/Src/BSP_CAN.c b/BSP/STM32F413/Src/BSP_CAN.c index 82edafcd9..2261c28ea 100644 --- a/BSP/STM32F413/Src/BSP_CAN.c +++ b/BSP/STM32F413/Src/BSP_CAN.c @@ -1,72 +1,76 @@ /* Copyright (c) 2020 UT Longhorn Racing Solar */ #include "BSP_CAN.h" -#include "stm32f4xx.h" + #include "os.h" +#include "stm32f4xx.h" + +#define NUM_CAN_LINES 2 // The message information that we care to receive -typedef struct _msg -{ +typedef struct Msg { uint32_t id; - uint8_t data[8]; -} msg_t; + uint8_t data[BSP_CAN_DATA_LENGTH]; +} Msg; // Set up a fifo for receiving -#define FIFO_TYPE msg_t +#define FIFO_TYPE Msg #define FIFO_SIZE 25 -#define FIFO_NAME msg_queue +#define FIFO_NAME MsgQueue #include "fifo.h" -#define NUM_FILTER_REGS 4 // Number of 16 bit registers for ids in one CAN_FilterInit struct +#define NUM_FILTER_REGS \ + 4 // Number of 16 bit registers for ids in one CAN_FilterInit struct -//return error if someone tries to call from motor can +// return error if someone tries to call from motor can -static msg_queue_t gRxQueue[2]; +static MsgQueue g_rx_queue[NUM_CAN_LINES]; // Required for receiving CAN messages -static CanTxMsg gTxMessage[2]; -static CanRxMsg gRxMessage[2]; +static CanTxMsg g_tx_message[NUM_CAN_LINES]; +static CanRxMsg g_rx_message[NUM_CAN_LINES]; // User parameters for CAN events -static callback_t gRxEvent[2]; -static callback_t gTxEnd[2]; +static Callback g_rx_event[NUM_CAN_LINES]; +static Callback g_tx_end[NUM_CAN_LINES]; -void BSP_CAN1_Init(uint16_t* idWhitelist, uint8_t idWhitelistSize); -void BSP_CAN3_Init(uint16_t* idWhitelist, uint8_t idWhitelistSize); +void BspCan1Init(const uint16_t* id_whitelist, uint8_t id_whitelist_size); +void BspCan3Init(const uint16_t* id_whitelist, uint8_t id_whitelist_size); /** - * @brief Initializes the CAN module that communicates with the rest of the electrical system. - * @param rxEvent : the function to execute when recieving a message. NULL for no action. - * @param txEnd : the function to execute after transmitting a message. NULL for no action. + * @brief Initializes the CAN module that communicates with the rest of the + * electrical system. + * @param rxEvent : the function to execute when recieving a message. NULL for + * no action. + * @param txEnd : the function to execute after transmitting a message. NULL + * for no action. * @return None */ -void BSP_CAN_Init(CAN_t bus, callback_t rxEvent, callback_t txEnd, uint16_t* idWhitelist, uint8_t idWhitelistSize) { - +void BspCanInit(Can bus, Callback rx_event, Callback tx_end, + uint16_t* id_whitelist, uint8_t id_whitelist_size) { // Configure event handles - gRxEvent[bus] = rxEvent; - gTxEnd[bus] = txEnd; + g_rx_event[bus] = rx_event; + g_tx_end[bus] = tx_end; - if (bus == CAN_1) - { - BSP_CAN1_Init(idWhitelist, idWhitelistSize); - } - else - { - BSP_CAN3_Init(idWhitelist, idWhitelistSize); + if (bus == kCan1) { + BspCan1Init(id_whitelist, id_whitelist_size); + } else { + BspCan3Init(id_whitelist, id_whitelist_size); } } -void BSP_CAN1_Init(uint16_t* idWhitelist, uint8_t idWhitelistSize) { - GPIO_InitTypeDef GPIO_InitStruct; - CAN_InitTypeDef CAN_InitStruct; - NVIC_InitTypeDef NVIC_InitStruct; - CAN_FilterInitTypeDef CAN_FilterInitStruct; +void BspCan1Init(const uint16_t* id_whitelist, uint8_t id_whitelist_size) { + GPIO_InitTypeDef gpio_init_struct; + CAN_InitTypeDef can_init_struct; + NVIC_InitTypeDef nvic_init_struct; + CAN_FilterInitTypeDef can_filter_init_struct; // Initialize the queue - gRxQueue[0] = msg_queue_new(); + g_rx_queue[0] = MsgQueueNew(); - /* CAN GPIOs configuration **************************************************/ + /* CAN GPIOs configuration + * **************************************************/ /* Enable GPIO clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); @@ -76,141 +80,160 @@ void BSP_CAN1_Init(uint16_t* idWhitelist, uint8_t idWhitelistSize) { GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_CAN1); /* Configure CAN RX and TX pins */ - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* CAN configuration ********************************************************/ + gpio_init_struct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12; + gpio_init_struct.GPIO_Mode = GPIO_Mode_AF; + gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz; + gpio_init_struct.GPIO_OType = GPIO_OType_PP; + gpio_init_struct.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_Init(GPIOA, &gpio_init_struct); + + /* CAN configuration + * ********************************************************/ /* Enable CAN clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); /* CAN cell init */ - CAN_InitStruct.CAN_TTCM = DISABLE; - CAN_InitStruct.CAN_ABOM = DISABLE; - CAN_InitStruct.CAN_AWUM = DISABLE; - CAN_InitStruct.CAN_NART = DISABLE; - CAN_InitStruct.CAN_RFLM = DISABLE; - CAN_InitStruct.CAN_TXFP = ENABLE; - #ifdef CAR_LOOPBACK + can_init_struct.CAN_TTCM = DISABLE; + can_init_struct.CAN_ABOM = DISABLE; + can_init_struct.CAN_AWUM = DISABLE; + can_init_struct.CAN_NART = DISABLE; + can_init_struct.CAN_RFLM = DISABLE; + can_init_struct.CAN_TXFP = ENABLE; +#ifdef CAR_LOOPBACK CAN_InitStruct.CAN_Mode = CAN_Mode_LoopBack; - #else - CAN_InitStruct.CAN_Mode = CAN_Mode_Normal; - #endif - CAN_InitStruct.CAN_SJW = CAN_SJW_1tq; +#else + can_init_struct.CAN_Mode = CAN_Mode_Normal; +#endif + can_init_struct.CAN_SJW = CAN_SJW_1tq; /* CAN Baudrate = 125 KBps * 1/(prescalar + (prescalar*BS1) + (prescalar*BS2)) * Clk = CAN Baudrate - * The CAN clk is currently set to 20MHz (APB1 clock set to 20MHz in BSP_PLL_Init()) + * The CAN clk is currently set to 20MHz (APB1 clock set to 20MHz in + * BSP_PLL_Init()) */ - CAN_InitStruct.CAN_BS1 = CAN_BS1_3tq; - CAN_InitStruct.CAN_BS2 = CAN_BS2_4tq; - CAN_InitStruct.CAN_Prescaler = 16; - CAN_Init(CAN1, &CAN_InitStruct); - - /* CAN filter init - * Initializes hardware filter banks to be used for filtering CAN IDs (whitelist) + can_init_struct.CAN_BS1 = CAN_BS1_3tq; + can_init_struct.CAN_BS2 = CAN_BS2_4tq; + can_init_struct.CAN_Prescaler = 16; // NOLINT + CAN_Init(CAN1, &can_init_struct); + + /* CAN filter init + * Initializes hardware filter banks to be used for filtering CAN IDs + * (whitelist) */ - if(idWhitelist == NULL){ + if (id_whitelist == NULL) { // No filtering. All IDs can pass through. - CAN_FilterInitStruct.CAN_FilterNumber = 0; - CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdMask; - CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_32bit; - CAN_FilterInitStruct.CAN_FilterIdHigh = 0x0000; - CAN_FilterInitStruct.CAN_FilterIdLow = 0x0000; - CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0x0000; - CAN_FilterInitStruct.CAN_FilterMaskIdLow = 0x0000; - CAN_FilterInitStruct.CAN_FilterFIFOAssignment = 0; - CAN_FilterInitStruct.CAN_FilterActivation = ENABLE; - CAN_FilterInit(CAN1, &CAN_FilterInitStruct); - } else{ + can_filter_init_struct.CAN_FilterNumber = 0; + can_filter_init_struct.CAN_FilterMode = CAN_FilterMode_IdMask; + can_filter_init_struct.CAN_FilterScale = CAN_FilterScale_32bit; + can_filter_init_struct.CAN_FilterIdHigh = 0x0000; + can_filter_init_struct.CAN_FilterIdLow = 0x0000; + can_filter_init_struct.CAN_FilterMaskIdHigh = 0x0000; + can_filter_init_struct.CAN_FilterMaskIdLow = 0x0000; + can_filter_init_struct.CAN_FilterFIFOAssignment = 0; + can_filter_init_struct.CAN_FilterActivation = ENABLE; + CAN_FilterInit(CAN1, &can_filter_init_struct); + } else { // Filter CAN IDs // So far, if we shift whatever id we need by 5, it works - // If whitelist is passed but no valid ID exists inside of it, filter nothing i.e. no ID gets through - // MAXIMUM CAN ID ALLOWED IS 2047 - - CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdList; //list mode - CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_16bit; - CAN_FilterInitStruct.CAN_FilterFIFOAssignment = 0; - CAN_FilterInitStruct.CAN_FilterActivation = ENABLE; - uint16_t validIDCounter = 0; - - uint16_t* FilterStructPtr = (uint16_t*)&(CAN_FilterInitStruct); //address of CAN Filter Struct - for(uint8_t i = 0; i < idWhitelistSize; i++){ - if (idWhitelist[i] == 0){ //zero ID check + // If whitelist is passed but no valid ID exists inside of it, filter + // nothing i.e. no ID gets through MAXIMUM CAN ID ALLOWED IS 2047 + + can_filter_init_struct.CAN_FilterMode = + CAN_FilterMode_IdList; // list mode + can_filter_init_struct.CAN_FilterScale = CAN_FilterScale_16bit; + can_filter_init_struct.CAN_FilterFIFOAssignment = 0; + can_filter_init_struct.CAN_FilterActivation = ENABLE; + uint16_t valid_id_counter = 0; + + uint16_t* filter_struct_ptr = (uint16_t*)&( + can_filter_init_struct); // address of CAN Filter Struct + for (uint8_t i = 0; i < id_whitelist_size; i++) { + if (id_whitelist[i] == 0) { // zero ID check continue; } - - CAN_FilterInitStruct.CAN_FilterNumber = i / NUM_FILTER_REGS; //determines filter number based on CAN ID - *(FilterStructPtr + (i%NUM_FILTER_REGS)) = idWhitelist[i] << 5; - validIDCounter++; - - if(i % NUM_FILTER_REGS == NUM_FILTER_REGS - 1){ //if four elements have been written to a filter call CAN_FilterInit() - CAN_FilterInit(CAN1, &CAN_FilterInitStruct); - } - else if(i == idWhitelistSize - 1){ //we are out of elements, call CAN_FilterInit() - for(uint8_t j = i%NUM_FILTER_REGS + 1; j <= NUM_FILTER_REGS - 1; j++) // Set unfilled filter registers to 0 - *(FilterStructPtr + j) = 0x0000; - CAN_FilterInit(CAN1, &CAN_FilterInitStruct); - } - else if(validIDCounter > 112){ //All filter banks are to be filled and there is no point in filtering - for(uint8_t filter = 0; filter < 28; filter++){//Therefore, let all IDs through (no filtering) - CAN_FilterInitStruct.CAN_FilterNumber = filter; - CAN_FilterInitStruct.CAN_FilterActivation = DISABLE; - CAN_FilterInit(CAN1, &CAN_FilterInitStruct); - } + can_filter_init_struct.CAN_FilterNumber = + i / + NUM_FILTER_REGS; // determines filter number based on CAN ID + *(filter_struct_ptr + (i % NUM_FILTER_REGS)) = id_whitelist[i] + << 5; // NOLINT + valid_id_counter++; + + if (i % NUM_FILTER_REGS == + NUM_FILTER_REGS - 1) { // if four elements have been written to + // a filter call CAN_FilterInit() + CAN_FilterInit(CAN1, &can_filter_init_struct); + } else if (i == id_whitelist_size - 1) { // we are out of elements, + // call CAN_FilterInit() + for (uint8_t j = i % NUM_FILTER_REGS + 1; + j <= NUM_FILTER_REGS - 1; + j++) { // Set unfilled filter registers to 0 + *(filter_struct_ptr + j) = 0x0000; + } + + CAN_FilterInit(CAN1, &can_filter_init_struct); + } else if (valid_id_counter > + 112) { // NOLINT + // All filter banks are to be filled and there is + // no point in filtering + for (uint8_t filter = 0; filter < 28; // NOLINT + filter++) { // Therefore, let all IDs through (no + // filtering) + can_filter_init_struct.CAN_FilterNumber = filter; + can_filter_init_struct.CAN_FilterActivation = DISABLE; + CAN_FilterInit(CAN1, &can_filter_init_struct); + } } } } /* Transmit Structure preparation */ - gTxMessage[0].ExtId = 0x5; - gTxMessage[0].RTR = CAN_RTR_DATA; - gTxMessage[0].IDE = CAN_ID_STD; - gTxMessage[0].DLC = 1; + g_tx_message[0].ExtId = 0x5; // NOLINT + g_tx_message[0].RTR = CAN_RTR_DATA; + g_tx_message[0].IDE = CAN_ID_STD; + g_tx_message[0].DLC = 1; /* Receive Structure preparation */ - gRxMessage[0].StdId = 0x00; - gRxMessage[0].ExtId = 0x00; - gRxMessage[0].IDE = CAN_ID_STD; - gRxMessage[0].DLC = 0; - gRxMessage[0].FMI = 0; + g_rx_message[0].StdId = 0x00; + g_rx_message[0].ExtId = 0x00; + g_rx_message[0].IDE = CAN_ID_STD; + g_rx_message[0].DLC = 0; + g_rx_message[0].FMI = 0; /* Enable FIFO 0 message pending Interrupt */ CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // Enable Rx interrupts - NVIC_InitStruct.NVIC_IRQChannel = CAN1_RX0_IRQn; // TODO: CHECK IRQ CHANNELS - NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00; - NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00; - NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStruct); - - if(NULL != gTxEnd[0]) { + nvic_init_struct.NVIC_IRQChannel = + CAN1_RX0_IRQn; // TODO: CHECK IRQ CHANNELS + nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0x00; + nvic_init_struct.NVIC_IRQChannelSubPriority = 0x00; + nvic_init_struct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&nvic_init_struct); + + if (NULL != g_tx_end[0]) { // Enable Tx Interrupts CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); - NVIC_InitStruct.NVIC_IRQChannel = CAN1_TX_IRQn; - NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x0; // TODO: assess both of these priority settings - NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x0; - NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStruct); + nvic_init_struct.NVIC_IRQChannel = CAN1_TX_IRQn; + nvic_init_struct.NVIC_IRQChannelPreemptionPriority = + 0x0; // TODO: assess both of these priority settings + nvic_init_struct.NVIC_IRQChannelSubPriority = 0x0; + nvic_init_struct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&nvic_init_struct); } } -void BSP_CAN3_Init(uint16_t* idWhitelist, uint8_t idWhitelistSize) -{ - GPIO_InitTypeDef GPIO_InitStruct; - CAN_InitTypeDef CAN_InitStruct; - NVIC_InitTypeDef NVIC_InitStruct; - CAN_FilterInitTypeDef CAN_FilterInitStruct; +void BspCan3Init(const uint16_t* id_whitelist, uint8_t id_whitelist_size) { + GPIO_InitTypeDef gpio_init_struct; + CAN_InitTypeDef can_init_struct; + NVIC_InitTypeDef nvic_init_struct; + CAN_FilterInitTypeDef can_filter_init_struct; // Initialize the queue - gRxQueue[1] = msg_queue_new(); + g_rx_queue[1] = MsgQueueNew(); - /* CAN GPIOs configuration **************************************************/ + /* CAN GPIOs configuration + * **************************************************/ /* Enable GPIO clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); @@ -220,75 +243,87 @@ void BSP_CAN3_Init(uint16_t* idWhitelist, uint8_t idWhitelistSize) GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF11_CAN3); /* Configure CAN RX and TX pins */ - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_8; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* CAN configuration ********************************************************/ + gpio_init_struct.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_8; + gpio_init_struct.GPIO_Mode = GPIO_Mode_AF; + gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz; + gpio_init_struct.GPIO_OType = GPIO_OType_PP; + gpio_init_struct.GPIO_PuPd = GPIO_PuPd_UP; + GPIO_Init(GPIOA, &gpio_init_struct); + + /* CAN configuration + * ********************************************************/ /* Enable CAN clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN3, ENABLE); /* CAN cell init */ - CAN_InitStruct.CAN_TTCM = DISABLE; - CAN_InitStruct.CAN_ABOM = DISABLE; - CAN_InitStruct.CAN_AWUM = DISABLE; - CAN_InitStruct.CAN_NART = DISABLE; - CAN_InitStruct.CAN_RFLM = DISABLE; - CAN_InitStruct.CAN_TXFP = ENABLE; - #ifdef MOTOR_LOOPBACK + can_init_struct.CAN_TTCM = DISABLE; + can_init_struct.CAN_ABOM = DISABLE; + can_init_struct.CAN_AWUM = DISABLE; + can_init_struct.CAN_NART = DISABLE; + can_init_struct.CAN_RFLM = DISABLE; + can_init_struct.CAN_TXFP = ENABLE; +#ifdef MOTOR_LOOPBACK CAN_InitStruct.CAN_Mode = CAN_Mode_LoopBack; - #else - CAN_InitStruct.CAN_Mode = CAN_Mode_Normal; - #endif - CAN_InitStruct.CAN_SJW = CAN_SJW_1tq; +#else + can_init_struct.CAN_Mode = CAN_Mode_Normal; +#endif + can_init_struct.CAN_SJW = CAN_SJW_1tq; /* CAN Baudrate = 125 KBps * 1/(prescalar + (prescalar*BS1) + (prescalar*BS2)) * Clk = CAN Baudrate - * The CAN clk is currently set to 20MHz (APB1 clock set to 20MHz in BSP_PLL_Init()) + * The CAN clk is currently set to 20MHz (APB1 clock set to 20MHz in + * BSP_PLL_Init()) */ - CAN_InitStruct.CAN_BS1 = CAN_BS1_3tq; - CAN_InitStruct.CAN_BS2 = CAN_BS2_4tq; - CAN_InitStruct.CAN_Prescaler = 16; - CAN_Init(CAN3, &CAN_InitStruct); - - /* CAN filter init - * Initializes hardware filter banks to be used for filtering CAN IDs (whitelist) + can_init_struct.CAN_BS1 = CAN_BS1_3tq; + can_init_struct.CAN_BS2 = CAN_BS2_4tq; + can_init_struct.CAN_Prescaler = 16; // NOLINT + CAN_Init(CAN3, &can_init_struct); + + /* CAN filter init + * Initializes hardware filter banks to be used for filtering CAN IDs + * (whitelist) */ - if(idWhitelist == NULL){ + if (id_whitelist == NULL) { // No filtering. All IDs can pass through. - CAN_FilterInitStruct.CAN_FilterNumber = 0; - CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdMask; - CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_32bit; - CAN_FilterInitStruct.CAN_FilterIdHigh = 0x0000; - CAN_FilterInitStruct.CAN_FilterIdLow = 0x0000; - CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0x0000; - CAN_FilterInitStruct.CAN_FilterMaskIdLow = 0x0000; - CAN_FilterInitStruct.CAN_FilterFIFOAssignment = 0; - CAN_FilterInitStruct.CAN_FilterActivation = ENABLE; - CAN_FilterInit(CAN3, &CAN_FilterInitStruct); - } else{ + can_filter_init_struct.CAN_FilterNumber = 0; + can_filter_init_struct.CAN_FilterMode = CAN_FilterMode_IdMask; + can_filter_init_struct.CAN_FilterScale = CAN_FilterScale_32bit; + can_filter_init_struct.CAN_FilterIdHigh = 0x0000; + can_filter_init_struct.CAN_FilterIdLow = 0x0000; + can_filter_init_struct.CAN_FilterMaskIdHigh = 0x0000; + can_filter_init_struct.CAN_FilterMaskIdLow = 0x0000; + can_filter_init_struct.CAN_FilterFIFOAssignment = 0; + can_filter_init_struct.CAN_FilterActivation = ENABLE; + CAN_FilterInit(CAN3, &can_filter_init_struct); + } else { // Filter CAN IDs - CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdList; //list mode - CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_16bit; - CAN_FilterInitStruct.CAN_FilterFIFOAssignment = 0; - CAN_FilterInitStruct.CAN_FilterActivation = ENABLE; - - uint16_t* FilterStructPtr = (uint16_t*)&(CAN_FilterInitStruct); //address of CAN Filter Struct - for(uint8_t i = 0; i < idWhitelistSize; i++){ - CAN_FilterInitStruct.CAN_FilterNumber = i / NUM_FILTER_REGS; //determines filter number based on CAN ID - *(FilterStructPtr + (i%NUM_FILTER_REGS)) = idWhitelist[i]; - - if(i % NUM_FILTER_REGS == NUM_FILTER_REGS - 1){ //if four elements have been written to a filter call CAN_FilterInit() - CAN_FilterInit(CAN3, &CAN_FilterInitStruct); - } - else if(i == idWhitelistSize - 1){ //we are out of elements, call CAN_FilterInit() - for(uint8_t j = i%NUM_FILTER_REGS + 1; j <= NUM_FILTER_REGS - 1; j++) // Set unfilled filter registers to 0 - *(FilterStructPtr + j) = 0x0000; - - CAN_FilterInit(CAN3, &CAN_FilterInitStruct); + can_filter_init_struct.CAN_FilterMode = + CAN_FilterMode_IdList; // list mode + can_filter_init_struct.CAN_FilterScale = CAN_FilterScale_16bit; + can_filter_init_struct.CAN_FilterFIFOAssignment = 0; + can_filter_init_struct.CAN_FilterActivation = ENABLE; + + uint16_t* filter_struct_ptr = (uint16_t*)&( + can_filter_init_struct); // address of CAN Filter Struct + for (uint8_t i = 0; i < id_whitelist_size; i++) { + can_filter_init_struct.CAN_FilterNumber = + i / + NUM_FILTER_REGS; // determines filter number based on CAN ID + *(filter_struct_ptr + (i % NUM_FILTER_REGS)) = id_whitelist[i]; + + if (i % NUM_FILTER_REGS == + NUM_FILTER_REGS - 1) { // if four elements have been written to + // a filter call CAN_FilterInit() + CAN_FilterInit(CAN3, &can_filter_init_struct); + } else if (i == id_whitelist_size - 1) { // we are out of elements, + // call CAN_FilterInit() + for (uint8_t j = i % NUM_FILTER_REGS + 1; + j <= NUM_FILTER_REGS - 1; + j++) { // Set unfilled filter registers to 0 + *(filter_struct_ptr + j) = 0x0000; + } + + CAN_FilterInit(CAN3, &can_filter_init_struct); } } } @@ -296,61 +331,63 @@ void BSP_CAN3_Init(uint16_t* idWhitelist, uint8_t idWhitelistSize) // CAN_SlaveStartBank(CAN1, 0); /* Transmit Structure preparation */ - gTxMessage[1].ExtId = 0x5; - gTxMessage[1].RTR = CAN_RTR_DATA; - gTxMessage[1].IDE = CAN_ID_STD; - gTxMessage[1].DLC = 1; + g_tx_message[1].ExtId = 0x5; // NOLINT + g_tx_message[1].RTR = CAN_RTR_DATA; + g_tx_message[1].IDE = CAN_ID_STD; + g_tx_message[1].DLC = 1; /* Receive Structure preparation */ - gRxMessage[1].StdId = 0x00; - gRxMessage[1].ExtId = 0x00; - gRxMessage[1].IDE = CAN_ID_STD; - gRxMessage[1].DLC = 0; - gRxMessage[1].FMI = 0; + g_rx_message[1].StdId = 0x00; + g_rx_message[1].ExtId = 0x00; + g_rx_message[1].IDE = CAN_ID_STD; + g_rx_message[1].DLC = 0; + g_rx_message[1].FMI = 0; /* Enable FIFO 0 message pending Interrupt */ CAN_ITConfig(CAN3, CAN_IT_FMP0, ENABLE); - //TODO: Double check preemption priority and subpriority - // Enable Rx interrupts - NVIC_InitStruct.NVIC_IRQChannel = CAN3_RX0_IRQn; - NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00; - NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00; - NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStruct); + // TODO: Double check preemption priority and subpriority + // Enable Rx interrupts + nvic_init_struct.NVIC_IRQChannel = CAN3_RX0_IRQn; + nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0x00; + nvic_init_struct.NVIC_IRQChannelSubPriority = 0x00; + nvic_init_struct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&nvic_init_struct); // Enable Tx interrupts - if(NULL != gTxEnd[1]){ - CAN_ITConfig(CAN3,CAN_IT_TME,ENABLE); - NVIC_InitStruct.NVIC_IRQChannel = CAN3_TX_IRQn; - NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00; - NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00; - NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStruct); + if (NULL != g_tx_end[1]) { + CAN_ITConfig(CAN3, CAN_IT_TME, ENABLE); + nvic_init_struct.NVIC_IRQChannel = CAN3_TX_IRQn; + nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0x00; + nvic_init_struct.NVIC_IRQChannelSubPriority = 0x00; + nvic_init_struct.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&nvic_init_struct); } } /** * @brief Transmits the data onto the CAN bus with the specified id - * @param id : Message of ID. Also indicates the priority of message. The lower the value, the higher the priority. + * @param id : Message of ID. Also indicates the priority of message. The + * lower the value, the higher the priority. * @param data : data to be transmitted. The max is 8 bytes. - * @param length : num of bytes of data to be transmitted. This must be <= 8 bytes or else the rest of the message is dropped. - * @return ERROR if module was unable to transmit the data onto the CAN bus. SUCCESS indicates data was transmitted. + * @param length : num of bytes of data to be transmitted. This must be <= 8 + * bytes or else the rest of the message is dropped. + * @return ERROR if module was unable to transmit the data onto the CAN bus. + * SUCCESS indicates data was transmitted. */ -ErrorStatus BSP_CAN_Write(CAN_t bus, uint32_t id, uint8_t data[8], uint8_t length) -{ - - memset(gTxMessage[bus].Data, 0, sizeof gTxMessage[bus].Data); - gTxMessage[bus].StdId = id; - gTxMessage[bus].DLC = length; - for (int i = 0; i < length; i++) - { - gTxMessage[bus].Data[i] = data[i]; +ErrorStatus BspCanWrite(Can bus, uint32_t id, + const uint8_t data[BSP_CAN_DATA_LENGTH], + uint8_t length) { + memset(g_tx_message[bus].Data, 0, sizeof g_tx_message[bus].Data); + g_tx_message[bus].StdId = id; + g_tx_message[bus].DLC = length; + for (int i = 0; i < length; i++) { + g_tx_message[bus].Data[i] = data[i]; } - uint8_t retVal = (CAN_Transmit(bus == CAN_1 ? CAN1 : CAN3, &gTxMessage[bus]) != 0); - if (retVal == CAN_TxStatus_NoMailBox) - { + uint8_t ret_val = + (CAN_Transmit(bus == kCan1 ? CAN1 : CAN3, &g_tx_message[bus]) != 0); + if (ret_val == CAN_TxStatus_NoMailBox) { return ERROR; } return SUCCESS; @@ -361,24 +398,23 @@ ErrorStatus BSP_CAN_Write(CAN_t bus, uint32_t id, uint8_t data[8], uint8_t lengt * @note Non-blocking statement * @pre The data parameter must be at least 8 bytes or hardfault may occur. * @param id : pointer to store id of the message that was received. - * @param data : pointer to store data that was received. Must be 8bytes or bigger. - * @return ERROR if nothing was received so ignore id and data that was received. SUCCESS indicates data was received and stored. + * @param data : pointer to store data that was received. Must be 8bytes or + * bigger. + * @return ERROR if nothing was received so ignore id and data that was + * received. SUCCESS indicates data was received and stored. */ -ErrorStatus BSP_CAN_Read(CAN_t bus, uint32_t *id, uint8_t *data) -{ +ErrorStatus BspCanRead(Can bus, uint32_t* id, uint8_t* data) { // If the queue is empty, return err - if (msg_queue_is_empty(&gRxQueue[bus])) - { + if (MsgQueueIsEmpty(&g_rx_queue[bus])) { return ERROR; } // Get the message - msg_t msg; - msg_queue_get(&gRxQueue[bus], &msg); + Msg msg; + MsgQueueGet(&g_rx_queue[bus], &msg); // Transfer the message to the provided pointers - for (int i = 0; i < 8; i++) - { + for (int i = 0; i < BSP_CAN_DATA_LENGTH; i++) { // NOLINT data[i] = msg.data[i]; } *id = msg.id; @@ -386,80 +422,69 @@ ErrorStatus BSP_CAN_Read(CAN_t bus, uint32_t *id, uint8_t *data) return SUCCESS; } -void CAN3_RX0_IRQHandler() -{ +void Can3RX0IrqHandler() { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSIntEnter(); CPU_CRITICAL_EXIT(); // Take any pending messages into a queue - while (CAN_MessagePending(CAN3, CAN_FIFO0)) - { - CAN_Receive(CAN3, CAN_FIFO0, &gRxMessage[1]); + while (CAN_MessagePending(CAN3, CAN_FIFO0)) { + CAN_Receive(CAN3, CAN_FIFO0, &g_rx_message[1]); - msg_t rxMsg; - rxMsg.id = gRxMessage[1].StdId; - memcpy(&rxMsg.data[0], gRxMessage[1].Data, 8); + Msg rx_msg; + rx_msg.id = g_rx_message[1].StdId; + memcpy(&rx_msg.data[0], g_rx_message[1].Data, BSP_CAN_DATA_LENGTH); // Place the message in the queue - if (msg_queue_put(&gRxQueue[1], rxMsg)) - { + if (MsgQueuePut(&g_rx_queue[1], rx_msg)) { // If the queue was not already full... // Call the driver-provided function, if it is not null - if (gRxEvent[1] != NULL) - { - gRxEvent[1](); + if (g_rx_event[1] != NULL) { + g_rx_event[1](); } - } - else - { - // If the queue is already full, then we can't really do anything else + } else { + // If the queue is already full, then we can't really do anything + // else break; } } - OSIntExit(); // Signal to uC/OS + OSIntExit(); // Signal to uC/OS } -void CAN1_RX0_IRQHandler(void) -{ +void Can1RX0IrqHandler(void) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSIntEnter(); CPU_CRITICAL_EXIT(); // Take any pending messages into a queue - while (CAN_MessagePending(CAN1, CAN_FIFO0)) - { - CAN_Receive(CAN1, CAN_FIFO0, &gRxMessage[0]); + while (CAN_MessagePending(CAN1, CAN_FIFO0)) { + CAN_Receive(CAN1, CAN_FIFO0, &g_rx_message[0]); - msg_t rxMsg; - rxMsg.id = gRxMessage[0].StdId; - memcpy(&rxMsg.data[0], gRxMessage[0].Data, 8); + Msg rx_msg; + rx_msg.id = g_rx_message[0].StdId; + memcpy(&rx_msg.data[0], g_rx_message[0].Data, BSP_CAN_DATA_LENGTH); // Place the message in the queue - if (msg_queue_put(&gRxQueue[0], rxMsg)) - { + if (MsgQueuePut(&g_rx_queue[0], rx_msg)) { // If the queue was not already full... // Call the driver-provided function, if it is not null - if (gRxEvent[0] != NULL) - { - gRxEvent[0](); + if (g_rx_event[0] != NULL) { + g_rx_event[0](); } - } - else - { - // If the queue is already full, then we can't really do anything else + } else { + // If the queue is already full, then we can't really do anything + // else break; } } - OSIntExit(); // Signal to uC/OS + OSIntExit(); // Signal to uC/OS } -void CAN3_TX_IRQHandler(void) -{ +void Can3TxIrqHandler(void) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSIntEnter(); @@ -469,20 +494,19 @@ void CAN3_TX_IRQHandler(void) CAN_ClearFlag(CAN3, CAN_FLAG_RQCP0 | CAN_FLAG_RQCP1 | CAN_FLAG_RQCP2); // Call the function provided - gTxEnd[1](); + g_tx_end[1](); - OSIntExit(); // Signal to uC/OS + OSIntExit(); // Signal to uC/OS } -void CAN1_TX_IRQHandler(void) -{ +void Can1TxIrqHandler(void) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSIntEnter(); CPU_CRITICAL_EXIT(); // Call the function provided CAN_ClearFlag(CAN1, CAN_FLAG_RQCP0 | CAN_FLAG_RQCP1 | CAN_FLAG_RQCP2); - gTxEnd[0](); + g_tx_end[0](); - OSIntExit(); // Signal to uC/OS + OSIntExit(); // Signal to uC/OS } diff --git a/BSP/STM32F413/Src/BSP_GPIO.c b/BSP/STM32F413/Src/BSP_GPIO.c old mode 100755 new mode 100644 index ffd20a800..fe0eafa8f --- a/BSP/STM32F413/Src/BSP_GPIO.c +++ b/BSP/STM32F413/Src/BSP_GPIO.c @@ -1,110 +1,106 @@ /* Copyright (c) 2021 UT Longhorn Racing Solar */ #include "BSP_GPIO.h" + #include "Tasks.h" +#include "common.h" -static GPIO_TypeDef* GPIO_GetPort(port_t port){ - const GPIO_TypeDef* gpio_mapping[4] = {GPIOA, GPIOB, GPIOC, GPIOD}; +#define NUM_PORTS 4 - return (GPIO_TypeDef *) gpio_mapping[port]; +static GPIO_TypeDef *gpioGetPort(Port port) { + const GPIO_TypeDef *gpio_mapping[NUM_PORTS] = {GPIOA, GPIOB, GPIOC, GPIOD}; + return (GPIO_TypeDef *)gpio_mapping[port]; } - /** * @brief Initializes a GPIO port * @param port - port to initialize * @param mask - pins - * @param direction - input or output + * @param direction - input or output * @return None - */ - -void BSP_GPIO_Init(port_t port, uint16_t mask, direction_t direction){ - GPIO_InitTypeDef GPIO_InitStruct; - - RCC_AHB1PeriphClockCmd(1 << port, ENABLE); - // Configure the pins to be generic GPIO - GPIO_InitStruct.GPIO_Pin = mask; - GPIO_InitStruct.GPIO_Mode = direction ? GPIO_Mode_OUT : GPIO_Mode_IN; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_Speed = GPIO_Low_Speed; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // TODO: verify - - // Compute the offset for the port handle from the port passed in - GPIO_TypeDef *portHandle = GPIO_GetPort(port); + */ + +void BspGpioInit(Port port, uint16_t mask, Direction direction) { + GPIO_InitTypeDef gpio_init_struct; + + RCC_AHB1PeriphClockCmd(1 << port, ENABLE); + // Configure the pins to be generic GPIO + gpio_init_struct.GPIO_Pin = mask; + gpio_init_struct.GPIO_Mode = direction ? GPIO_Mode_OUT : GPIO_Mode_IN; + gpio_init_struct.GPIO_OType = GPIO_OType_PP; + gpio_init_struct.GPIO_Speed = GPIO_Low_Speed; + gpio_init_struct.GPIO_PuPd = GPIO_PuPd_NOPULL; // TODO: verify + + // Compute the offset for the port handle from the port passed in + GPIO_TypeDef *port_handle = gpioGetPort(port); // Initialize the GPIO - GPIO_Init(portHandle, &GPIO_InitStruct); + GPIO_Init(port_handle, &gpio_init_struct); } - /** * @brief Reads value of the specified port * @param port to read * @return data of the port - */ + */ -uint16_t BSP_GPIO_Read(port_t port){ - GPIO_TypeDef *gpio_port = GPIO_GetPort(port); +uint16_t BspGpioRead(Port port) { + GPIO_TypeDef *gpio_port = gpioGetPort(port); - return GPIO_ReadInputData(gpio_port); + return GPIO_ReadInputData(gpio_port); } - /** - * @brief Writes data to a specified port + * @brief Writes data to a specified port * @param port port to write to - * @param data data to write + * @param data data to write * @return None - */ + */ -void BSP_GPIO_Write(port_t port, uint16_t data){ - GPIO_TypeDef *gpio_port = GPIO_GetPort(port); +void BspGpioWrite(Port port, uint16_t data) { + GPIO_TypeDef *gpio_port = gpioGetPort(port); - GPIO_Write(gpio_port, data); + GPIO_Write(gpio_port, data); } - /** - * @brief Reads data from a specified input pin (not applicable to output pins) + * @brief Reads data from a specified input pin (not applicable to output + * pins) * @param port The port to read from - * @param pin The pin to read from + * @param pin The pin to read from * @return State of the pin - */ + */ -uint8_t BSP_GPIO_Read_Pin(port_t port, uint16_t pinmask){ - GPIO_TypeDef *gpio_port = GPIO_GetPort(port); +uint8_t BspGpioReadPin(Port port, uint16_t pin_mask) { + GPIO_TypeDef *gpio_port = gpioGetPort(port); - return GPIO_ReadInputDataBit(gpio_port, pinmask); + return GPIO_ReadInputDataBit(gpio_port, pin_mask); } - - /** * @brief Writes data to a specified pin * @param port The port to write to - * @param pin The pin to write to + * @param pin The pin to write to * @param state true=ON or false=OFF * @return None - */ + */ -void BSP_GPIO_Write_Pin(port_t port, uint16_t pinmask, bool state){ - GPIO_TypeDef *gpio_port = GPIO_GetPort(port); - GPIO_WriteBit(gpio_port, pinmask, (state==ON)?Bit_SET:Bit_RESET); +void BspGpioWritePin(Port port, uint16_t pin_mask, bool state) { + GPIO_TypeDef *gpio_port = gpioGetPort(port); + GPIO_WriteBit(gpio_port, pin_mask, (state == ON) ? Bit_SET : Bit_RESET); } - - /** * @brief Returns state of output pin (not applicable to input pins) * @param port The port to get state from * @param pin The pin to get state from * @return 1 if pin is high, 0 if low - */ + */ -uint8_t BSP_GPIO_Get_State(port_t port, uint16_t pin){ - GPIO_TypeDef *gpio_port = GPIO_GetPort(port); +uint8_t BspGpioGetState(Port port, uint16_t pin) { + GPIO_TypeDef *gpio_port = gpioGetPort(port); - return GPIO_ReadOutputDataBit(gpio_port, pin); + return GPIO_ReadOutputDataBit(gpio_port, pin); } diff --git a/BSP/STM32F413/Src/BSP_SPI.c b/BSP/STM32F413/Src/BSP_SPI.c deleted file mode 100644 index 32e8fd4c1..000000000 --- a/BSP/STM32F413/Src/BSP_SPI.c +++ /dev/null @@ -1,251 +0,0 @@ -/* Copyright (c) 2020 UT Longhorn Racing Solar */ - -#include "BSP_SPI.h" -#include "stm32f4xx.h" -#include "os.h" - -#define SPI_PORT SPI1 - -// These are the sizes of the fifos. -// You can write/read more than this at once, -// but performance will degrade slightly. -#define TX_SIZE 128 -#define RX_SIZE 64 - -#define FIFO_TYPE uint8_t -#define FIFO_SIZE TX_SIZE -#define FIFO_NAME txfifo -#include "fifo.h" - -#define FIFO_TYPE uint8_t -#define FIFO_SIZE RX_SIZE -#define FIFO_NAME rxfifo -#include "fifo.h" - -static txfifo_t spiTxFifo; -static rxfifo_t spiRxFifo; - -static OS_SEM SPI_Update_Sem4; - -static void spi_post(void) { - OS_ERR err; - OSSemPost(&SPI_Update_Sem4, OS_OPT_POST_1, &err); - // TODO: error handling -} - -static void spi_pend(void) { - OS_ERR err; - CPU_TS ts; - OSSemPend(&SPI_Update_Sem4, 0, OS_OPT_PEND_BLOCKING, &ts, &err); - // TODO: error handling -} - -// Use this inline function to wait until SPI communication is complete -static inline void SPI_Wait(void) { - while((SPI1->SR & (SPI_SR_TXE | SPI_SR_RXNE)) == 0 || (SPI1->SR & SPI_SR_BSY)); -} - -// Use this inline function to wait until SPI communication is complete -static inline void SPI_WaitTx(void) { - SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE); - spi_pend(); -} - -/** SPI_WriteRead - * @brief Sends and receives a byte of data on the SPI line. - * @param txData single byte that will be sent to the device. - * @return rxData single byte that was read from the device. - */ -static uint8_t SPI_WriteRead(uint8_t txData){ - - SPI_TypeDef *bus = SPI_PORT; - - SPI_Wait(); - bus->DR = txData & 0x00FF; - SPI_Wait(); - return bus->DR & 0x00FF; -} - - -/** - * @brief Initializes the SPI port. - * @return None - */ -void BSP_SPI_Init(void) { - - OS_ERR err; - OSSemCreate(&SPI_Update_Sem4, "SPI Update", 0, &err); - - spiTxFifo = txfifo_new(); - spiRxFifo = rxfifo_new(); - - GPIO_InitTypeDef GPIO_InitStruct; - SPI_InitTypeDef SPI_InitStruct; - - - - // SPI configuration: - // speed : 125kbps - // CPOL : 1 (polarity of clock during idle is high) - // CPHA : 1 (tx recorded during 2nd edge) - // Pins: - // SPI1: - // PA5 : SCK - // PA6 : MISO - // PA7 : MOSI - // PA4 : CS - - // Initialize clocks - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); - - // Initialize pins - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_Init(GPIOA, &GPIO_InitStruct); - - GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); - GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); - - // Initialize SPI port - SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; - SPI_InitStruct.SPI_Mode = SPI_Mode_Master; - SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; - SPI_InitStruct.SPI_CPOL = SPI_CPOL_High; - SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge; - SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; - SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; - SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; - SPI_InitStruct.SPI_CRCPolynomial = 0; - SPI_Init(SPI1, &SPI_InitStruct); - SPI_Cmd(SPI1, ENABLE); - - // Initialize CS pin - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_Init(GPIOA, &GPIO_InitStruct); - - // Configure SPI1 interrupt priority - NVIC_InitTypeDef NVIC_InitStruct; - NVIC_InitStruct.NVIC_IRQChannel = SPI1_IRQn; - NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStruct); - - // Enable the Rx buffer not empty interrupt - SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE); -} - -/** - * @brief Transmits data to through SPI. - * @note Blocking statement - * @param txBuf data array that contains the data to be sent. - * @param txLen length of data array. - * @return None - * Do not call from an ISR - */ -void BSP_SPI_Write(uint8_t *txBuf, uint8_t txLen) { - // If we're below an experimentally-determined value, just use polling - if(txLen < 8) { - for(int i = 0; i < txLen; i++) { - SPI_WriteRead(txBuf[i]); - } - } else { - // If we have a lot of data, we use interrupts to mitigate it - // Fill as much of the fifo as possible - size_t i = 0; - while(i < txLen) { - // Put as much data into the fifo as can fit - while(i < txLen && txfifo_put(&spiTxFifo, txBuf[i])) { - i++; - } - - // Wait for the transmission to complete - SPI_WaitTx(); - } - - SPI_Wait(); - } -} - -/** - * @brief Gets the data from SPI. - * @note Blocking statement - * @param rxBuf data array to store the data that is received. - * @param rxLen length of data array. - * @return None - * Do not call from an ISR - */ -void BSP_SPI_Read(uint8_t *rxBuf, uint8_t rxLen) { - - // If we have only a little amount of data, just use polling - if(rxLen < 8) { - for(int i = 0; i < rxLen; i++) { - rxBuf[i] = SPI_WriteRead(0x00); - } - } else { - SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE); - // Fill the fifo with zeros to read - size_t i = 0, r = 0; - // Empty the fifo - rxfifo_renew(&spiRxFifo); - // Read the data - while(i < rxLen) { - // Keep filling the fifo with data until we have read everything - while(i < rxLen && txfifo_put(&spiTxFifo, 0)) { - i++; - } - - // Wait for the transmission to complete - SPI_WaitTx(); - - // Busy wait the last bit, just to ensure all bytes have been received - SPI_Wait(); - - // Copy the data out of the fifo - while(r < i && rxfifo_get(&spiRxFifo, &rxBuf[r])) { - r++; - } - } - SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE); - } -} - - -void SPI1_IRQHandler(){ - // Save the CPU registers - CPU_SR_ALLOC(); - - // Protect a critical section - CPU_CRITICAL_ENTER(); - - // make the kernel aware that the interrupt has started - OSIntEnter(); - CPU_CRITICAL_EXIT(); - - // Handle the interrupts - if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_TXE) == SET){ - // Check to see if there is any data awaiting transmission - if(!txfifo_get(&spiTxFifo, (uint8_t*)&SPI1->DR)) { - // We are out of data, so turn off the interrupt and post the semaphore - SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, DISABLE); - spi_post(); - } - } - if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET){ - // Get the incoming data, put it in the fifo - // If this overflows, it's the user's fault. - rxfifo_put(&spiRxFifo, SPI1->DR); - } - - //make the kernel aware that the interrupt has ended - OSIntExit(); -} diff --git a/BSP/STM32F413/Src/BSP_Switches.c b/BSP/STM32F413/Src/BSP_Switches.c deleted file mode 100644 index e69de29bb..000000000 diff --git a/BSP/STM32F413/Src/BSP_UART.c b/BSP/STM32F413/Src/BSP_UART.c index b7ed87423..35aa67122 100644 --- a/BSP/STM32F413/Src/BSP_UART.c +++ b/BSP/STM32F413/Src/BSP_UART.c @@ -1,323 +1,344 @@ /* Copyright (c) 2020 UT Longhorn Racing Solar */ #include "BSP_UART.h" -#include "stm32f4xx.h" + #include "os.h" +#include "stm32f4xx.h" -#define TX_SIZE 128 -#define RX_SIZE 64 +#define TX_SIZE 128 +#define RX_SIZE 64 +#define NUM_USART 2 // Initialize the FIFOs #define FIFO_TYPE char #define FIFO_SIZE TX_SIZE -#define FIFO_NAME txfifo +#define FIFO_NAME TxFifo #include "fifo.h" -static txfifo_t usbTxFifo; -static txfifo_t displayTxFifo; +static TxFifo usb_tx_fifo; +static TxFifo display_tx_fifo; #define FIFO_TYPE char #define FIFO_SIZE RX_SIZE -#define FIFO_NAME rxfifo +#define FIFO_NAME RxFifo #include "fifo.h" -static rxfifo_t usbRxFifo; -static rxfifo_t displayRxFifo; +static RxFifo usb_rx_fifo; +static RxFifo display_rx_fifo; -static bool usbLineReceived = false; -static bool displayLineReceived = false; +static bool usb_line_received = false; +static bool display_line_received = false; -static callback_t usbRxCallback = NULL; -static callback_t usbTxCallback = NULL; -static callback_t displayRxCallback = NULL; -static callback_t displayTxCallback = NULL; +static Callback usb_rx_callback = NULL; +static Callback usb_tx_callback = NULL; +static Callback display_rx_callback = NULL; +static Callback display_tx_callback = NULL; -static rxfifo_t *rx_fifos[NUM_UART] = {&usbRxFifo, &displayRxFifo}; -static txfifo_t *tx_fifos[NUM_UART] = {&usbTxFifo, &displayTxFifo}; -static bool *lineRecvd[NUM_UART] = {&usbLineReceived, &displayLineReceived}; -static USART_TypeDef *handles[NUM_UART] = {USART2, USART3}; +static RxFifo *rx_fifos[NUM_USART] = {&usb_rx_fifo, &display_rx_fifo}; +static TxFifo *tx_fifos[NUM_USART] = {&usb_tx_fifo, &display_tx_fifo}; +static bool *line_recvd_global[NUM_USART] = {&usb_line_received, + &display_line_received}; +static USART_TypeDef *handles[NUM_USART] = {USART2, USART3}; -static void USART_DISPLAY_Init() { - displayTxFifo = txfifo_new(); - displayRxFifo = rxfifo_new(); +static void usartDisplayInit() { + display_tx_fifo = TxFifoNew(); + display_rx_fifo = RxFifoNew(); - GPIO_InitTypeDef GPIO_InitStruct = {0}; - USART_InitTypeDef UART_InitStruct = {0}; + GPIO_InitTypeDef gpio_init_struct = {0}; + USART_InitTypeDef usart_init_struct = {0}; // Initialize clocks - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); // Initialize pins - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz; - GPIO_Init(GPIOB, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5; - GPIO_Init(GPIOC, &GPIO_InitStruct); + gpio_init_struct.GPIO_Pin = GPIO_Pin_10; + gpio_init_struct.GPIO_Mode = GPIO_Mode_AF; + gpio_init_struct.GPIO_OType = GPIO_OType_PP; + gpio_init_struct.GPIO_PuPd = GPIO_PuPd_UP; + gpio_init_struct.GPIO_Speed = GPIO_Speed_25MHz; + GPIO_Init(GPIOB, &gpio_init_struct); + gpio_init_struct.GPIO_Pin = GPIO_Pin_5; + GPIO_Init(GPIOC, &gpio_init_struct); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_USART3); - //Initialize UART3 - UART_InitStruct.USART_BaudRate = 115200; - UART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; - UART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; - UART_InitStruct.USART_Parity = USART_Parity_No; - UART_InitStruct.USART_StopBits = USART_StopBits_1; - UART_InitStruct.USART_WordLength = USART_WordLength_8b; - USART_Init(USART3, &UART_InitStruct); + // Initialize USART3 + usart_init_struct.USART_BaudRate = 115200; // NOLINT + usart_init_struct.USART_HardwareFlowControl = + USART_HardwareFlowControl_None; + usart_init_struct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; + usart_init_struct.USART_Parity = USART_Parity_No; + usart_init_struct.USART_StopBits = USART_StopBits_1; + usart_init_struct.USART_WordLength = USART_WordLength_8b; + USART_Init(USART3, &usart_init_struct); // Enable interrupts USART_Cmd(USART3, ENABLE); // Enable NVIC - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + NVIC_InitTypeDef nvic_init_structure; + nvic_init_structure.NVIC_IRQChannel = USART3_IRQn; + nvic_init_structure.NVIC_IRQChannelPreemptionPriority = 1; + nvic_init_structure.NVIC_IRQChannelSubPriority = 0; + nvic_init_structure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&nvic_init_structure); } -static void USART_USB_Init() { - usbTxFifo = txfifo_new(); - usbRxFifo = rxfifo_new(); +static void usartUsbInit() { + usb_tx_fifo = TxFifoNew(); + usb_rx_fifo = RxFifoNew(); - GPIO_InitTypeDef GPIO_InitStruct = {0}; - USART_InitTypeDef UART_InitStruct = {0}; + GPIO_InitTypeDef gpio_init_struct = {0}; + USART_InitTypeDef usart_init_struct = {0}; // Initialize clocks RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // Initialize pins - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz; - GPIO_Init(GPIOA, &GPIO_InitStruct); + gpio_init_struct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; + gpio_init_struct.GPIO_Mode = GPIO_Mode_AF; + gpio_init_struct.GPIO_OType = GPIO_OType_PP; + gpio_init_struct.GPIO_PuPd = GPIO_PuPd_UP; + gpio_init_struct.GPIO_Speed = GPIO_Speed_25MHz; + GPIO_Init(GPIOA, &gpio_init_struct); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); - //Initialize UART2 - UART_InitStruct.USART_BaudRate = 115200; - UART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; - UART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; - UART_InitStruct.USART_Parity = USART_Parity_No; - UART_InitStruct.USART_StopBits = USART_StopBits_1; - UART_InitStruct.USART_WordLength = USART_WordLength_8b; - USART_Init(USART2, &UART_InitStruct); + // Initialize USART2 + usart_init_struct.USART_BaudRate = 115200; // NOLINT + usart_init_struct.USART_HardwareFlowControl = + USART_HardwareFlowControl_None; + usart_init_struct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; + usart_init_struct.USART_Parity = USART_Parity_No; + usart_init_struct.USART_StopBits = USART_StopBits_1; + usart_init_struct.USART_WordLength = USART_WordLength_8b; + USART_Init(USART2, &usart_init_struct); USART_Cmd(USART2, ENABLE); // Enable NVIC - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + NVIC_InitTypeDef nvic_init_structure; + nvic_init_structure.NVIC_IRQChannelPreemptionPriority = 1; + nvic_init_structure.NVIC_IRQChannelSubPriority = 0; + nvic_init_structure.NVIC_IRQChannel = USART2_IRQn; + nvic_init_structure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&nvic_init_structure); setvbuf(stdout, NULL, _IONBF, 0); } /** - * @brief Initializes the UART peripheral + * @brief Initializes the USART peripheral */ -static void BSP_UART_Init_Internal(callback_t rxCallback, callback_t txCallback, UART_t uart) { - switch(uart){ - case UART_2: // their UART_USB - USART_USB_Init(); - usbRxCallback = rxCallback; - usbTxCallback = txCallback; - break; - case UART_3: // their UART_DISPLAY - USART_DISPLAY_Init(); - displayRxCallback = rxCallback; - displayTxCallback = txCallback; - break; - default: - // Error - break; +static void bspUartInitInternal(Callback rx_callback, Callback tx_callback, + Uart usart) { + switch (usart) { + case kUart2: // their USART_USB + usartUsbInit(); + usb_rx_callback = rx_callback; + usb_tx_callback = tx_callback; + break; + case kUart3: // their USART_DISPLAY + usartDisplayInit(); + display_rx_callback = rx_callback; + display_tx_callback = tx_callback; + break; + default: + // Error + break; } } -void BSP_UART_Init(UART_t uart) { +void BspUartInit(Uart usart) { // Not using callbacks for now - BSP_UART_Init_Internal(NULL, NULL, uart); + bspUartInitInternal(NULL, NULL, usart); } /** - * @brief Gets one line of ASCII text that was received. The '\n' and '\r' characters will not be stored (tested on Putty on Windows) + * @brief Gets one line of ASCII text that was received. The '\n' and '\r' + * characters will not be stored (tested on Putty on Windows) * @pre str should be at least 128bytes long. - * @param str : pointer to buffer to store the string. This buffer should be initialized - * before hand. + * @param str : pointer to buffer to store the string. This buffer should be + * initialized before hand. * @param usart : which usart to read from (2 or 3) * @return number of bytes that was read */ -uint32_t BSP_UART_Read(UART_t usart, char *str) { +uint32_t BspUartRead(Uart usart, char *str) { char data = 0; uint32_t recvd = 0; - bool *line_recvd = lineRecvd[usart]; - - while(*line_recvd == false){ - BSP_UART_Write(usart, "", 0); // needs to be in. Otherwise, usbLineReceived will not update + bool *line_recvd = line_recvd_global[usart]; + + while (*line_recvd == false) { + BspUartWrite( + usart, "", + 0); // needs to be in. Otherwise, usbLineReceived will not update } USART_TypeDef *usart_handle = handles[usart]; - USART_ITConfig(usart_handle, USART_IT_RXNE, RESET); - - rxfifo_t *fifo = rx_fifos[usart]; - - rxfifo_peek(fifo, &data); - while(!rxfifo_is_empty(fifo) && data != '\r') { - recvd += rxfifo_get(fifo, (char*)str++); - rxfifo_peek(fifo, &data); + USART_ITConfig(usart_handle, USART_IT_RXNE, (FunctionalState)RESET); + + RxFifo *fifo = rx_fifos[usart]; + + RxFifoPeek(fifo, &data); + while (!RxFifoIsEmpty(fifo) && data != '\r') { + recvd += RxFifoGet(fifo, (char *)str++); + RxFifoPeek(fifo, &data); } - rxfifo_get(fifo, &data); + RxFifoGet(fifo, &data); *str = 0; *line_recvd = false; - USART_ITConfig(usart_handle, USART_IT_RXNE, SET); + USART_ITConfig(usart_handle, USART_IT_RXNE, (FunctionalState)SET); return recvd; } /** - * @brief Transmits data to through UART line + * @brief Transmits data to through USART line * @param str : pointer to buffer with data to send. * @param len : size of buffer * @param usart : which usart to read from (2 or 3) * @return number of bytes that were sent - * + * * @note This function uses a fifo to buffer the write. If that * fifo is full, this function may block while waiting for * space to open up. Do not call from timing-critical * sections of code. */ -uint32_t BSP_UART_Write(UART_t usart, char *str, uint32_t len) { +uint32_t BspUartWrite(Uart usart, char *str, uint32_t len) { uint32_t sent = 0; USART_TypeDef *usart_handle = handles[usart]; - USART_ITConfig(usart_handle, USART_IT_TC, RESET); + USART_ITConfig(usart_handle, USART_IT_TC, (FunctionalState)RESET); - txfifo_t *fifo = tx_fifos[usart]; + TxFifo *fifo = tx_fifos[usart]; - while(sent < len) { - if(!txfifo_put(fifo, str[sent])) { + while (sent < len) { + if (!TxFifoPut(fifo, str[sent])) { // Allow the interrupt to fire - USART_ITConfig(usart_handle, USART_IT_TC, SET); + USART_ITConfig(usart_handle, USART_IT_TC, (FunctionalState)SET); // Wait for space to open up - while(txfifo_is_full(fifo)); + while (TxFifoIsFull(fifo)) { + ; + } // Disable the interrupt again - USART_ITConfig(usart_handle, USART_IT_TC, RESET); + USART_ITConfig(usart_handle, USART_IT_TC, (FunctionalState)RESET); } else { - sent++; + sent++; } } - USART_ITConfig(usart_handle, USART_IT_TC, SET); + USART_ITConfig(usart_handle, USART_IT_TC, (FunctionalState)SET); return sent; } -void USART2_IRQHandler(void) { +void UsarT2IrqHandler(void) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSIntEnter(); CPU_CRITICAL_EXIT(); - if(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET) { + if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET) { uint8_t data = USART2->DR; - bool removeSuccess = 1; - if(data == '\r' || data == '\n'){ - usbLineReceived = true; - if(usbRxCallback != NULL) - usbRxCallback(); + bool remove_success = 1; + if (data == '\r' || data == '\n') { + usb_line_received = true; + if (usb_rx_callback != NULL) { + usb_rx_callback(); + } } // Check if it was a backspace. // '\b' for minicmom // '\177' for putty - else if(data != '\b' && data != '\177') { - rxfifo_put(&usbRxFifo, data); + else if (data != '\b' && data != '\177') { + RxFifoPut(&usb_rx_fifo, (char)data); } // Sweet, just a "regular" key. Put it into the fifo - // Doesn't matter if it fails. If it fails, then the data gets thrown away - // and the easiest solution for this is to increase RX_SIZE + // Doesn't matter if it fails. If it fails, then the data gets thrown + // away and the easiest solution for this is to increase RX_SIZE else { - char junk; + char junk = 0; // Delete the last entry! - removeSuccess = rxfifo_popback(&usbRxFifo, &junk); + remove_success = RxFifoPopBack(&usb_rx_fifo, &junk); - USART_SendData(UART_2, 0x7F); // TODO: Not sure if the backspace works. Need to test + USART_SendData(USART2, + 0x7F); // NOLINT + // TODO: Not sure if the backspace works. + // Need to test } - if(removeSuccess) { + if (remove_success) { USART2->DR = data; } } - if(USART_GetITStatus(USART2, USART_IT_TC) != RESET) { - // If getting data from fifo fails i.e. the tx fifo is empty, then turn off the TX interrupt - if(!txfifo_get(&usbTxFifo, (char*)&(USART2->DR))) { - USART_ITConfig(USART2, USART_IT_TC, RESET); // Turn off the interrupt - if(usbTxCallback != NULL) - usbTxCallback(); // Callback + if (USART_GetITStatus(USART2, USART_IT_TC) != RESET) { + // If getting data from fifo fails i.e. the tx fifo is empty, then turn + // off the TX interrupt + if (!TxFifoGet(&usb_tx_fifo, (char *)&(USART2->DR))) { + USART_ITConfig(USART2, USART_IT_TC, + (FunctionalState)RESET); // Turn off the interrupt + if (usb_tx_callback != NULL) { + usb_tx_callback(); // Callback + } } } - if(USART_GetITStatus(USART2, USART_IT_ORE) != RESET); - + if (USART_GetITStatus(USART2, USART_IT_ORE) != RESET) {} OSIntExit(); - } -void USART3_IRQHandler(void) { +void Usart3IrqHandler(void) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); OSIntEnter(); CPU_CRITICAL_EXIT(); - if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { + if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { uint8_t data = USART3->DR; - bool removeSuccess = 1; - if(data == '\r'){ - displayLineReceived = true; - if(displayRxCallback != NULL) - displayRxCallback(); + bool remove_success = 1; + if (data == '\r') { + display_line_received = true; + if (display_rx_callback != NULL) { + display_rx_callback(); + } } // Check if it was a backspace. // '\b' for minicmom // '\177' for putty - if(data != '\b' && data != '\177') rxfifo_put(&displayRxFifo, data); - // Sweet, just a "regular" key. Put it into the fifo - // Doesn't matter if it fails. If it fails, then the data gets thrown away - // and the easiest solution for this is to increase RX_SIZE - else { - char junk; + if (data != '\b' && data != '\177') { + RxFifoPut(&display_rx_fifo, (char)data); + // Sweet, just a "regular" key. Put it into the fifo + // Doesn't matter if it fails. If it fails, then the data gets + // thrown away and the easiest solution for this is to increase + // RX_SIZE + } else { + char junk = 0; // Delete the last entry! - removeSuccess = rxfifo_popback(&displayRxFifo, &junk); + remove_success = RxFifoPopBack(&display_rx_fifo, &junk); } - if(removeSuccess) { + if (remove_success) { USART3->DR = data; } } - if(USART_GetITStatus(USART3, USART_IT_TC) != RESET) { - // If getting data from fifo fails i.e. the tx fifo is empty, then turn off the TX interrupt - if(!txfifo_get(&displayTxFifo, (char*)&(USART3->DR))) { - USART_ITConfig(USART3, USART_IT_TC, RESET); - if(displayTxCallback != NULL) - displayTxCallback(); + if (USART_GetITStatus(USART3, USART_IT_TC) != RESET) { + // If getting data from fifo fails i.e. the tx fifo is empty, then turn + // off the TX interrupt + if (!TxFifoGet(&display_tx_fifo, (char *)&(USART3->DR))) { + USART_ITConfig(USART3, USART_IT_TC, (FunctionalState)RESET); + if (display_tx_callback != NULL) { + display_tx_callback(); + } } } - if(USART_GetITStatus(USART3, USART_IT_ORE) != RESET); + if (USART_GetITStatus(USART3, USART_IT_ORE) != RESET) {} OSIntExit(); } diff --git a/BSP/STM32F413/Src/retarget.c b/BSP/STM32F413/Src/retarget.c index 305ffb46b..42c84db2b 100644 --- a/BSP/STM32F413/Src/retarget.c +++ b/BSP/STM32F413/Src/retarget.c @@ -1,35 +1,24 @@ /* Copyright (c) 2020 UT Longhorn Racing Solar */ -#include "common.h" #include "BSP_UART.h" +#include "common.h" -#define STDIN_FILENO 0 +#define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -int _write(int fd, char *buffer, unsigned int len) { - if(buffer != NULL) { - BSP_UART_Write(UART_2, buffer, len); +int _write(int fd, char *buffer, unsigned int len) { // NOLINT + if (buffer != NULL) { + BspUartWrite(kUart2, buffer, len); } - return len; + return (int)len; } -int _read(int const fd, char *buffer, unsigned const len) { - if(buffer != NULL) { - - } +int _read(int const fd, const char *buffer, unsigned const len) { // NOLINT + if (buffer != NULL) {} return 1; } -int _close(int file) -{ - return -1; -} - -int _lseek(int file, int ptr, int dir) -{ - return 0; -} - - +int _close(int file) { return -1; } // NOLINT +int _lseek(int file, int ptr, int dir) { return 0; } // NOLINT diff --git a/Drivers/Inc/CANbus.h b/Drivers/Inc/CANbus.h deleted file mode 100644 index fcc01383e..000000000 --- a/Drivers/Inc/CANbus.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file CANbus.h - * @brief - * - * @defgroup CANbus - * @addtogroup CANbus - * @{ - */ - -#ifndef CAN_H__ -#define CAN_H__ - -#include "BSP_CAN.h" - -#define CARCAN CAN_1 //convenience aliases for the CANBuses -#define MOTORCAN CAN_3 - -/** - * This enum is used to signify the ID of the message you want to send. - * It is used internally to index our lookup table (CANLUT.C) and get message-specific fields. - * For user purposes, it selects the message to send. - * - * If changing the order of this enum, make sure to mirror that change in the lookup table, or - * else the driver will not work properly. - * - * If adding new types of CAN messages, add the identifier wherever it fits in - * (the enum is sorted in ascending order on purpose), and then add an entry to the lookup table. - */ -typedef enum { - BPS_TRIP = 0x002, - BPS_CONTACTOR = 0x102, - STATE_OF_CHARGE = 0x106, - SUPPLEMENTAL_VOLTAGE = 0x10B, - MOTOR_DRIVE = 0x221, - MOTOR_POWER = 0x222, - MOTOR_RESET = 0x223, - MOTOR_STATUS = 0x241, - MC_BUS = 0x242, - VELOCITY = 0x243, - MC_PHASE_CURRENT = 0x244, - VOLTAGE_VEC = 0x245, - CURRENT_VEC = 0x246, - BACKEMF = 0x247, - TEMPERATURE = 0x24B, - ODOMETER_AMPHOURS = 0x24E, - ARRAY_CONTACTOR_STATE_CHANGE = 0x24F, - SLIP_SPEED = 0x257, - CONTROL_MODE = 0x580, - IO_STATE = 0x581, - MAX_CAN_ID -} CANId_t; - -/** - * @brief Struct to use in CAN MSG LUT - * @param idxEn Whether or not this message is part of a sequence of messages. - * @param size Size of message's data. Should be a maximum of eight (in decimal). - */ -typedef struct { - bool idxEn: 1; - unsigned int size: 7; -} CANLUT_T; - -/** - * Standard CAN packet - * @param ID CANId_t value indicating which message we are trying to send - * @param idx If message is part of a sequence of messages (for messages longer than 64 bits), this indicates the index of the message. - * This is not designed to exceed the 8bit unsigned max value. - * @param data data of the message -*/ -typedef struct { - CANId_t ID; - uint8_t idx; - uint8_t data[8]; -} CANDATA_t; - -/** - * Standard identifier for whether or not a CAN transaction is blocking or not - * (DEPRECATED) - */ -// typedef enum {CAN_BLOCKING=0, CAN_NON_BLOCKING} CAN_blocking_t; - -//Compatibility macros for deprecated enum -#define CAN_BLOCKING true -#define CAN_NON_BLOCKING false - - -/** - * @brief Initializes the CAN system for a given bus - * @param bus The bus to initialize. You can either use CAN_1, CAN_3, or the convenience macros CARCAN and MOTORCAN. CAN2 will not be supported. - * @param idWhitelist A list of CAN IDs that we want to receive. If NULL, we will receive all messages. - * @param idWhitelistSize The size of the whitelist. - * @return ERROR if bus != CAN1 or CAN3, SUCCESS otherwise - */ -ErrorStatus CANbus_Init(CAN_t bus, CANId_t* idWhitelist, uint8_t idWhitelistSize); - -/** - * @brief Transmits data onto the CANbus. Transmits up to 8 bytes at a time. If more is necessary, please use an IDX message. - * @param CanData The data to be transmitted - * @param blocking Whether or not this transmission should be a blocking send. - * @param bus The bus to transmit on. This should be either CARCAN or MOTORCAN. - * @return ERROR if data wasn't sent, otherwise it was sent. - */ -ErrorStatus CANbus_Send(CANDATA_t CanData,bool blocking, CAN_t bus); - -/** - * @brief Reads a CAN message from the CAN hardware and returns it to the provided pointers. - * @param data pointer to where to store the CAN id of the received msg - * @param blocking Whether or not this read should be a blocking read - * @param bus The bus to use. This should either be CARCAN or MOTORCAN. - * @returns ERROR if read failed, SUCCESS otherwise - */ -ErrorStatus CANbus_Read(CANDATA_t* data, bool blocking, CAN_t bus); - -#endif - - -/* @} */ diff --git a/Drivers/Inc/CanBus.h b/Drivers/Inc/CanBus.h new file mode 100644 index 000000000..49b397dfd --- /dev/null +++ b/Drivers/Inc/CanBus.h @@ -0,0 +1,121 @@ +/** + * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file CanBus.h + * @brief + * + * @defgroup CANbus + * @addtogroup CANbus + * @{ + */ + +#ifndef CAN_H +#define CAN_H + +#include "BSP_CAN.h" + +#define CARCAN kCan1 // convenience aliases for the CANBuses +#define MOTORCAN kCan3 + +/** + * This enum is used to signify the ID of the message you want to send. + * It is used internally to index our lookup table (kCanLut.C) and get + * message-specific fields. For user purposes, it selects the message to send. + * + * If changing the order of this enum, make sure to mirror that change in the + * lookup table, or else the driver will not work properly. + * + * If adding new types of CAN messages, add the identifier wherever it fits in + * (the enum is sorted in ascending order on purpose), and then add an entry to + * the lookup table. + */ +typedef enum { + kBpsTrip = 0x002, + kBpsContactor = 0x102, + kStateOfCharge = 0x106, + kSupplementalVoltage = 0x10B, + kMotorDrive = 0x221, + kMotorPower = 0x222, + kMotorReset = 0x223, + kMotorStatus = 0x241, + kMcBus = 0x242, + kVelocity = 0x243, + kMcPhaseCurrent = 0x244, + kVoltageVec = 0x245, + kCurrentVec = 0x246, + kBackEmf = 0x247, + kTemperature = 0x24B, + kOdometerAmpHours = 0x24E, + kArrayContactorStateChange = 0x24F, + kSlipSpeed = 0x257, + kControlMode = 0x580, + kIoState = 0x581, + kMaxCanId +} CanId; + +/** + * @brief Struct to use in CAN MSG LUT + * @param idxEn Whether or not this message is part of a sequence of messages. + * @param size Size of message's data. Should be a maximum of eight (in + * decimal). + */ +typedef struct { + bool idx_en : 1; + unsigned int size : 7; +} CanLut; + +/** + * Standard CAN packet + * @param ID CanId value indicating which message we are trying to send + * @param idx If message is part of a sequence of messages (for messages + * longer than 64 bits), this indicates the index of the message. This is not + * designed to exceed the 8bit unsigned max value. + * @param data data of the message + */ +typedef struct { + CanId id; + uint8_t idx; + uint8_t data[BSP_CAN_DATA_LENGTH]; +} CanData; + +// Compatibility macros for deprecated enum +#define CAN_BLOCKING true +#define CAN_NON_BLOCKING false + +/** + * @brief Initializes the CAN system for a given bus + * @param bus The bus to initialize. You can either use CAN_1, CAN_3, or the + * convenience macros CARCAN and MOTORCAN. CAN2 will not be supported. + * @param idWhitelist A list of CAN IDs that we want to receive. If NULL, we + * will receive all messages. + * @param idWhitelistSize The size of the whitelist. + * @return ERROR if bus != CAN1 or CAN3, SUCCESS otherwise + */ +ErrorStatus CanBusInit(Can bus, CanId* id_whitelist, uint8_t id_whitelist_size); + +/** + * @brief Transmits data onto the CANbus. Transmits up to 8 bytes at a time. + * If more is necessary, please use an IDX message. + * @param CanData The data to be transmitted + * @param blocking Whether or not this transmission should be a + * blocking send. + * @param bus The bus to transmit on. This should be + * either CARCAN or MOTORCAN. + * @return ERROR if data wasn't sent, otherwise it was sent. + */ +ErrorStatus CanBusSend(CanData can_data, bool blocking, Can bus); + +/** + * @brief Reads a CAN message from the CAN hardware and returns it to the + * provided pointers. + * @param data pointer to where to store the CAN id of the + * received msg + * @param blocking Whether or not this read should be a blocking read + * @param bus The bus to use. This should either be CARCAN or + * MOTORCAN. + * @returns ERROR if read failed, SUCCESS otherwise + */ +ErrorStatus CanBusRead(CanData* msg_container, bool blocking, Can bus); + +#endif + +/* @} */ diff --git a/Drivers/Inc/CANConfig.h b/Drivers/Inc/CanConfig.h similarity index 59% rename from Drivers/Inc/CANConfig.h rename to Drivers/Inc/CanConfig.h index 0035e2f37..609c45485 100644 --- a/Drivers/Inc/CANConfig.h +++ b/Drivers/Inc/CanConfig.h @@ -1,30 +1,30 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file CANConfig.h - * @brief - * + * @file CanConfig.h + * @brief + * * @defgroup CANConfig * @addtogroup CANConfig * @{ */ #ifndef CAN_CONFIG #define CAN_CONFIG -#include "CANbus.h" + +#include "CanBus.h" /** * Filter Lists for CarCAN and MotorCAN -*/ + */ #define NUM_CARCAN_FILTERS 4 #define NUM_MOTORCAN_FILTERS 7 -extern CANId_t carCANFilterList[NUM_CARCAN_FILTERS]; -extern CANId_t motorCANFilterList[NUM_MOTORCAN_FILTERS]; - +extern CanId car_can_filter_list[NUM_CARCAN_FILTERS]; +extern CanId motor_can_filter_list[NUM_MOTORCAN_FILTERS]; /** - * The lookup table containing the entries for all of our CAN messages. Located in CANLUT.c + * The lookup table containing the entries for all of our CAN messages. Located + * in kCanLut.c */ -extern const CANLUT_T CANLUT[MAX_CAN_ID]; +extern const CanLut kCanLut[kMaxCanId]; #endif - /* @} */ diff --git a/Drivers/Inc/Contactors.h b/Drivers/Inc/Contactors.h index 77cf7ec15..4d9b2aaac 100644 --- a/Drivers/Inc/Contactors.h +++ b/Drivers/Inc/Contactors.h @@ -1,63 +1,58 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Contactors.h - * @brief - * + * @brief + * * @defgroup Contactors * @addtogroup Contactors * @{ */ -#ifndef __CONTACTORS_H -#define __CONTACTORS_H +#ifndef CONTACTORS_H +#define CONTACTORS_H +#include "BSP_GPIO.h" #include "common.h" #include "config.h" -#include "BSP_GPIO.h" -#include "stm32f4xx_gpio.h" - - -#define CONTACTORS_PORT PORTC -#define ARRAY_PRECHARGE_BYPASS_PIN GPIO_Pin_10 -#define MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN GPIO_Pin_12 - -#define FOREACH_contactor(contactor) \ - contactor(ARRAY_PRECHARGE_BYPASS_CONTACTOR), \ - contactor(MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR), \ -typedef enum contactor_ENUM { - FOREACH_contactor(GENERATE_ENUM) - NUM_CONTACTORS, -}contactor_t; +#define CONTACTORS_PORT kPortC +#define ARRAY_PRECHARGE_BYPASS_PIN GPIO_Pin_10 +#define MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN GPIO_Pin_12 +#define FOREACH_CONTACTOR(contactor) \ + contactor(kArrayPrechargeBypassContactor), \ + contactor(kMotorControllerPrechargeBypassContactor), +typedef enum ContactorEnum { + FOREACH_CONTACTOR(GENERATE_ENUM) kNumContactors, +} Contactor; /** * @brief Initializes contactors to be used * in connection with the Motor and Array * @return None - */ -void Contactors_Init(); + */ +void ContactorsInit(); /** - * @brief Returns the current state of + * @brief Returns the current state of * a specified contactor * @param contactor the contactor - * (MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR/ARRAY_PRECHARGE_BYPASS_CONTACTOR) + * (kMotorControllerPrechargeBypassContactor/kArrayPrechargeBypassContactor) * @return The contactor's state (ON/OFF) - */ -bool Contactors_Get(contactor_t contactor); + */ +bool ContactorsGet(Contactor contactor); /** * @brief Sets the state of a specified contactor - * @param contactor the contactor (MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR/ARRAY_PRECHARGE_BYPASS_CONTACTOR) + * @param contactor the contactor + * (kMotorControllerPrechargeBypassContactor/kArrayPrechargeBypassContactor) * @param state the state to set (ON/OFF) (true/false) * @param blocking whether or not this should be a blocking call * @return Whether or not the contactor was successfully set */ -ErrorStatus Contactors_Set(contactor_t contactor, bool state, bool blocking); +ErrorStatus ContactorsSet(Contactor contactor, bool state, bool blocking); #endif - /* @} */ diff --git a/Drivers/Inc/Display.h b/Drivers/Inc/Display.h index b97048b26..2225f3a81 100644 --- a/Drivers/Inc/Display.h +++ b/Drivers/Inc/Display.h @@ -2,107 +2,103 @@ * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Display.h * @brief Function prototypes for the display driver. - * + * * This contains function prototypes relevant to sending/receiving messages * to/from our Nextion HMI. - * + * * @defgroup Display * @addtogroup Display * @{ */ -#ifndef __DISPLAY_H -#define __DISPLAY_H +#ifndef DISPLAY_H +#define DISPLAY_H -#include "common.h" // common headers -#include "Tasks.h" // for os and fault error locs +#include "Tasks.h" // for os and fault error locs +#include "common.h" // common headers -#define MAX_ARGS 2 // maximum # of arguments in a command packet +#define DISPLAY_CMD_MAX_ARGS 2 // maximum # of arguments in a command packet /** * Error types */ -typedef enum{ // Currently only ERR_NONE and ERR_PARSE are used - DISPLAY_ERR_NONE, - DISPLAY_ERR_PARSE, // Error parsing command struct passed to Display_Send - DISPLAY_ERR_INV_INSTR, // Invalid instruction passed to nextion (0x00) - DISPLAY_ERR_INV_COMP, // Invalid component id passed to nextion (0x02) - DISPLAY_ERR_INV_PGID, // Invalid page id passed to nextion (0x03) - DISPLAY_ERR_INV_VAR, // Invalid variable name passed to nextion (0x1A) - DISPLAY_ERR_INV_VAROP, // Invalid variable operation passed to nextion (0x1B) - DISPLAY_ERR_ASSIGN, // Assignment failure nextion (0x1C) - DISPLAY_ERR_PARAMS, // Invalid number of parameters passed to nextion (0x1E) - DISPLAY_ERR_MAX_ARGS, // Command arg list exceeded MAX_ARGS elements - DISPLAY_ERR_OTHER // Other nextion display error -} DisplayError_t; - +typedef enum { // Currently only ERR_NONE and ERR_PARSE are used + kDisplayErrNone, + kDisplayErrParse, // Error parsing command struct passed to Display_Send + kDisplayErrInvInstr, // Invalid instruction passed to nextion (0x00) + kDisplayErrInvComp, // Invalid component id passed to nextion (0x02) + kDisplayErrInvPgid, // Invalid page id passed to nextion (0x03) + kDisplayErrInvVar, // Invalid variable name passed to nextion (0x1A) + kDisplayErrInvVarop, // Invalid variable operation passed to nextion + // (0x1B) + kDisplayErrAssign, // Assignment failure nextion (0x1C) + kDisplayErrParams, // Invalid number of parameters passed to nextion + // (0x1E) + kDisplayErrMaxArgs, // Command arg list exceeded DISPLAY_CMD_MAX_ARGS + // elements + kDisplayErrOther // Other nextion display error +} DisplayError; /** - * All three pages on the HMI + * All three pages on the HMI */ -typedef enum{ - STARTUP =0, - INFO, - FAULT -} Page_t; +typedef enum { kStartup = 0, kInfo, kFault } Page; /** * Argument types */ -typedef enum{ - STR_ARG, - INT_ARG -} Arg_e; +typedef enum { kStrArg, kIntArg } Arg; /** * Packages relevant display command data */ -typedef struct{ - char* compOrCmd; - char* attr; - char* op; - uint8_t numArgs; - Arg_e argTypes[MAX_ARGS]; // TRUE for integers, FALSE for strings - union{ - char* str; - uint32_t num; - } args[MAX_ARGS]; -} DisplayCmd_t; +typedef struct { + char* comp_or_cmd; + char* attr; + char* op; + uint8_t num_args; + Arg arg_types[DISPLAY_CMD_MAX_ARGS]; // TRUE for integers, FALSE for + // strings + union { + char* str; + uint32_t num; + } args[DISPLAY_CMD_MAX_ARGS]; +} DisplayCmd; /** * @brief Sends a display message. * @returns DisplayError_t */ -DisplayError_t Display_Send(DisplayCmd_t cmd); +DisplayError DisplaySend(DisplayCmd cmd); /** * @brief Initializes the display * @returns DisplayError_t */ -DisplayError_t Display_Init(void); +DisplayError DisplayInit(void); /** * @brief Resets (reboots) the display * @returns DisplayError_t */ -DisplayError_t Display_Reset(void); +DisplayError DisplayReset(void); /** - * @brief Overwrites any processing commands and triggers the display fault screen + * @brief Overwrites any processing commands and triggers the display fault + * screen * @param faultCode the application's fault code (will be displayed in hex) * @returns DisplayError_t */ -DisplayError_t Display_Error(error_code_t faultCode); +DisplayError DisplayFault(ErrorCode fault_code); /** * @brief Overwrites any processing commands and triggers the evacuation screen * @param SOC_percent the state of charge of the battery in percent * @param supp_mv the voltage of the battery in millivolts * @returns DisplayError_t -*/ -DisplayError_t Display_Evac(uint8_t SOC_percent, uint32_t supp_mv); + */ +DisplayError DisplayEvac(uint8_t soc_percent, uint32_t supp_mv); #endif - /* @} */ diff --git a/Drivers/Inc/GPIOExpander.h b/Drivers/Inc/GPIOExpander.h deleted file mode 100644 index 5e8644c85..000000000 --- a/Drivers/Inc/GPIOExpander.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file GPIOExpander.h - * @brief - * - * @defgroup GPIOExpander - * @addtogroup GPIOExpander - * @{ - */ - -/* Deprecated */ - -#ifndef __GPIOEXPANDER_H -#define __GPIOEXPANDER_H - -#include "common.h" - -typedef struct _spi_message { - int8_t opcode; - int8_t requestedPort; - int8_t data; -} spi_message; - - -// Opcodes -#define SPI_OPCODE_R 0x41 -#define SPI_OPCODE_W 0x40 - -// Register Addresses (BANK = 0) -#define SPI_IODIRA 0x00 -#define SPI_IOPOLA 0x02 -#define SPI_GPINTENA 0x04 -#define SPI_DEFVALA 0x06 -#define SPI_INTCONA 0x08 -#define SPI_IOCONA 0x0A -#define SPI_GPPUA 0x0C -#define SPI_INTFA 0x0E -#define SPI_INTCAPA 0x10 -#define SPI_GPIOA 0x12 - -#define SPI_IODIRB 0x01 -#define SPI_IOPOLB 0x03 -#define SPI_GPINTENB 0x05 -#define SPI_DEFVALB 0x07 -#define SPI_INTCONB 0x09 -#define SPI_GPPUAB 0x0D -#define SPI_INTFAB 0x0F -#define SPI_INTCAPB 0x11 -#define SPI_GPIOB 0x13 -#define SPI_OLATB 0x15 - -#endif - -/* @} */ diff --git a/Drivers/Inc/Minions.h b/Drivers/Inc/Minions.h index 4ef240c22..4f7304962 100644 --- a/Drivers/Inc/Minions.h +++ b/Drivers/Inc/Minions.h @@ -2,10 +2,10 @@ /** * @defgroup Minions - * - * This modules allows us to use GPIO more easily + * + * This modules allows us to use GPIO more easily * for our application's purposes - * + * * @defgroup Minions * @addtogroup Minions * @{ @@ -13,58 +13,51 @@ #ifndef MINIONS_H #define MINIONS_H -#include "common.h" -#include + #include "BSP_GPIO.h" +#include "common.h" // used to index into lookup table // if changed, PINS_LOOKARR should be changed in Minions.c -#define FOREACH_PIN(PIN) \ - PIN(IGN_1), \ - PIN(IGN_2), \ - PIN(REGEN_SW), \ - PIN(FOR_SW), \ - PIN(REV_SW), \ - PIN(CRUZ_EN), \ - PIN(CRUZ_ST), \ - PIN(BRAKELIGHT), \ +#define FOREACH_PIN(PIN) \ + PIN(kIgn1), PIN(kIgn2), PIN(kRegenSw), PIN(kForSw), PIN(kRevSw), \ + PIN(kCruzEn), PIN(kCruzSt), PIN(kBrakeLight), -typedef enum MINIONPIN_ENUM { - FOREACH_PIN(GENERATE_ENUM) - NUM_PINS, -} pin_t; +typedef enum { + FOREACH_PIN(GENERATE_ENUM) kNumPins, +} Pin; typedef struct { - uint16_t pinMask; - port_t port; - direction_t direction; -} pinInfo_t; + uint16_t pin_mask; + Port port; + Direction direction; +} PinInfo; /** * @brief Initializes digital I/O - * + * */ -void Minions_Init(void); +void MinionsInit(void); /** * @brief Reads the status of a pin - * - * @param pin + * + * @param pin * @return true is high * @return false is low */ -bool Minions_Read(pin_t pin); +bool MinionsRead(Pin pin); /** * @brief Updates the status of a pin - * - * @param pin - * @param status + * + * @param pin + * @param status * @return true is fail (wrote to an input) * @return false is success (wrote to an output) */ -bool Minions_Write(pin_t pin, bool status); +bool MinionsWrite(Pin pin, bool status); -#endif +#endif /* @} */ diff --git a/Drivers/Inc/Pedals.h b/Drivers/Inc/Pedals.h index 365180e10..45232b924 100644 --- a/Drivers/Inc/Pedals.h +++ b/Drivers/Inc/Pedals.h @@ -2,44 +2,38 @@ * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Pedals.h * @brief Header file for the Pedals driver - * + * * @defgroup Pedals * @addtogroup Pedals * @{ */ -#ifndef __PEDALS_H -#define __PEDALS_H +#ifndef PEDALS_H +#define PEDALS_H #include "BSP_ADC.h" /** * @brief Stuff - * + * */ -typedef enum -{ - ACCELERATOR, - BRAKE, - NUMBER_OF_PEDALS -} pedal_t; +typedef enum { kAccelerator, kBrake, kNumberOfPedals } Pedal; /** * @brief Initialize the pedals * @param None * @return None - */ -void Pedals_Init(void); + */ +void PedalsInit(void); /** - * @brief Provides the pedal distance pressed in percetage (accelerator or brake) + * @brief Provides the pedal distance pressed in percetage (accelerator or + * brake) * @param pedal_t pedal, ACCELERATOR or BRAKE as defined in enum * @return distance the pedal has been pressed in percentage - */ -int8_t Pedals_Read(pedal_t pedal); - + */ +int8_t PedalsRead(Pedal pedal); #endif - /* @} */ diff --git a/Drivers/Src/CANConfig.c b/Drivers/Src/CANConfig.c deleted file mode 100644 index 23135d00b..000000000 --- a/Drivers/Src/CANConfig.c +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file CANConfig.c - * @brief - * - */ -#include "CANConfig.h" - -#define BYTE 1 -#define HALFWORD 2 -#define WORD 4 -#define DOUBLE 8 -#define NOIDX false -#define IDX true - -/** - * @brief Lookup table to simplify user-defined packet structs. Contains metadata fields that are always the same for every message of a given ID. - * Indexed by CANId_t values. Any changes or additions must be made in parallel with changes made to the CANID_t enum in CANbus.h - */ -const CANLUT_T CANLUT[MAX_CAN_ID] = { - [BPS_TRIP] = {NOIDX, DOUBLE}, /** BPS_TRIP **/ - [BPS_CONTACTOR] = {NOIDX, DOUBLE}, /** BPS_CONTACTOR **/ - [STATE_OF_CHARGE] = {NOIDX, DOUBLE}, /** STATE_OF_CHARGE **/ - [SUPPLEMENTAL_VOLTAGE] = {NOIDX, DOUBLE}, /** SUPPLEMENTAL_VOLTAGE **/ - [MOTOR_DRIVE] = {NOIDX, DOUBLE}, /** MOTOR_DRIVE **/ - [MOTOR_POWER] = {NOIDX, DOUBLE}, /** MOTOR_POWER **/ - [MOTOR_RESET] = {NOIDX, DOUBLE}, /** MOTOR_RESET **/ - [MOTOR_STATUS] = {NOIDX, DOUBLE}, /** MOTOR_STATUS **/ - [MC_BUS] = {NOIDX, DOUBLE}, /** MC_BUS **/ - [VELOCITY] = {NOIDX, DOUBLE}, /** VELOCITY **/ - [MC_PHASE_CURRENT] = {NOIDX, DOUBLE}, /** MC_PHASE_CURRENT **/ - [VOLTAGE_VEC] = {NOIDX, DOUBLE}, /** VOLTAGE_VEC **/ - [CURRENT_VEC] = {NOIDX, DOUBLE}, /** CURRENT_VEC **/ - [BACKEMF] = {NOIDX, DOUBLE}, /** BACKEMF **/ - [TEMPERATURE] = {NOIDX, DOUBLE}, /** TEMPERATURE **/ - [ODOMETER_AMPHOURS] = {NOIDX, DOUBLE}, /** ODOMETER_AMPHOURS **/ - [ARRAY_CONTACTOR_STATE_CHANGE] = {NOIDX, BYTE }, /** ARRAY_CONTACTOR_STATE_CHANGE **/ - [SLIP_SPEED] = {NOIDX, DOUBLE}, - [MOTOR_DRIVE] = {NOIDX, DOUBLE}, /** MOTOR_DRIVE **/ - [MOTOR_POWER] = {NOIDX, DOUBLE}, /** MOTOR_POWER **/ - [MOTOR_RESET] = {NOIDX, DOUBLE}, /** MOTOR_RESET **/ - [MOTOR_STATUS] = {NOIDX, DOUBLE}, /** MOTOR_STATUS **/ - [IO_STATE] = {NOIDX, DOUBLE}, /** IO_STATE **/ - [CONTROL_MODE] = {NOIDX, BYTE }, /** CONTROL_MODE **/ -}; - -/** - * @brief Lists of CAN IDs that we want to receive. Used to initialize the CAN filters for CarCAN and MotorCAN. -*/ - -CANId_t carCANFilterList[NUM_CARCAN_FILTERS] = { - BPS_TRIP, - BPS_CONTACTOR, // Bit 1 and 0 contain BPS HV Plus/Minus (associated Motor Controller) Contactor and BPS HV Array Contactor, respectively - STATE_OF_CHARGE, - SUPPLEMENTAL_VOLTAGE -}; - -CANId_t motorCANFilterList[NUM_MOTORCAN_FILTERS] = { - MC_BUS, - VELOCITY, - BACKEMF, - TEMPERATURE, - ODOMETER_AMPHOURS, - SLIP_SPEED, - MOTOR_STATUS -}; diff --git a/Drivers/Src/CANbus.c b/Drivers/Src/CANbus.c deleted file mode 100755 index 413a5c734..000000000 --- a/Drivers/Src/CANbus.c +++ /dev/null @@ -1,258 +0,0 @@ -/** - * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar - * @file CANbus.c - * @brief - * - */ -#include "CANbus.h" -#include "config.h" -#include "os.h" -#include "Tasks.h" -#include "CANConfig.h" - -static OS_SEM CANMail_Sem4[NUM_CAN]; // sem4 to count how many sending hardware mailboxes we have left (start at 3) -static OS_SEM CANBus_ReceiveSem4[NUM_CAN]; // sem4 to count how many msgs in our recieving queue -static OS_MUTEX CANbus_TxMutex[NUM_CAN]; // mutex to lock tx line -static OS_MUTEX CANbus_RxMutex[NUM_CAN]; // mutex to lock Rx line - -/** - * @brief this function will be passed down to the BSP layer to trigger on RX events. Increments the receive semaphore to signal message in hardware mailbox. Do not access directly outside this driver. - * @param bus The CAN bus to operate on. Should be CARCAN or MOTORCAN. - */ -void CANbus_RxHandler(CAN_t bus) -{ - OS_ERR err; - OSSemPost(&(CANBus_ReceiveSem4[bus]), OS_OPT_POST_1, &err); // increment our queue counter - assertOSError(err); -} - -/** - * @brief this function will be passed down to the BSP layer to trigger on TXend. Releases hold of the mailbox semaphore (Increments it to show mailbox available). Do not access directly outside this driver. - * @param bus The CAN bus to operate on. Should be CARCAN or MOTORCAN. - */ -void CANbus_TxHandler(CAN_t bus) -{ - OS_ERR err; - OSSemPost(&(CANMail_Sem4[bus]), OS_OPT_POST_1, &err); - assertOSError(err); -} - -//wrapper functions for the interrupt customized for each bus -void CANbus_TxHandler_1(){ - CANbus_TxHandler(CAN_1); -} - -void CANbus_RxHandler_1(){ - CANbus_RxHandler(CAN_1); -} -void CANbus_TxHandler_3(){ - CANbus_TxHandler(CAN_3); -} -void CANbus_RxHandler_3(){ - CANbus_RxHandler(CAN_3); -} - -/** - * @brief Checks each CAN ID. If an ID is not in CANLUT, set that ID to NULL - * @param wlist The whitelist containing the IDs to be checked - * @param size The size of the whitelist of IDs - * @return Returns the whitelist to be -*/ -static CANId_t* whitelist_validator(CANId_t* wlist, uint8_t size){ - for(int i = 0; i < size; i++){ - CANId_t curr = wlist[i]; - if(curr >= MAX_CAN_ID) { - wlist[i] = 0; - } else if (CANLUT[curr].size == 0 ) { - wlist[i] = 0; - } - } - return wlist; -} - -ErrorStatus CANbus_Init(CAN_t bus, CANId_t* idWhitelist, uint8_t idWhitelistSize) -{ - // initialize CAN mailbox semaphore to 3 for the 3 CAN mailboxes that we have - // initialize tx - OS_ERR err; - idWhitelist = whitelist_validator(idWhitelist, idWhitelistSize); - if(bus==CAN_1){ - BSP_CAN_Init(bus,&CANbus_RxHandler_1,&CANbus_TxHandler_1, (uint16_t*)idWhitelist, idWhitelistSize); - } else if (bus==CAN_3){ - BSP_CAN_Init(bus,&CANbus_RxHandler_3,&CANbus_TxHandler_3, (uint16_t*)idWhitelist, idWhitelistSize); - } else { - return ERROR; - } - - OSMutexCreate(&(CANbus_TxMutex[bus]), (bus == CAN_1 ? "CAN TX Lock 1":"CAN TX Lock 3"), &err); - assertOSError(err); - - OSMutexCreate(&(CANbus_RxMutex[bus]), (bus == CAN_1 ? "CAN RX Lock 1":"CAN RX Lock 3"), &err); - assertOSError(err); - - OSSemCreate(&(CANMail_Sem4[bus]), (bus == CAN_1 ? "CAN Mailbox Semaphore 1":"CAN Mailbox Semaphore 3"), 3, &err); // there's 3 hardware mailboxes on the board, so 3 software mailboxes - assertOSError(err); - - OSSemCreate(&(CANBus_ReceiveSem4[bus]), (bus == CAN_1 ? "CAN Received Msg Queue Ctr 1":"CAN Received Msg Queue Ctr 3"), 0, &err); // create a mailbox counter to hold the messages in as they come in - assertOSError(err); - - return SUCCESS; -} - -ErrorStatus CANbus_Send(CANDATA_t CanData,bool blocking, CAN_t bus) -{ - CPU_TS timestamp; - OS_ERR err; - - //error check the id - if(CanData.ID >= MAX_CAN_ID){return ERROR;} - - CANLUT_T msginfo = CANLUT[CanData.ID]; //lookup msg information in table - - if(msginfo.size == 0){return ERROR;} //if they passed in an invalid id, it will be zero - - - // make sure that Can mailbox is available - if (blocking == CAN_BLOCKING) - { - OSSemPend( - &(CANMail_Sem4[bus]), - 0, - OS_OPT_PEND_BLOCKING, - ×tamp, - &err); - } - else - { - OSSemPend( - &(CANMail_Sem4[bus]), - 0, - OS_OPT_PEND_NON_BLOCKING, - ×tamp, - &err); - - // don't crash if we are just using this in non-blocking mode and don't block - if(err == OS_ERR_PEND_WOULD_BLOCK){ - return ERROR; - } - } - if (err != OS_ERR_NONE) - { - assertOSError(err); - return ERROR; - } - - uint8_t txdata[8]; - if(msginfo.idxEn){ //first byte of txData should be the idx value - memcpy(txdata, &CanData.idx, 1); - memcpy(&(txdata[sizeof(CanData.idx)]), &CanData.data, msginfo.size); - } else { //non-idx case - memcpy(txdata, &CanData.data, msginfo.size); - } - - OSMutexPend( // ensure that tx line is available - &(CANbus_TxMutex[bus]), - 0, - OS_OPT_PEND_BLOCKING, - ×tamp, - &err); - assertOSError(err); // couldn't lock tx line - - // tx line locked - ErrorStatus retval = BSP_CAN_Write( - bus, //bus to transmit onto - CanData.ID, //ID from Data struct - txdata, //data we memcpy'd earlier - (msginfo.idxEn ? msginfo.size+sizeof(CanData.idx) : msginfo.size) //if IDX then add one to the msg size, else the msg size - ); - - OSMutexPost( // unlock the TX line - &(CANbus_TxMutex[bus]), - OS_OPT_POST_NONE, - &err); - assertOSError(err); - if(retval == ERROR){ - CANbus_TxHandler(bus); //release the mailbox by posting back to the counter semaphore - } - - return retval; -} - -ErrorStatus CANbus_Read(CANDATA_t* MsgContainer, bool blocking, CAN_t bus) -{ - CPU_TS timestamp; - OS_ERR err; - - if (blocking == CAN_BLOCKING) - { - OSSemPend( // check if the queue actually has anything - &(CANBus_ReceiveSem4[bus]), - 0, - OS_OPT_PEND_BLOCKING, - ×tamp, - &err); - } - else - { - OSSemPend( - &(CANBus_ReceiveSem4[bus]), - 0, - OS_OPT_PEND_NON_BLOCKING, - ×tamp, - &err); - - // don't crash if we are just using this in non-blocking mode and don't block - if(err == OS_ERR_PEND_WOULD_BLOCK){ - return ERROR; - } - } - if (err != OS_ERR_NONE) - { - assertOSError(err); - return ERROR; - } - - OSMutexPend( // ensure that RX line is available - &(CANbus_RxMutex[bus]), - 0, - OS_OPT_PEND_BLOCKING, - ×tamp, - &err); - assertOSError(err); - - // Actually get the message - uint32_t id; - ErrorStatus status = BSP_CAN_Read(bus, &id, MsgContainer->data); - - OSMutexPost( // unlock RX line - &(CANbus_RxMutex[bus]), - OS_OPT_POST_NONE, - &err); - assertOSError(err); - if(status == ERROR){ - return ERROR; - } - - //error check the id - MsgContainer->ID = (CANId_t) id; - if(MsgContainer->ID >= MAX_CAN_ID){ - MsgContainer = NULL; - return ERROR; - } - CANLUT_T entry = CANLUT[MsgContainer->ID]; //lookup msg information in table - if(entry.size == 0){ - MsgContainer = NULL; - return ERROR; - } //if they passed in an invalid id, it will be zero - - //search LUT for id to populate idx and trim data - if(entry.idxEn==true){ - MsgContainer->idx = MsgContainer->data[0]; - memmove( // Can't use memcpy, as memory regions overlap - MsgContainer->data, - &(MsgContainer->data[1]), - 7 // max size of data (8) - size of idx byte (1) - ); - } - return status; -} diff --git a/Drivers/Src/CanBus.c b/Drivers/Src/CanBus.c new file mode 100644 index 000000000..8fe433fa3 --- /dev/null +++ b/Drivers/Src/CanBus.c @@ -0,0 +1,240 @@ +/** + * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file CANbus.c + * @brief + * + */ + +#include "CanBus.h" + +#include "CanConfig.h" +#include "Tasks.h" +#include "config.h" +#include "os.h" + +static OS_SEM + can_mail_sem4[kNumCan]; // sem4 to count how many sending hardware + // mailboxes we have left (start at 3) +static OS_SEM can_bus_receive_sem4[kNumCan]; // sem4 to count how many msgs in + // our recieving queue +static OS_MUTEX can_bus_tx_mutex[kNumCan]; // mutex to lock tx line +static OS_MUTEX can_bus_rx_mutex[kNumCan]; // mutex to lock Rx line + +/** + * @brief this function will be passed down to the BSP layer to trigger on RX + * events. Increments the receive semaphore to signal message in hardware + * mailbox. Do not access directly outside this driver. + * @param bus The CAN bus to operate on. Should be CARCAN or MOTORCAN. + */ +void CanBusRxHandler(Can bus) { + OS_ERR err = 0; + OSSemPost(&(can_bus_receive_sem4[bus]), OS_OPT_POST_1, + &err); // increment our queue counter + ASSERT_OS_ERROR(err); +} + +/** + * @brief this function will be passed down to the BSP layer to trigger on + * TXend. Releases hold of the mailbox semaphore (Increments it to show mailbox + * available). Do not access directly outside this driver. + * @param bus The CAN bus to operate on. Should be CARCAN or MOTORCAN. + */ +void CanBusTxHandler(Can bus) { + OS_ERR err = 0; + OSSemPost(&(can_mail_sem4[bus]), OS_OPT_POST_1, &err); + ASSERT_OS_ERROR(err); +} + +// wrapper functions for the interrupt customized for each bus +void CanBusTxHandler1() { CanBusTxHandler(kCan1); } + +void CanBusRxHandler1() { CanBusRxHandler(kCan1); } +void CanBusTxHandler3() { CanBusTxHandler(kCan3); } +void CanBusRxHandler3() { CanBusRxHandler(kCan3); } + +/** + * @brief Checks each CAN ID. If an ID is not in kCanLut, set that ID to NULL + * @param wlist The whitelist containing the IDs to be checked + * @param size The size of the whitelist of IDs + * @return Returns the whitelist to be + */ +static CanId* whitelistValidator(CanId* wlist, uint8_t size) { + for (int i = 0; i < size; i++) { + CanId curr = wlist[i]; + if (curr >= kMaxCanId || kCanLut[curr].size == 0) { + wlist[i] = 0; + } + } + return wlist; +} + +ErrorStatus CanBusInit(Can bus, CanId* id_whitelist, + uint8_t id_whitelist_size) { + // initialize CAN mailbox semaphore to 3 for the 3 CAN mailboxes that we + // have initialize tx + OS_ERR err = 0; + id_whitelist = whitelistValidator(id_whitelist, id_whitelist_size); + if (bus == kCan1) { + BspCanInit(bus, &CanBusRxHandler1, &CanBusTxHandler1, + (uint16_t*)id_whitelist, id_whitelist_size); + } else if (bus == kCan3) { + BspCanInit(bus, &CanBusRxHandler3, &CanBusTxHandler3, + (uint16_t*)id_whitelist, id_whitelist_size); + } else { + return ERROR; + } + + OSMutexCreate(&(can_bus_tx_mutex[bus]), + (bus == kCan1 ? "CAN TX Lock 1" : "CAN TX Lock 3"), &err); + ASSERT_OS_ERROR(err); + + OSMutexCreate(&(can_bus_rx_mutex[bus]), + (bus == kCan1 ? "CAN RX Lock 1" : "CAN RX Lock 3"), &err); + ASSERT_OS_ERROR(err); + + OSSemCreate( + &(can_mail_sem4[bus]), + (bus == kCan1 ? "CAN Mailbox Semaphore 1" : "CAN Mailbox Semaphore 3"), + BSP_CAN_NUM_MAILBOX, &err); // there's 3 hardware mailboxes on the + // board, so 3 software mailboxes + ASSERT_OS_ERROR(err); + + OSSemCreate(&(can_bus_receive_sem4[bus]), + (bus == kCan1 ? "CAN Received Msg Queue Ctr 1" + : "CAN Received Msg Queue Ctr 3"), + 0, &err); // create a mailbox counter to hold the messages in + // as they come in + ASSERT_OS_ERROR(err); + + return SUCCESS; +} + +ErrorStatus CanBusSend(CanData can_data, bool blocking, Can bus) { + CPU_TS timestamp = 0; + OS_ERR err = 0; + + // error check the id + if (can_data.id >= kMaxCanId) { + return ERROR; + } + + CanLut msginfo = kCanLut[can_data.id]; // lookup msg information in table + + if (msginfo.size == 0) { + return ERROR; + } // if they passed in an invalid id, it will be zero + + // make sure that Can mailbox is available + if (blocking == CAN_BLOCKING) { + OSSemPend(&(can_mail_sem4[bus]), 0, OS_OPT_PEND_BLOCKING, ×tamp, + &err); + } else { + OSSemPend(&(can_mail_sem4[bus]), 0, OS_OPT_PEND_NON_BLOCKING, + ×tamp, &err); + + // don't crash if we are just using this in non-blocking mode and don't + // block + if (err == OS_ERR_PEND_WOULD_BLOCK) { + return ERROR; + } + } + if (err != OS_ERR_NONE) { + ASSERT_OS_ERROR(err); + return ERROR; + } + + uint8_t txdata[BSP_CAN_DATA_LENGTH]; + if (msginfo.idx_en) { // first byte of txData should be the idx value + memcpy(txdata, &can_data.idx, 1); + memcpy(&(txdata[sizeof(can_data.idx)]), &can_data.data, msginfo.size); + } else { // non-idx case + memcpy(txdata, &can_data.data, msginfo.size); + } + + OSMutexPend( // ensure that tx line is available + &(can_bus_tx_mutex[bus]), 0, OS_OPT_PEND_BLOCKING, ×tamp, &err); + ASSERT_OS_ERROR(err); // couldn't lock tx line + + // tx line locked + ErrorStatus retval = BspCanWrite( + bus, // bus to transmit onto + can_data.id, // ID from Data struct + txdata, // data we memcpy'd earlier + (msginfo.idx_en ? msginfo.size + sizeof(can_data.idx) + : msginfo.size) // if IDX then add one to the msg size, + // else the msg size + ); + + OSMutexPost( // unlock the TX line + &(can_bus_tx_mutex[bus]), OS_OPT_POST_NONE, &err); + ASSERT_OS_ERROR(err); + if (retval == ERROR) { + CanBusTxHandler(bus); // release the mailbox by posting back to the + // counter semaphore + } + + return retval; +} + +ErrorStatus CanBusRead(CanData* msg_container, bool blocking, Can bus) { + CPU_TS timestamp = 0; + OS_ERR err = 0; + + if (blocking == CAN_BLOCKING) { + OSSemPend( // check if the queue actually has anything + &(can_bus_receive_sem4[bus]), 0, OS_OPT_PEND_BLOCKING, ×tamp, + &err); + } else { + OSSemPend(&(can_bus_receive_sem4[bus]), 0, OS_OPT_PEND_NON_BLOCKING, + ×tamp, &err); + + // don't crash if we are just using this in non-blocking mode and don't + // block + if (err == OS_ERR_PEND_WOULD_BLOCK) { + return ERROR; + } + } + if (err != OS_ERR_NONE) { + ASSERT_OS_ERROR(err); + return ERROR; + } + + OSMutexPend( // ensure that RX line is available + &(can_bus_rx_mutex[bus]), 0, OS_OPT_PEND_BLOCKING, ×tamp, &err); + ASSERT_OS_ERROR(err); + + // Actually get the message + uint32_t id = 0; + ErrorStatus status = BspCanRead(bus, &id, msg_container->data); + + OSMutexPost( // unlock RX line + &(can_bus_rx_mutex[bus]), OS_OPT_POST_NONE, &err); + ASSERT_OS_ERROR(err); + if (status == ERROR) { + return ERROR; + } + + // error check the id + msg_container->id = (CanId)id; + if (msg_container->id >= kMaxCanId) { + msg_container = NULL; + return ERROR; + } + CanLut entry = + kCanLut[msg_container->id]; // lookup msg information in table + if (entry.size == 0) { + msg_container = NULL; + return ERROR; + } // if they passed in an invalid id, it will be zero + + // search LUT for id to populate idx and trim data + if (entry.idx_en == true) { + msg_container->idx = msg_container->data[0]; + memmove( // Can't use memcpy, as memory regions overlap + msg_container->data, &(msg_container->data[1]), + BSP_CAN_DATA_LENGTH - + 1 // max size of data (8) - size of idx byte (1) + ); + } + return status; +} diff --git a/Drivers/Src/CanConfig.c b/Drivers/Src/CanConfig.c new file mode 100644 index 000000000..06e59b4d7 --- /dev/null +++ b/Drivers/Src/CanConfig.c @@ -0,0 +1,60 @@ +/** + * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file CANConfig.c + * @brief + * + */ + +#include "CanConfig.h" + +#define BYTE 1 +#define HALFWORD 2 +#define WORD 4 +#define DOUBLE 8 +#define NOIDX false +#define IDX true + +/** + * @brief Lookup table to simplify user-defined packet structs. Contains + * metadata fields that are always the same for every message of a given ID. + * Indexed by CanId values. Any changes or additions must be made in + * parallel with changes made to the CANID_t enum in CanBus.h + */ +const CanLut kCanLut[kMaxCanId] = { + [kBpsTrip] = {NOIDX, DOUBLE}, + [kBpsContactor] = {NOIDX, DOUBLE}, + [kStateOfCharge] = {NOIDX, DOUBLE}, + [kSupplementalVoltage] = {NOIDX, DOUBLE}, + [kMotorDrive] = {NOIDX, DOUBLE}, + [kMotorPower] = {NOIDX, DOUBLE}, + [kMotorReset] = {NOIDX, DOUBLE}, + [kMotorStatus] = {NOIDX, DOUBLE}, + [kMcBus] = {NOIDX, DOUBLE}, + [kVelocity] = {NOIDX, DOUBLE}, + [kMcPhaseCurrent] = {NOIDX, DOUBLE}, + [kVoltageVec] = {NOIDX, DOUBLE}, + [kCurrentVec] = {NOIDX, DOUBLE}, + [kBackEmf] = {NOIDX, DOUBLE}, + [kTemperature] = {NOIDX, DOUBLE}, + [kOdometerAmpHours] = {NOIDX, DOUBLE}, + [kArrayContactorStateChange] = {NOIDX, BYTE}, + [kSlipSpeed] = {NOIDX, DOUBLE}, + [kIoState] = {NOIDX, DOUBLE}, + [kControlMode] = {NOIDX, BYTE}, +}; + +/** + * @brief Lists of CAN IDs that we want to receive. Used to initialize the CAN + * filters for CarCAN and MotorCAN. + */ + +CanId car_can_filter_list[NUM_CARCAN_FILTERS] = { + kBpsTrip, + kBpsContactor, // Bit 1 and 0 contain BPS HV Plus/Minus (associated Motor + // Controller) Contactor and BPS HV Array Contactor, + // respectively + kStateOfCharge, kSupplementalVoltage}; + +CanId motor_can_filter_list[NUM_MOTORCAN_FILTERS] = { + kMcBus, kVelocity, kBackEmf, kTemperature, kOdometerAmpHours, + kSlipSpeed, kMotorStatus}; diff --git a/Drivers/Src/Contactors.c b/Drivers/Src/Contactors.c index 66ec45e0f..f1dfb251d 100644 --- a/Drivers/Src/Contactors.c +++ b/Drivers/Src/Contactors.c @@ -1,31 +1,33 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Contactors.h - * @brief - * + * @brief + * */ #include "Contactors.h" -#include "stm32f4xx_gpio.h" + #include "Tasks.h" -static OS_MUTEX contactorsMutex; +static OS_MUTEX contactors_mutex; /** * @brief Helper function for setting contactors without mutex. - * Should only be called if mutex is held and struct contactor has been checked + * Should only be called if mutex is held and struct contactor has been + * checked * @param contactor the contactor - * (MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR/ARRAY_PRECHARGE_BYPASS_CONTACTOR) + * (kMotorControllerPrechargeBypassContactor/kArrayPrechargeBypassContactor) * @param state the state to set (ON/OFF) * @return None - */ -static void setContactor(contactor_t contactor, bool state) { + */ +static void setContactor(Contactor contactor, bool state) { switch (contactor) { - case ARRAY_PRECHARGE_BYPASS_CONTACTOR : - BSP_GPIO_Write_Pin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, state); + case kArrayPrechargeBypassContactor: + BspGpioWritePin(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN, state); break; - case MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR : - BSP_GPIO_Write_Pin(CONTACTORS_PORT, MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN, state); + case kMotorControllerPrechargeBypassContactor: + BspGpioWritePin(CONTACTORS_PORT, + MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN, state); break; default: break; @@ -36,40 +38,41 @@ static void setContactor(contactor_t contactor, bool state) { * @brief Initializes contactors to be used * in connection with the Motor and Array * @return None - */ -void Contactors_Init() { - BSP_GPIO_Init(CONTACTORS_PORT, - (ARRAY_PRECHARGE_BYPASS_PIN) | - (MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN), - 1); + */ +void ContactorsInit() { + BspGpioInit( + CONTACTORS_PORT, + (ARRAY_PRECHARGE_BYPASS_PIN) | (MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN), + 1); // start disabled - for (int contactor = 0; contactor < NUM_CONTACTORS; ++contactor) { + for (int contactor = 0; contactor < kNumContactors; ++contactor) { setContactor(contactor, OFF); } // initialize mutex - OS_ERR err; - OSMutexCreate(&contactorsMutex, "Contactors lock", &err); - assertOSError(err); + OS_ERR err = 0; + OSMutexCreate(&contactors_mutex, "Contactors lock", &err); + ASSERT_OS_ERROR(err); } /** - * @brief Returns the current state of + * @brief Returns the current state of * a specified contactor * @param contactor the contactor - * (MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR/ARRAY_PRECHARGE_BYPASS_CONTACTOR) + * (kMotorControllerPrechargeBypassContactor/kArrayPrechargeBypassContactor) * @return The contactor's state (ON/OFF) - */ -bool Contactors_Get(contactor_t contactor) { + */ +bool ContactorsGet(Contactor contactor) { State state = OFF; switch (contactor) { - - case ARRAY_PRECHARGE_BYPASS_CONTACTOR : - state = BSP_GPIO_Get_State(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN); + case kArrayPrechargeBypassContactor: + state = + BspGpioGetState(CONTACTORS_PORT, ARRAY_PRECHARGE_BYPASS_PIN); break; - case MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR : - state = BSP_GPIO_Get_State(CONTACTORS_PORT, MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN); + case kMotorControllerPrechargeBypassContactor: + state = BspGpioGetState(CONTACTORS_PORT, + MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN); break; default: break; @@ -80,32 +83,34 @@ bool Contactors_Get(contactor_t contactor) { /** * @brief Sets the state of a specified contactor * @param contactor the contactor - * (MOTOR_CONTROLLER_PRECHARGE_BYPASS_CONTACTOR/ARRAY_PRECHARGE_BYPASS_CONTACTOR) + * (kMotorControllerPrechargeBypassContactor/kArrayPrechargeBypassContactor) * @param state the state to set (ON/OFF) * @param blocking whether or not this should be a blocking call * @return Whether or not the contactor was successfully set */ -ErrorStatus Contactors_Set(contactor_t contactor, bool state, bool blocking) { - CPU_TS timestamp; - OS_ERR err; +ErrorStatus ContactorsSet(Contactor contactor, bool state, bool blocking) { + CPU_TS timestamp = 0; + OS_ERR err = 0; ErrorStatus result = ERROR; // acquire lock if its available - OSMutexPend(&contactorsMutex, 0, blocking ? OS_OPT_PEND_BLOCKING : OS_OPT_PEND_NON_BLOCKING, ×tamp, &err); - - if(err == OS_ERR_PEND_WOULD_BLOCK){ + OSMutexPend(&contactors_mutex, 0, + blocking ? OS_OPT_PEND_BLOCKING : OS_OPT_PEND_NON_BLOCKING, + ×tamp, &err); + + if (err == OS_ERR_PEND_WOULD_BLOCK) { return ERROR; } - assertOSError(err); + ASSERT_OS_ERROR(err); // change contactor to match state and make sure it worked setContactor(contactor, state); - bool ret = (bool)Contactors_Get(contactor); - result = (ret == state) ? SUCCESS: ERROR; + bool ret = (bool)ContactorsGet(contactor); + result = (ret == state) ? SUCCESS : ERROR; // release lock - OSMutexPost(&contactorsMutex, OS_OPT_POST_NONE, &err); - assertOSError(err); + OSMutexPost(&contactors_mutex, OS_OPT_POST_NONE, &err); + ASSERT_OS_ERROR(err); return result; } diff --git a/Drivers/Src/Display.c b/Drivers/Src/Display.c index 298ea0f25..e85f00d81 100644 --- a/Drivers/Src/Display.c +++ b/Drivers/Src/Display.c @@ -5,124 +5,133 @@ * * This contains functions relevant to sending/receiving messages * to/from our Nextion display. - * + * */ #include "Display.h" -#include "bsp.h" // for writing to UART -#include "Tasks.h" // for os and fault error codes -#define DISP_OUT UART_3 +#include "Tasks.h" // for os and fault error codes +#include "bsp.h" // for writing to UART + +#define PAGE_STR_SIZE 7 +#define FAULT_STR_SIZE 20 +#define SOC_STR_SIZE 13 +#define SUPP_STR_SIZE 18 + +#define DISP_OUT kUart3 #define MAX_MSG_LEN 32 #define MAX_ARG_LEN 16 // Assignment commands have only 1 arg, an operator, and an attribute -#define isAssignCmd(cmd) (cmd.compOrCmd != NULL && cmd.op != NULL && cmd.attr != NULL && cmd.numArgs == 1) -// Operational commands have no attribute and no operator, just a command and >= 0 arguments -#define isOpCmd(cmd) (cmd.op == NULL && cmd.attr == NULL) - -static const char *TERMINATOR = "\xff\xff\xff"; - -DisplayError_t Display_Init(){ - BSP_UART_Init(DISP_OUT); - return Display_Reset(); +#define IS_ASSIGN_CMD(cmd) \ + ((((cmd).comp_or_cmd != NULL) && ((cmd).op != NULL) && \ + ((cmd).attr != NULL) && ((cmd).num_args == 1))) +// Operational commands have no attribute and no operator, just a command and >= +// 0 arguments +#define IS_OP_CMD(cmd) ((cmd).op == NULL && (cmd).attr == NULL) + +static const char *terminator = "\xff\xff\xff"; + +DisplayError DisplayInit() { + BspUartInit(DISP_OUT); + return DisplayReset(); } -DisplayError_t Display_Send(DisplayCmd_t cmd){ - char msgArgs[MAX_MSG_LEN]; - if (isAssignCmd(cmd)){ - if (cmd.argTypes[0] == INT_ARG){ - sprintf(msgArgs, "%d", (int)cmd.args[0].num); - } - else{ - if (cmd.args[0].str == NULL){return DISPLAY_ERR_PARSE;} - sprintf(msgArgs, "%s", cmd.args[0].str); - } - - BSP_UART_Write(DISP_OUT, cmd.compOrCmd, strlen(cmd.compOrCmd)); - BSP_UART_Write(DISP_OUT, ".", 1); - BSP_UART_Write(DISP_OUT, cmd.attr, strlen(cmd.attr)); - BSP_UART_Write(DISP_OUT, cmd.op, strlen(cmd.op)); - } - else if (isOpCmd(cmd)){ - msgArgs[0] = ' '; // No args - msgArgs[1] = '\0'; - if (cmd.numArgs > MAX_ARGS){return DISPLAY_ERR_OTHER;} - if (cmd.numArgs >= 1){ // If there are arguments - for (int i = 0; i < cmd.numArgs; i++){ - char arg[MAX_ARG_LEN]; - if (cmd.argTypes[i] == INT_ARG){ - sprintf(arg, "%d", (int)cmd.args[i].num); - } - else{ - sprintf(arg, "%s", cmd.args[i].str); - } - - strcat(msgArgs, arg); - - if (i < cmd.numArgs - 1){ // delimiter - strcat(msgArgs, ","); - } - } - } - BSP_UART_Write(DISP_OUT, cmd.compOrCmd, strlen(cmd.compOrCmd)); - } - else{ // Error parsing command struct - return DISPLAY_ERR_PARSE; - } - - if (cmd.numArgs >= 1){ // If there are arguments - BSP_UART_Write(DISP_OUT, msgArgs, strlen(msgArgs)); - } - - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); - - return DISPLAY_ERR_NONE; +DisplayError DisplaySend(DisplayCmd cmd) { + char msg_args[MAX_MSG_LEN]; + if (IS_ASSIGN_CMD(cmd)) { + if (cmd.arg_types[0] == kIntArg) { + sprintf(msg_args, "%d", (int)cmd.args[0].num); + } else { + if (cmd.args[0].str == NULL) { + return kDisplayErrParse; + } + sprintf(msg_args, "%s", cmd.args[0].str); + } + + BspUartWrite(DISP_OUT, cmd.comp_or_cmd, strlen(cmd.comp_or_cmd)); + BspUartWrite(DISP_OUT, ".", 1); + BspUartWrite(DISP_OUT, cmd.attr, strlen(cmd.attr)); + BspUartWrite(DISP_OUT, cmd.op, strlen(cmd.op)); + } else if (IS_OP_CMD(cmd)) { + msg_args[0] = ' '; // No args + msg_args[1] = '\0'; + if (cmd.num_args > DISPLAY_CMD_MAX_ARGS) { + return kDisplayErrOther; + } + if (cmd.num_args >= 1) { // If there are arguments + for (int i = 0; i < cmd.num_args; i++) { + char arg[MAX_ARG_LEN]; + if (cmd.arg_types[i] == kIntArg) { + sprintf(arg, "%d", (int)cmd.args[i].num); + } else { + sprintf(arg, "%s", cmd.args[i].str); + } + + strcat(msg_args, arg); + + if (i < cmd.num_args - 1) { // delimiter + strcat(msg_args, ","); + } + } + } + BspUartWrite(DISP_OUT, cmd.comp_or_cmd, strlen(cmd.comp_or_cmd)); + } else { // Error parsing command struct + return kDisplayErrParse; + } + + if (cmd.num_args >= 1) { // If there are arguments + BspUartWrite(DISP_OUT, msg_args, strlen(msg_args)); + } + + BspUartWrite(DISP_OUT, (char *)terminator, strlen(terminator)); + + return kDisplayErrNone; } -DisplayError_t Display_Reset(){ - DisplayCmd_t restCmd = { - .compOrCmd = "rest", - .attr = NULL, - .op = NULL, - .numArgs = 0}; +DisplayError DisplayReset() { + DisplayCmd rest_cmd = { + .comp_or_cmd = "rest", .attr = NULL, .op = NULL, .num_args = 0}; - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); // Terminates any in progress command + BspUartWrite(DISP_OUT, (char *)terminator, + strlen(terminator)); // Terminates any in progress command - return Display_Send(restCmd); + return DisplaySend(rest_cmd); } -DisplayError_t Display_Error(error_code_t faultCode){ - - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); // Terminates any in progress command +DisplayError DisplayFault(ErrorCode fault_code) { + BspUartWrite(DISP_OUT, (char *)terminator, + strlen(terminator)); // Terminates any in progress command - char faultPage[7] = "page 2"; - BSP_UART_Write(DISP_OUT, faultPage, strlen(faultPage)); - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); + char fault_page[PAGE_STR_SIZE] = "page 2"; + BspUartWrite(DISP_OUT, fault_page, strlen(fault_page)); + BspUartWrite(DISP_OUT, (char *)terminator, strlen(terminator)); - char setFaultCode[20]; - sprintf(setFaultCode, "%s\"%04x\"", "faulterr.txt=", (uint16_t)faultCode); - BSP_UART_Write(DISP_OUT, setFaultCode, strlen(setFaultCode)); - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); + char set_fault_code[FAULT_STR_SIZE]; + sprintf(set_fault_code, "%s\"%04x\"", + "faulterr.txt=", (uint16_t)fault_code); + BspUartWrite(DISP_OUT, set_fault_code, strlen(set_fault_code)); + BspUartWrite(DISP_OUT, (char *)terminator, strlen(terminator)); - return DISPLAY_ERR_NONE; + return kDisplayErrNone; } -DisplayError_t Display_Evac(uint8_t SOC_percent, uint32_t supp_mv){ - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); // Terminates any in progress command +DisplayError DisplayEvac(uint8_t soc_percent, uint32_t supp_mv) { + BspUartWrite(DISP_OUT, (char *)terminator, + strlen(terminator)); // Terminates any in progress command - char evacPage[7] = "page 3"; - BSP_UART_Write(DISP_OUT, evacPage, strlen(evacPage)); - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); + char evac_page[PAGE_STR_SIZE] = "page 3"; + BspUartWrite(DISP_OUT, evac_page, strlen(evac_page)); + BspUartWrite(DISP_OUT, (char *)terminator, strlen(terminator)); - char soc[13]; - sprintf(soc, "%s%d", "soc.val=", (int)SOC_percent); - BSP_UART_Write(DISP_OUT, soc, strlen(soc)); - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); + char soc[SOC_STR_SIZE]; + sprintf(soc, "%s%d", "soc.val=", (int)soc_percent); + BspUartWrite(DISP_OUT, soc, strlen(soc)); + BspUartWrite(DISP_OUT, (char *)terminator, strlen(terminator)); - char supp[18]; - sprintf(supp, "%s%d", "supp.val=", (int)supp_mv); - BSP_UART_Write(DISP_OUT, supp, strlen(supp)); - BSP_UART_Write(DISP_OUT, (char *)TERMINATOR, strlen(TERMINATOR)); + char supp[SUPP_STR_SIZE]; + sprintf(supp, "%s%d", "supp.val=", (int)supp_mv); + BspUartWrite(DISP_OUT, supp, strlen(supp)); + BspUartWrite(DISP_OUT, (char *)terminator, strlen(terminator)); - return DISPLAY_ERR_NONE; + return kDisplayErrNone; } diff --git a/Drivers/Src/Minions.c b/Drivers/Src/Minions.c index b42857275..983f38bae 100644 --- a/Drivers/Src/Minions.c +++ b/Drivers/Src/Minions.c @@ -1,40 +1,43 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Minions.c - * @brief - * + * @brief + * */ #include "Minions.h" /* Should be in sync with enum in Minions.h */ -const pinInfo_t PININFO_LUT[NUM_PINS] = { - {GPIO_Pin_1, PORTA, INPUT}, - {GPIO_Pin_0, PORTA, INPUT}, - {GPIO_Pin_4, PORTA, INPUT}, - {GPIO_Pin_5, PORTA, INPUT}, - {GPIO_Pin_6, PORTA, INPUT}, - {GPIO_Pin_7, PORTA, INPUT}, - {GPIO_Pin_4, PORTB, INPUT}, - {GPIO_Pin_5, PORTB, OUTPUT} -}; +const PinInfo kPininfoLut[kNumPins] = { + {GPIO_Pin_1, kPortA, kInput}, {GPIO_Pin_0, kPortA, kInput}, + {GPIO_Pin_4, kPortA, kInput}, {GPIO_Pin_5, kPortA, kInput}, + {GPIO_Pin_6, kPortA, kInput}, {GPIO_Pin_7, kPortA, kInput}, + {GPIO_Pin_4, kPortB, kInput}, {GPIO_Pin_5, kPortB, kOutput}}; -void Minions_Init(void){ - for(uint8_t i = 0; i < NUM_PINS; i++){ - BSP_GPIO_Init(PININFO_LUT[i].port, PININFO_LUT[i].pinMask, PININFO_LUT[i].direction); +void MinionsInit(void) { + for (int i = 0; i < kNumPins; i++) { + BspGpioInit(kPininfoLut[i].port, kPininfoLut[i].pin_mask, + kPininfoLut[i].direction); } } -bool Minions_Read(pin_t pin){ - if((PININFO_LUT[pin].direction == INPUT)){ - return (bool) BSP_GPIO_Read_Pin(PININFO_LUT[pin].port, PININFO_LUT[pin].pinMask); - } else{ - return (bool)BSP_GPIO_Get_State(PININFO_LUT[pin].port, PININFO_LUT[pin].pinMask); +bool MinionsRead(Pin pin) { + if ((kPininfoLut[pin].direction == kInput)) { + // Ignition pins are negative logic, special-case them + if (pin == kIgn1 || pin == kIgn2) { + return !((bool)BspGpioReadPin(kPininfoLut[pin].port, + kPininfoLut[pin].pin_mask)); + } + return (bool)BspGpioReadPin(kPininfoLut[pin].port, + kPininfoLut[pin].pin_mask); } + return (bool)BspGpioGetState(kPininfoLut[pin].port, + kPininfoLut[pin].pin_mask); } -bool Minions_Write(pin_t pin, bool status){ - if(PININFO_LUT[pin].direction == OUTPUT){ - BSP_GPIO_Write_Pin(PININFO_LUT[pin].port, PININFO_LUT[pin].pinMask, status); +bool MinionsWrite(Pin pin, bool status) { + if (kPininfoLut[pin].direction == kOutput) { + BspGpioWritePin(kPininfoLut[pin].port, kPininfoLut[pin].pin_mask, + status); return true; } return false; diff --git a/Drivers/Src/Pedals.c b/Drivers/Src/Pedals.c old mode 100755 new mode 100644 index e28397fdf..770e3fa9a --- a/Drivers/Src/Pedals.c +++ b/Drivers/Src/Pedals.c @@ -1,57 +1,62 @@ /** * @copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar * @file Pedals.c - * @brief - * + * @brief + * */ #include "Pedals.h" // Constants used to tune the pedals -// Indexed using pedal_t +// Indexed using Pedal // Refine in testing -static const int16_t LowerBound[NUMBER_OF_PEDALS] = { - 400, // Accelerator lower bound - 2100, // Brake lower bound +static const int16_t kLowerBound[kNumberOfPedals] = { + 400, // Accelerator lower bound + 2100, // Brake lower bound }; -static const int16_t UpperBound[NUMBER_OF_PEDALS] = { - 900, // Accelerator upper bound - 3300, // Brake upper bound +static const int16_t kUpperBound[kNumberOfPedals] = { + 900, // Accelerator upper bound + 3300, // Brake upper bound }; /** - * @brief Initializes the brake and accelerator by using the - * BSP_ADC_Init function with parameters ACCELERATOR - * and BRAKE + * @brief Initializes the brake and accelerator by using the + * BspAdcInit function with parameters ACCELERATOR + * and BRAKE * @param None * @return None */ -void Pedals_Init(){ - BSP_ADC_Init(); -} +void PedalsInit() { BspAdcInit(); } /** - * @brief Fetches the millivoltage value of the potentiomenter as provided + * @brief Fetches the millivoltage value of the potentiomenter as provided * by the ADC channel of the requested pedal (Accelerator or Brake), - * converts it to a percentage of the total distance pressed using + * converts it to a percentage of the total distance pressed using * data from calibration testing, and returns it - * @param pedal_t, ACCELERATOR or BRAKE as defined in enum + * @param Pedal, ACCELERATOR or BRAKE as defined in enum * @return percent amount the pedal has been pressed in percentage */ -int8_t Pedals_Read(pedal_t pedal){ - if (pedal >= NUMBER_OF_PEDALS) return 0; - int16_t millivoltsPedal = (int16_t) BSP_ADC_Get_Millivoltage(pedal); +int8_t PedalsRead(Pedal pedal) { + if (pedal >= kNumberOfPedals) { + return 0; + } + int16_t millivolts_pedal = + (int16_t)BspAdcGetMillivoltage((pedal == kAccelerator) ? kCh10 : kCh11); int8_t percentage = 0; - - if (millivoltsPedal >= LowerBound[pedal]) { - percentage = (int8_t) ( (int32_t) (millivoltsPedal - LowerBound[pedal]) * 100 / - (UpperBound[pedal] - LowerBound[pedal])); + + if (millivolts_pedal >= kLowerBound[pedal]) { + percentage = (int8_t)((int32_t)(millivolts_pedal - kLowerBound[pedal]) * + 100 / (kUpperBound[pedal] - kLowerBound[pedal])); } - if (percentage > 100) return 100; - if (percentage < 0) return 0; + if (percentage > 100) { + return 100; + } + if (percentage < 0) { + return 0; + } return percentage; } diff --git a/Embedded-Sharepoint b/Embedded-Sharepoint index 7584311df..0d80b95ab 160000 --- a/Embedded-Sharepoint +++ b/Embedded-Sharepoint @@ -1 +1 @@ -Subproject commit 7584311df293c27ac40d60bcb29cb662496a792e +Subproject commit 0d80b95ab47648b09034cc27a8b755bd89a4589b diff --git a/Makefile b/Makefile index 3a5cc919e..9d7c685a1 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,20 @@ export CAR_LOOPBACK # Check if test file exists for the leader. ifneq (,$(wildcard Tests/Test_$(TEST).c)) TEST_LEADER ?= Tests/Test_$(TEST).c + FILE = $(TEST) + else TEST_LEADER ?= Apps/Src/main.c + FILE = MAIN +endif +export FILE + +#Check if unit test file exists (just to inform user if it isn't found) +#UNITTEST is solely used for echoing purposes +ifneq (,$(wildcard Tests/UnitTests/Tests/Test_$(TEST).c)) + UNITTEST ?= Tests/UnitTests/Tests/Test_$(TEST).c +else + UNITTEST ?= no test found endif LEADER = controls-leader @@ -37,6 +49,12 @@ stm32f413: $(MAKE) -C BSP -C STM32F413 -j TARGET=$(LEADER) TEST=$(TEST_LEADER) @echo "${BLUE}Compiled for leader! Jolly Good!${NC}" +unittest: + @echo "${YELLOW}Compiling unit test...${NC}" + @echo "$(UNITTEST)" + $(MAKE) -C Tests -C UnitTests -j TARGET=$(LEADER) TEST=$(TEST) + @echo "${BLUE}Compiled unit test! Jolly Good!${NC}" + flash: $(MAKE) -C BSP -C STM32F413 flash @@ -61,4 +79,19 @@ clean: rm -fR Objects rm -f *.out rm -fr Docs/doxygen - rm -fr Docs/build \ No newline at end of file + rm -fr Docs/build + +tidy: + $(MAKE) -C BSP -C STM32F413 tidy + +format: + $(MAKE) -C BSP -C STM32F413 format + +tidy-check: + $(MAKE) -C BSP -C STM32F413 tidy-check + +format-check: + $(MAKE) -C BSP -C STM32F413 format-check + +check: format-check format tidy-check + diff --git a/README.md b/README.md index 7de6b781a..c509a3776 100644 --- a/README.md +++ b/README.md @@ -83,13 +83,13 @@ make clean ### Usage -Follow our [documentation](https://utexas.sharepoint.com/:w:/s/ENGR-LonghornRacing/EUx6dS9swT1Js18ZlOrAfJIBKsM_7dLuQ818EnGZKrpbAQ?e=PyRIyh) to set up the Controls test rig, power the board with 12V, and use ```make flash``` to flash the board with your ```Objects/controls-leader.elf``` executable, either built from source using ```make leader``` or placed in the Objects folder from your intended release. +Follow our [integration documentation](https://utexas.sharepoint.com/:w:/s/ENGR-LonghornRacing/EUx6dS9swT1Js18ZlOrAfJIBKsM_7dLuQ818EnGZKrpbAQ?e=PyRIyh) to set up the Controls test rig, power the board with 12V, and use ```make flash``` to flash the board with your ```Objects/controls-leader.elf``` executable, either built from source using ```make leader``` or placed in the Objects folder from your intended release. ### Running Tests WIP: A formal test framework has yet to be defined for the Controls system. -For now, ```make leader TEST=TestName``` should build the Controls system excluding **Apps/Src/main.c** and including **Tests/Test_TestName.c**. +For now, ```make leader TEST=TestName``` should build the Controls system excluding **Apps/Src/main.c** and including **Tests/Test_TestName.c**. A macro DEBUG_TESTNAME is also defined which can be used for debug dumps and more! An example of this can be found in Test_HelloWorld. ### Debugging OpenOCD is a debugger program that is open source and compatible with the STM32F413. GDB is a debugger program that can be used to step through a program as it is being run on the board. To use, you need two terminals open, as well as a USB connection to the ST-Link programmer (as if you were going to flash the program to the board). @@ -200,4 +200,4 @@ This project is licensed under the MIT License - see [LICENSE](LICENSE) file for See the list of [contributors](https://github.com/lhr-solar/Controls/contributors) who participated in this project. -**[Back to top](#table-of-contents)** \ No newline at end of file +**[Back to top](#table-of-contents)** diff --git a/Tests/Test_HelloWorld.c b/Tests/Test_HelloWorld.c index 220bce2b3..24cbffc2c 100644 --- a/Tests/Test_HelloWorld.c +++ b/Tests/Test_HelloWorld.c @@ -3,8 +3,14 @@ #include int main(void){ - BSP_UART_Init(UART_2); - printf("Hello World\n"); + // This is an example of how to use DEBUG_ MACRO + + BspUartInit(kUart2); + #ifdef DEBUG_HELLOWORLD + printf("This print statement means that DEBUG_HELLOWORLD is defined\n"); + #else + printf("Hello World, your DEBUG_HELLOWORLD is not defined"); + #endif while(1){} diff --git a/Tests/UnitTests/Makefile b/Tests/UnitTests/Makefile new file mode 100644 index 000000000..fa621bce5 --- /dev/null +++ b/Tests/UnitTests/Makefile @@ -0,0 +1,139 @@ +# COLORS +RED=\033[0;31m +GREEN=\033[0;32m +ORANGE=\033[0;33m +BLUE=\033[0;34m +PURPLE=\033[0;35m +CYAN=\033[0;36m +LIGHTGRAY=\033[0;37m +DARKGRAY=\033[1;30m +YELLOW=\033[0;33m +NC=\033[0m # No Color + +# Build path +BUILD_DIR = ../../Objects + +###################################### +# source + +# C sources +# Need to include test, unity, real source file for the test, mock c functions minus source file for test +C_SOURCES = \ +Tests/Test_$(TEST).c \ +Unity/unity.c \ +$(filter-out $(wildcard ../../Tests/*/Src/$(TEST).c), $(wildcard ../../*/Src/$(TEST).c)) \ +$(wildcard Mocks/RTOS/os.c) \ +$(filter-out $(wildcard Mocks/*/Src/$(TEST).c), $(wildcard Mocks/*/Src/*.c)) + + + +$(foreach src,$(C_SOURCES),$(info --- $(src))) + +####################################### +# binaries +####################################### + +CC = gcc +AS = gcc -x assembler-with-cpp +CP = objcopy +SZ = size + +HEX = $(CP) -O ihex +BIN = $(CP) -O binary -S + +SF = st-flash + +####################################### +# C_INCLUDES +####################################### +C_INCLUDES := \ +-I- \ +-I../../Tests/Inc/ \ +-I../../Tests/UnitTests/Mocks/Apps/Inc \ +-I../../Tests/UnitTests/Mocks/Drivers/Inc \ +-I../../Tests/UnitTests/Mocks/BSP/Inc \ +-I../../Tests/UnitTests/Mocks/RTOS/ \ +-I../../Apps/Inc \ +-I../../Drivers/Inc \ +-I../../BSP/Inc \ +-I../../BSP/STM32F413/STM32F4xx_StdPeriph_Driver/Inc \ +-I../../CMSIS/Device/ST/STM32F4xx/Include \ +-I../../CMSIS/Include \ +-I../../Config/Inc \ +-I../../Tests/UnitTests \ +-I../../Tests/UnitTests/Unity \ +-I../../RTOS/uCOS-III-STM32F4/uCOS-III/Source/ \ +-I../../RTOS/uCOS-III-STM32F4/uCOS-III/Ports/ARM-Cortex-M4/Generic/GNU/ \ +-I../../RTOS/uCOS-III-STM32F4/uC-CPU/ \ +-I../../RTOS/uCOS-III-STM32F4/uC-CPU/ARM-Cortex-M4/GNU/ \ +-I../../RTOS/uCOS-III-STM32F4/uC-LIB/ + + +$(foreach src,$(C_INCLUDES),$(info --- $(src))) + +# C defines +C_DEFS = \ +-DSTM32F413_423xx + +CFLAGS += $(C_DEFS) + +ifeq ($(DEBUG), 1) +CFLAGS += -g3 -gdwarf-2 -DDEBUG +endif + +ifeq ($(MOTOR_LOOPBACK), 1) +CFLAGS += -DMOTOR_LOOPBACK +endif + +ifeq ($(CAR_LOOPBACK), 1) +CFLAGS += -DCAR_LOOPBACK +endif + +MOCKING=1 +CFLAGS += -DMOCKING + +FILETOTEST = $(shell echo '$(TEST)' | tr '[:lower:]' '[:upper:]') #Uses shell to make TEST file uppercase to define a macro +CFLAGS += -DTEST_$(FILETOTEST) #Defines a macro TEST_ to determine if we should use a mock or regular header file + +####################################### +# build the application +####################################### +# list of objects +OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) +vpath %.c $(sort $(dir $(C_SOURCES))) +# list of ASM program objects +OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o))) +vpath %.s $(sort $(dir $(ASM_SOURCES))) + + +## # @$(CC) $(OBJECTS) -o $@ + + +$(BUILD_DIR)/$(TEST): $(BUILD_DIR) $(C_SOURCES) + @echo "LD $(<:../../%=%)" + @$(CC) $(CFLAGS) $(C_INCLUDES) $(C_SOURCES) -o $(BUILD_DIR)/Test_$(TEST).out + @echo "SZ $(<:../../%=%)" + - ./$(BUILD_DIR)/Test_$(TEST).out + + +$(BUILD_DIR): + mkdir $@ + +####################################### +# clean up +####################################### +clean: + -rm -fR $(BUILD_DIR) + +####################################### +# flash +####################################### +#flash: +# $(SF) write $(BUILD_DIR)/$(TARGET).bin 0x8000000 +# unsure if this works or if we would ever use it +####################################### +# dependencies +####################################### +-include $(wildcard $(BUILD_DIR)/*.d) +#don't think we use any .d files? +# *** EOF *** diff --git a/Tests/UnitTests/Mocks/Apps/Inc/ReadCarCan.h b/Tests/UnitTests/Mocks/Apps/Inc/ReadCarCan.h new file mode 100644 index 000000000..e0110a0df --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Inc/ReadCarCan.h @@ -0,0 +1,15 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "ReadCarCan.h" +#ifndef TEST_READCARCAN + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(TaskReadCarCan, void*); +DECLARE_FAKE_VALUE_FUNC(bool, ChargeEnableGet); + +#endif + diff --git a/Tests/UnitTests/Mocks/Apps/Inc/ReadTritium.h b/Tests/UnitTests/Mocks/Apps/Inc/ReadTritium.h new file mode 100755 index 000000000..0a833653f --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Inc/ReadTritium.h @@ -0,0 +1,15 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "ReadTritium.h" +#ifndef TEST_READTRITIUM + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(TaskReadTritium, void*); +DECLARE_FAKE_VALUE_FUNC(float, MotorRpmGet); +DECLARE_FAKE_VALUE_FUNC(float, MotorVelocityGet); + +#endif diff --git a/Tests/UnitTests/Mocks/Apps/Inc/SendCarCan.h b/Tests/UnitTests/Mocks/Apps/Inc/SendCarCan.h new file mode 100644 index 000000000..21fa30979 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Inc/SendCarCan.h @@ -0,0 +1,15 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "SendCarCan.h" +#ifndef TEST_SENDCARCAN + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(TaskSendCarCan, void*); +DECLARE_FAKE_VOID_FUNC(SendCarCanInit); +DECLARE_FAKE_VOID_FUNC(SendCarCanPut, CanData); + +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Inc/SendTritium.h b/Tests/UnitTests/Mocks/Apps/Inc/SendTritium.h new file mode 100644 index 000000000..872f2aa5b --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Inc/SendTritium.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "SendTritium.h" +#ifndef TEST_SENDTRITIUM + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(TaskSendTritium, void*); + +// Getter functions for local variables in SendTritium.c +DECLARE_FAKE_VALUE_FUNC(bool, GetCruiseEnable); +DECLARE_FAKE_VALUE_FUNC(bool, GetCruiseSet); +DECLARE_FAKE_VALUE_FUNC(bool, GetOnePedalEnable); +DECLARE_FAKE_VALUE_FUNC(bool, GetRegenEnable); +DECLARE_FAKE_VALUE_FUNC(uint8_t, GetBrakePedalPercent); +DECLARE_FAKE_VALUE_FUNC(uint8_t, GetAccelPedalPercent); +DECLARE_FAKE_VALUE_FUNC(Gear, GetGear); +DECLARE_FAKE_VALUE_FUNC(TritiumState, GetState); +DECLARE_FAKE_VALUE_FUNC(float, GetVelocityObserved); +DECLARE_FAKE_VALUE_FUNC(float, GetCruiseVelSetpoint); +DECLARE_FAKE_VALUE_FUNC(float, GetCurrentSetpoint); +DECLARE_FAKE_VALUE_FUNC(float, GetVelocitySetpoint); + +// Setter functions for local variables in SendTritium.c +#ifdef SENDTRITIUM_EXPOSE_VARS +DECLARE_FAKE_VOID_FUNC(SetCruiseEnable, bool); +DECLARE_FAKE_VOID_FUNC(SetCruiseSet, bool); +DECLARE_FAKE_VOID_FUNC(SetOnePedalEnable, bool); +DECLARE_FAKE_VOID_FUNC(SetRegenEnable, bool); +DECLARE_FAKE_VOID_FUNC(SetBrakePedalPercent, uint8_t); +DECLARE_FAKE_VOID_FUNC(SetAccelPedalPercent, uint8_t); +DECLARE_FAKE_VOID_FUNC(SetGear, Gear); +DECLARE_FAKE_VOID_FUNC(SetState, TritiumState); +DECLARE_FAKE_VOID_FUNC(SetVelocityObserved, float); +DECLARE_FAKE_VOID_FUNC(SetCruiseVelSetpoint, float); +DECLARE_FAKE_VOID_FUNC(SetCurrentSetpoint, float); +DECLARE_FAKE_VOID_FUNC(SetVelocitySetpoint, float); +#endif + +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Inc/Tasks.h b/Tests/UnitTests/Mocks/Apps/Inc/Tasks.h new file mode 100644 index 000000000..c4f04b54b --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Inc/Tasks.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "Tasks.h" +#ifndef TEST_TASKS + +#include "fff.h" + +#ifndef TEST_MAIN +DECLARE_FAKE_VOID_FUNC(TaskInit, void *); +#else +void TaskInit(void* p_arg); +#endif + +#ifndef TEST_DEBUGDUMP +DECLARE_FAKE_VOID_FUNC(TaskDebugDump, void*); +#else +void TaskDebugDump(void *p_arg); +#endif + +#ifndef TEST_COMMANDLINE +DECLARE_FAKE_VOID_FUNC(TaskCommandLine, void*); +#else +void Task_CommandLine(void* p_arg); +#endif + +DECLARE_FAKE_VOID_FUNC(TaskSwHookInit); +DECLARE_FAKE_VOID_FUNC(EmergencyContactorOpen); +DECLARE_FAKE_VOID_FUNC(ThrowTaskError, ErrorCode, Callback, ErrorSchedulerLockOpt, ErrorRecovOpt); +DECLARE_FAKE_VOID_FUNC(AssertOsError, OS_ERR); + +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Inc/UpdateDisplay.h b/Tests/UnitTests/Mocks/Apps/Inc/UpdateDisplay.h new file mode 100644 index 000000000..f71ed0b23 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Inc/UpdateDisplay.h @@ -0,0 +1,26 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "UpdateDisplay.h" +#ifndef TEST_UPDATEDISPLAY + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(TaskUpdateDisplay, void*); + +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplayInit); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetPage, Page); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetSoc, uint8_t); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetSbpv, uint32_t); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetVelocity, uint32_t); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetAccel, uint8_t); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetArray, bool); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetMotor, bool); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetGear, TriState); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetRegenState, TriState); +DECLARE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetCruiseState, TriState); +DECLARE_FAKE_VOID_FUNC(UpdateDisplayClearQueue); + +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Src/ReadCarCan.c b/Tests/UnitTests/Mocks/Apps/Src/ReadCarCan.c new file mode 100644 index 000000000..f7e2ebad1 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Src/ReadCarCan.c @@ -0,0 +1,10 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "ReadCarCan.h" +#include "fff.h" + + +DEFINE_FAKE_VOID_FUNC(TaskReadCarCan, void*); +DEFINE_FAKE_VALUE_FUNC(bool, ChargeEnableGet); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Src/ReadTritium.c b/Tests/UnitTests/Mocks/Apps/Src/ReadTritium.c new file mode 100755 index 000000000..1c320cc01 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Src/ReadTritium.c @@ -0,0 +1,9 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "ReadTritium.h" + +DEFINE_FAKE_VOID_FUNC(TaskReadTritium, void*); +DEFINE_FAKE_VALUE_FUNC(float, MotorRpmGet); +DEFINE_FAKE_VALUE_FUNC(float, MotorVelocityGet); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Src/SendCarCan.c b/Tests/UnitTests/Mocks/Apps/Src/SendCarCan.c new file mode 100644 index 000000000..750e101c4 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Src/SendCarCan.c @@ -0,0 +1,9 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "SendCarCan.h" + +DEFINE_FAKE_VOID_FUNC(TaskSendCarCan, void*); +DEFINE_FAKE_VOID_FUNC(SendCarCanInit); +DEFINE_FAKE_VOID_FUNC(SendCarCanPut, CanData); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Src/SendTritium.c b/Tests/UnitTests/Mocks/Apps/Src/SendTritium.c new file mode 100644 index 000000000..49df5b3b3 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Src/SendTritium.c @@ -0,0 +1,34 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "SendTritium.h" + +DEFINE_FAKE_VOID_FUNC(TaskSendTritium, void*); +DEFINE_FAKE_VALUE_FUNC(bool, GetCruiseEnable); +DEFINE_FAKE_VALUE_FUNC(bool, GetCruiseSet); +DEFINE_FAKE_VALUE_FUNC(bool, GetOnePedalEnable); +DEFINE_FAKE_VALUE_FUNC(bool, GetRegenEnable); +DEFINE_FAKE_VALUE_FUNC(uint8_t, GetBrakePedalPercent); +DEFINE_FAKE_VALUE_FUNC(uint8_t, GetAccelPedalPercent); +DEFINE_FAKE_VALUE_FUNC(Gear, GetGear); +DEFINE_FAKE_VALUE_FUNC(TritiumState, GetState); +DEFINE_FAKE_VALUE_FUNC(float, GetVelocityObserved); +DEFINE_FAKE_VALUE_FUNC(float, GetCruiseVelSetpoint); +DEFINE_FAKE_VALUE_FUNC(float, GetCurrentSetpoint); +DEFINE_FAKE_VALUE_FUNC(float, GetVelocitySetpoint); + +#ifdef SENDTRITIUM_EXPOSE_VARS +DEFINE_FAKE_VOID_FUNC(SetCruiseEnable, bool); +DEFINE_FAKE_VOID_FUNC(SetCruiseSet, bool); +DEFINE_FAKE_VOID_FUNC(SetOnePedalEnable, bool); +DEFINE_FAKE_VOID_FUNC(SetRegenEnable, bool); +DEFINE_FAKE_VOID_FUNC(SetBrakePedalPercent, uint8_t); +DEFINE_FAKE_VOID_FUNC(SetAccelPedalPercent, uint8_t); +DEFINE_FAKE_VOID_FUNC(SetGear, Gear); +DEFINE_FAKE_VOID_FUNC(SetState, TritiumState); +DEFINE_FAKE_VOID_FUNC(SetVelocityObserved, float); +DEFINE_FAKE_VOID_FUNC(SetCruiseVelSetpoint, float); +DEFINE_FAKE_VOID_FUNC(SetCurrentSetpoint, float); +DEFINE_FAKE_VOID_FUNC(SetVelocitySetpoint, float); +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Src/Tasks.c b/Tests/UnitTests/Mocks/Apps/Src/Tasks.c new file mode 100644 index 000000000..cd26e7400 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Src/Tasks.c @@ -0,0 +1,30 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "Tasks.h" + +#include "ReadTritium.h" +#include "ReadCarCan.h" +#include "UpdateDisplay.h" + +ErrorCode error_read_car_can = kReadCarCanErrNone; +ErrorCode error_read_tritium = kNone; // Initialized to no error +ErrorCode error_update_display = kUpdateDisplayErrNone; + +#ifndef TEST_MAIN +DEFINE_FAKE_VOID_FUNC(TaskInit, void*); +#endif + +#ifndef TEST_DEBUGDUMP +DEFINE_FAKE_VOID_FUNC(TaskDebugDump, void*); +#endif + +#ifndef TEST_COMMANDLINE +DEFINE_FAKE_VOID_FUNC(TaskCommandLine, void*); +#endif + +DEFINE_FAKE_VOID_FUNC(TaskSwHookInit); +DEFINE_FAKE_VOID_FUNC(EmergencyContactorOpen); +DEFINE_FAKE_VOID_FUNC(ThrowTaskError, ErrorCode, Callback, ErrorSchedulerLockOpt, ErrorRecovOpt); +DEFINE_FAKE_VOID_FUNC(AssertOsError, OS_ERR); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Apps/Src/UpdateDisplay.c b/Tests/UnitTests/Mocks/Apps/Src/UpdateDisplay.c new file mode 100644 index 000000000..aa0666a68 --- /dev/null +++ b/Tests/UnitTests/Mocks/Apps/Src/UpdateDisplay.c @@ -0,0 +1,20 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "UpdateDisplay.h" + +DEFINE_FAKE_VOID_FUNC(TaskUpdateDisplay, void*); + +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplayInit); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetPage, Page); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetSoc, uint8_t); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetSbpv, uint32_t); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetVelocity, uint32_t); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetAccel, uint8_t); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetArray, bool); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetMotor, bool); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetGear, TriState); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetRegenState, TriState); +DEFINE_FAKE_VALUE_FUNC(UpdateDisplayError, UpdateDisplaySetCruiseState, TriState); +DEFINE_FAKE_VOID_FUNC(UpdateDisplayClearQueue); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Inc/BSP_ADC.h b/Tests/UnitTests/Mocks/BSP/Inc/BSP_ADC.h new file mode 100644 index 000000000..ac6cfe8d4 --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Inc/BSP_ADC.h @@ -0,0 +1,11 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "BSP_ADC.h" +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(BspAdcInit); +DECLARE_FAKE_VALUE_FUNC(int16_t, BspAdcGetValue, Adc); +DECLARE_FAKE_VALUE_FUNC(int16_t, BspAdcGetMillivoltage, Adc); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Inc/BSP_CAN.h b/Tests/UnitTests/Mocks/BSP/Inc/BSP_CAN.h new file mode 100644 index 000000000..ce53ed99e --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Inc/BSP_CAN.h @@ -0,0 +1,11 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "BSP_CAN.h" +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(BspCanInit, Can, Callback, Callback, uint16_t*, uint8_t); +//DECLARE_FAKE_VALUE_FUNC(ErrorStatus, BspCanWrite, Can, uint32_t, uint8_t, uint8_t); +DECLARE_FAKE_VALUE_FUNC(ErrorStatus, BspCanRead, Can, uint32_t*, uint8_t*); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Inc/BSP_GPIO.h b/Tests/UnitTests/Mocks/BSP/Inc/BSP_GPIO.h new file mode 100644 index 000000000..81a7c2f4b --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Inc/BSP_GPIO.h @@ -0,0 +1,14 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "BSP_GPIO.h" +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(BspGpioInit, Port, uint16_t, Direction); +DECLARE_FAKE_VALUE_FUNC(uint16_t, BspGpioRead, Port); +DECLARE_FAKE_VOID_FUNC(BspGpioWrite, Port, uint16_t); +DECLARE_FAKE_VALUE_FUNC(uint8_t, BspGpioReadPin, Port, uint16_t); +DECLARE_FAKE_VOID_FUNC(BspGpioWritePin, Port, uint16_t, bool); +DECLARE_FAKE_VALUE_FUNC(uint8_t, BspGpioGetState, Port, uint16_t); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Inc/BSP_UART.h b/Tests/UnitTests/Mocks/BSP/Inc/BSP_UART.h new file mode 100644 index 000000000..d38bd0247 --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Inc/BSP_UART.h @@ -0,0 +1,11 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "BSP_UART.h" +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(BspUartInit, Uart); +DECLARE_FAKE_VALUE_FUNC(uint32_t, BspUartRead, Uart, char*); +DECLARE_FAKE_VALUE_FUNC(uint32_t, BspUartWrite, Uart, char*, uint32_t); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Inc/stm32f4xx_gpio.h b/Tests/UnitTests/Mocks/BSP/Inc/stm32f4xx_gpio.h new file mode 100644 index 000000000..c9c066b8c --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Inc/stm32f4xx_gpio.h @@ -0,0 +1,59 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "stm32f4xx_gpio.h" +#include "fff.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/* Function used to set the GPIO configuration to the default reset state ****/ +DECLARE_FAKE_VOID_FUNC(GPIO_DeInit, GPIO_TypeDef*); + +/* Initialization and Configuration functions *********************************/ +DECLARE_FAKE_VOID_FUNC(GPIO_Init, GPIO_TypeDef*, GPIO_InitTypeDef*); + +DECLARE_FAKE_VOID_FUNC(GPIO_StructInit, GPIO_InitTypeDef*); + +DECLARE_FAKE_VOID_FUNC(GPIO_PinLockConfig, GPIO_TypeDef*, uint16_t); + +/* GPIO Read and Write functions **********************************************/ +DECLARE_FAKE_VALUE_FUNC(uint8_t, GPIO_ReadInputDataBit, GPIO_TypeDef*, uint16_t); + +DECLARE_FAKE_VALUE_FUNC(uint16_t, GPIO_ReadInputData, GPIO_TypeDef*); + +DECLARE_FAKE_VALUE_FUNC(uint8_t, GPIO_ReadOutputDataBit, GPIO_TypeDef*, uint16_t); + +DECLARE_FAKE_VALUE_FUNC(uint16_t, GPIO_ReadOutputData, GPIO_TypeDef*); + +DECLARE_FAKE_VOID_FUNC(GPIO_SetBits, GPIO_TypeDef*, uint16_t); + +DECLARE_FAKE_VOID_FUNC(GPIO_ResetBits, GPIO_TypeDef*, uint16_t); + +DECLARE_FAKE_VOID_FUNC(GPIO_WriteBit, GPIO_TypeDef*, uint16_t, BitAction); + +DECLARE_FAKE_VOID_FUNC(GPIO_Write, GPIO_TypeDef*, uint16_t); + +DECLARE_FAKE_VOID_FUNC(GPIO_ToggleBits, GPIO_TypeDef*, uint16_t); + +/* GPIO Alternate functions configuration function ****************************/ +DECLARE_FAKE_VOID_FUNC(GPIO_PinAFConfig, GPIO_TypeDef*, uint16_t, uint8_t); + +#ifdef __cplusplus +} +#endif +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/Tests/UnitTests/Mocks/BSP/Src/BSP_ADC.c b/Tests/UnitTests/Mocks/BSP/Src/BSP_ADC.c new file mode 100644 index 000000000..6646d538a --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Src/BSP_ADC.c @@ -0,0 +1,9 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "BSP_ADC.h" + +DEFINE_FAKE_VOID_FUNC(BspAdcInit); +DEFINE_FAKE_VALUE_FUNC(int16_t, BspAdcGetValue, Adc); +DEFINE_FAKE_VALUE_FUNC(int16_t, BspAdcGetMillivoltage, Adc); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Src/BSP_CAN.c b/Tests/UnitTests/Mocks/BSP/Src/BSP_CAN.c new file mode 100644 index 000000000..f84191f27 --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Src/BSP_CAN.c @@ -0,0 +1,9 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "BSP_CAN.h" + +DEFINE_FAKE_VOID_FUNC(BspCanInit, Can, Callback, Callback, uint16_t*, uint8_t); +//DEFINE_FAKE_VALUE_FUNC(ErrorStatus, BspCanWrite, Can, uint32_t, uint8_t, uint8_t); +DEFINE_FAKE_VALUE_FUNC(ErrorStatus, BspCanRead, Can, uint32_t*, uint8_t*); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Src/BSP_GPIO.c b/Tests/UnitTests/Mocks/BSP/Src/BSP_GPIO.c new file mode 100644 index 000000000..9ef95f1b3 --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Src/BSP_GPIO.c @@ -0,0 +1,12 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "BSP_GPIO.h" + +DEFINE_FAKE_VOID_FUNC(BspGpioInit, Port, uint16_t, Direction); +DEFINE_FAKE_VALUE_FUNC(uint16_t, BspGpioRead, Port); +DEFINE_FAKE_VOID_FUNC(BspGpioWrite, Port, uint16_t); +DEFINE_FAKE_VALUE_FUNC(uint8_t, BspGpioReadPin, Port, uint16_t); +DEFINE_FAKE_VOID_FUNC(BspGpioWritePin, Port, uint16_t, bool); +DEFINE_FAKE_VALUE_FUNC(uint8_t, BspGpioGetState, Port, uint16_t); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Src/BSP_UART.c b/Tests/UnitTests/Mocks/BSP/Src/BSP_UART.c new file mode 100644 index 000000000..c21c527f7 --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Src/BSP_UART.c @@ -0,0 +1,9 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "BSP_UART.h" + +DEFINE_FAKE_VOID_FUNC(BspUartInit, Uart); +DEFINE_FAKE_VALUE_FUNC(uint32_t, BspUartRead, Uart, char*); +DEFINE_FAKE_VALUE_FUNC(uint32_t, BspUartWrite, Uart, char*, uint32_t); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/BSP/Src/stm32f4xx_gpio.c b/Tests/UnitTests/Mocks/BSP/Src/stm32f4xx_gpio.c new file mode 100644 index 000000000..bb1f9afc4 --- /dev/null +++ b/Tests/UnitTests/Mocks/BSP/Src/stm32f4xx_gpio.c @@ -0,0 +1,21 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_gpio.h" + +DEFINE_FAKE_VOID_FUNC(GPIO_DeInit, GPIO_TypeDef*); +DEFINE_FAKE_VOID_FUNC(GPIO_Init, GPIO_TypeDef*, GPIO_InitTypeDef*); +DEFINE_FAKE_VOID_FUNC(GPIO_StructInit, GPIO_InitTypeDef*); +DEFINE_FAKE_VOID_FUNC(GPIO_PinLockConfig, GPIO_TypeDef*, uint16_t); +DEFINE_FAKE_VALUE_FUNC(uint8_t, GPIO_ReadInputDataBit, GPIO_TypeDef*, uint16_t); +DEFINE_FAKE_VALUE_FUNC(uint16_t, GPIO_ReadInputData, GPIO_TypeDef*); +DEFINE_FAKE_VALUE_FUNC(uint8_t, GPIO_ReadOutputDataBit, GPIO_TypeDef*, uint16_t); +DEFINE_FAKE_VALUE_FUNC(uint16_t, GPIO_ReadOutputData, GPIO_TypeDef*); +DEFINE_FAKE_VOID_FUNC(GPIO_SetBits, GPIO_TypeDef*, uint16_t); +DEFINE_FAKE_VOID_FUNC(GPIO_ResetBits, GPIO_TypeDef*, uint16_t); +DEFINE_FAKE_VOID_FUNC(GPIO_WriteBit, GPIO_TypeDef*, uint16_t, BitAction); +DEFINE_FAKE_VOID_FUNC(GPIO_Write, GPIO_TypeDef*, uint16_t); +DEFINE_FAKE_VOID_FUNC(GPIO_ToggleBits, GPIO_TypeDef*, uint16_t); +DEFINE_FAKE_VOID_FUNC(GPIO_PinAFConfig, GPIO_TypeDef*, uint16_t, uint8_t); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Drivers/Inc/CanBus.h b/Tests/UnitTests/Mocks/Drivers/Inc/CanBus.h new file mode 100644 index 000000000..1b407e76f --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Inc/CanBus.h @@ -0,0 +1,15 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "CanBus.h" +#ifndef TEST_CANBUS + +#include "fff.h" + +DECLARE_FAKE_VALUE_FUNC(ErrorStatus, CanBusInit, Can, CanId*, uint8_t); +DECLARE_FAKE_VALUE_FUNC(ErrorStatus, CanBusSend, CanData, bool, Can); +DECLARE_FAKE_VALUE_FUNC(ErrorStatus, CanBusRead, CanData*, bool, Can); + +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Drivers/Inc/Contactors.h b/Tests/UnitTests/Mocks/Drivers/Inc/Contactors.h new file mode 100644 index 000000000..fe0b975c0 --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Inc/Contactors.h @@ -0,0 +1,15 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "Contactors.h" +#ifndef TEST_CONTACTORS +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(ContactorsInit); +DECLARE_FAKE_VALUE_FUNC(bool, ContactorsGet, Contactor); +DECLARE_FAKE_VALUE_FUNC(ErrorStatus, ContactorsSet, Contactor, bool, bool); + +#endif + diff --git a/Tests/UnitTests/Mocks/Drivers/Inc/Display.h b/Tests/UnitTests/Mocks/Drivers/Inc/Display.h new file mode 100644 index 000000000..2ee86864a --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Inc/Display.h @@ -0,0 +1,17 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "Display.h" +#ifndef TEST_DISPLAY + +#include "fff.h" + +DECLARE_FAKE_VALUE_FUNC(DisplayError, DisplaySend, DisplayCmd); +DECLARE_FAKE_VALUE_FUNC(DisplayError, DisplayInit); +DECLARE_FAKE_VALUE_FUNC(DisplayError, DisplayReset); +DECLARE_FAKE_VALUE_FUNC(DisplayError, DisplayFault, ErrorCode); +DECLARE_FAKE_VALUE_FUNC(DisplayError, DisplayEvac, uint8_t, uint32_t); + +#endif diff --git a/Tests/UnitTests/Mocks/Drivers/Inc/Minions.h b/Tests/UnitTests/Mocks/Drivers/Inc/Minions.h new file mode 100644 index 000000000..4adb54bee --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Inc/Minions.h @@ -0,0 +1,14 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "Minions.h" +#ifndef TEST_MINIONS + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(MinionsInit); +DECLARE_FAKE_VALUE_FUNC(bool, MinionsRead, Pin); + +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Drivers/Inc/Pedals.h b/Tests/UnitTests/Mocks/Drivers/Inc/Pedals.h new file mode 100644 index 000000000..c274f9c4e --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Inc/Pedals.h @@ -0,0 +1,14 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once +#include_next "Pedals.h" +#ifndef TEST_PEDALS + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(PedalsInit); +DECLARE_FAKE_VALUE_FUNC(int8_t, PedalsRead, Pedal); + +#endif diff --git a/Tests/UnitTests/Mocks/Drivers/Src/CanBus.c b/Tests/UnitTests/Mocks/Drivers/Src/CanBus.c new file mode 100644 index 000000000..147d5ef51 --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Src/CanBus.c @@ -0,0 +1,9 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "CanBus.h" + +DEFINE_FAKE_VALUE_FUNC(ErrorStatus, CanBusInit, Can, CanId*, uint8_t); +DEFINE_FAKE_VALUE_FUNC(ErrorStatus, CanBusSend, CanData, bool, Can); +DEFINE_FAKE_VALUE_FUNC(ErrorStatus, CanBusRead, CanData*, bool, Can); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Drivers/Src/Contactors.c b/Tests/UnitTests/Mocks/Drivers/Src/Contactors.c new file mode 100644 index 000000000..aedae3ee6 --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Src/Contactors.c @@ -0,0 +1,9 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "Contactors.h" + +DEFINE_FAKE_VOID_FUNC(ContactorsInit); +DEFINE_FAKE_VALUE_FUNC(bool, ContactorsGet, Contactor); +DEFINE_FAKE_VALUE_FUNC(ErrorStatus, ContactorsSet, Contactor, bool, bool); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Drivers/Src/Display.c b/Tests/UnitTests/Mocks/Drivers/Src/Display.c new file mode 100644 index 000000000..98ca0cb9b --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Src/Display.c @@ -0,0 +1,11 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "Display.h" + +DEFINE_FAKE_VALUE_FUNC(DisplayError, DisplaySend, DisplayCmd); +DEFINE_FAKE_VALUE_FUNC(DisplayError, DisplayInit); +DEFINE_FAKE_VALUE_FUNC(DisplayError, DisplayReset); +DEFINE_FAKE_VALUE_FUNC(DisplayError, DisplayFault, ErrorCode); +DEFINE_FAKE_VALUE_FUNC(DisplayError, DisplayEvac, uint8_t, uint32_t); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/Drivers/Src/Minions.c b/Tests/UnitTests/Mocks/Drivers/Src/Minions.c new file mode 100644 index 000000000..d2e4138f0 --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Src/Minions.c @@ -0,0 +1,8 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "Minions.h" + +DEFINE_FAKE_VOID_FUNC(MinionsInit); +DEFINE_FAKE_VALUE_FUNC(bool, MinionsRead, Pin); diff --git a/Tests/UnitTests/Mocks/Drivers/Src/Pedals.c b/Tests/UnitTests/Mocks/Drivers/Src/Pedals.c new file mode 100755 index 000000000..65c7b2f03 --- /dev/null +++ b/Tests/UnitTests/Mocks/Drivers/Src/Pedals.c @@ -0,0 +1,8 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "Pedals.h" + +DEFINE_FAKE_VOID_FUNC(PedalsInit); +DEFINE_FAKE_VALUE_FUNC(int8_t, PedalsRead, Pedal); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/RTOS/cpu_core.c b/Tests/UnitTests/Mocks/RTOS/cpu_core.c new file mode 100644 index 000000000..31845f3ee --- /dev/null +++ b/Tests/UnitTests/Mocks/RTOS/cpu_core.c @@ -0,0 +1,8 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "cpu_core.h" +#include "fff.h" + +DEFINE_FAKE_VOID_FUNC(CPU_Init); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/RTOS/cpu_core.h b/Tests/UnitTests/Mocks/RTOS/cpu_core.h new file mode 100644 index 000000000..f2904b17d --- /dev/null +++ b/Tests/UnitTests/Mocks/RTOS/cpu_core.h @@ -0,0 +1,11 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// +#pragma once +#include_next "cpu_core.h" +#include +#include + +#include "fff.h" + +DECLARE_FAKE_VOID_FUNC(CPU_Init); diff --git a/Tests/UnitTests/Mocks/RTOS/os.c b/Tests/UnitTests/Mocks/RTOS/os.c new file mode 100644 index 000000000..ebd9a9750 --- /dev/null +++ b/Tests/UnitTests/Mocks/RTOS/os.c @@ -0,0 +1,191 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#include "fff.h" +#include "os.h" + + +/****** Event Flags *******/ + +DEFINE_FAKE_VOID_FUNC(OSFlagCreate, OS_FLAG_GRP*, CPU_CHAR*, OS_FLAGS, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSFlagDel, OS_FLAG_GRP*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_FLAGS, OSFlagPend, OS_FLAG_GRP*, OS_FLAGS, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSFlagPendAbort, OS_FLAG_GRP*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_FLAGS, OSFlagPendGetFlagsRdy, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_FLAGS, OSFlagPost, OS_FLAG_GRP*, OS_FLAGS, OS_OPT, OS_ERR*); + +/****** FIXED SIZE MEMORY BLOCK MANAGEMENT ******/ + +DEFINE_FAKE_VOID_FUNC(OSMemCreate, OS_MEM*, CPU_CHAR*, void*, OS_MEM_QTY, OS_MEM_SIZE, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(void*, OSMemGet, OS_MEM*, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSMemPut, OS_MEM*, void*, OS_ERR*); + +/****** MUTUAL EXCLUSION SEMAPHORES ******/ + +DEFINE_FAKE_VOID_FUNC(OSMutexCreate, OS_MUTEX*, char* , OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSMutexDel, OS_MUTEX*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSMutexPend, OS_MUTEX*, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSMutexPendAbort, OS_MUTEX*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSMutexPost, OS_MUTEX*, OS_OPT, OS_ERR*); + +/****** MULTI PEND ******/ + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSPendMulti, OS_PEND_DATA*, OS_OBJ_QTY, OS_TICK, OS_OPT, OS_ERR*); + +/****** MESSAGE QUEUES ******/ + +DEFINE_FAKE_VOID_FUNC(OSQCreate, OS_Q*, CPU_CHAR*, OS_MSG_QTY, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSQDel, OS_Q*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_MSG_QTY, OSQFlush, OS_Q*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(void*, OSQPend, OS_Q*, OS_TICK, OS_OPT, OS_MSG_SIZE*, CPU_TS*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSQPendAbort, OS_Q*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSQPost, OS_Q*, void*, OS_MSG_SIZE, OS_OPT, OS_ERR*); + +/****** SEMAPHORES ******/ + +DEFINE_FAKE_VOID_FUNC(OSSemCreate, OS_SEM*, CPU_CHAR*, OS_SEM_CTR, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSSemDel, OS_SEM*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSSemPend, OS_SEM*, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSSemPendAbort, OS_SEM*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSSemPost, OS_SEM*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSSemSet, OS_SEM*, OS_SEM_CTR, OS_ERR*); + +/****** TASK MANAGEMENT ******/ + +DEFINE_FAKE_VOID_FUNC(OSTaskChangePrio, OS_TCB*, OS_PRIO, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskCreate, OS_TCB*, CPU_CHAR*, OS_TASK_PTR, void*, OS_PRIO, CPU_STK*, CPU_STK_SIZE, CPU_STK_SIZE, OS_MSG_QTY, OS_TICK, void*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskDel, OS_TCB*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_MSG_QTY, OSTaskQFlush, OS_TCB*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(void*, OSTaskQPend, OS_TICK, OS_OPT, OS_MSG_SIZE*, CPU_TS*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTaskQPendAbort, OS_TCB*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskQPost, OS_TCB*, void*, OS_MSG_SIZE, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_REG, OSTaskRegGet, OS_TCB*, OS_REG_ID, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_REG_ID, OSTaskRegGetID, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskRegSet, OS_TCB*, OS_REG_ID, OS_REG, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskResume, OS_TCB*, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskSuspend, OS_TCB*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSTaskSemPend, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTaskSemPendAbort, OS_TCB*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSTaskSemPost, OS_TCB*, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSTaskSemSet, OS_TCB*, OS_SEM_CTR, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskStkChk, OS_TCB*, CPU_STK_SIZE*, CPU_STK_SIZE*, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTaskTimeQuantaSet, OS_TCB*, OS_TICK, OS_ERR*); + +/****** TASK LOCAL STORAGE (TLS) SUPPORT *******/ + +// Not currently used + +/****** TIME MANAGEMENT ******/ + +DEFINE_FAKE_VOID_FUNC(OSTimeDly, OS_TICK, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTimeDlyHMSM, CPU_INT16U, CPU_INT16U, CPU_INT16U, CPU_INT32U, OS_OPT, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTimeDlyResume, OS_TCB*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_TICK, OSTimeGet, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTimeSet, OS_TICK, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSTimeTick); + +/****** TIMER MANAGEMENT ******/ + +DEFINE_FAKE_VOID_FUNC(OSTmrCreate, OS_TMR*, CPU_CHAR*, OS_TICK, OS_TICK, OS_OPT, OS_TMR_CALLBACK_PTR, void*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTmrDel, OS_TMR*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_TICK, OSTmrRemainGet, OS_TMR*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTmrStart, OS_TMR*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(OS_STATE, OSTmrStateGet, OS_TMR*, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTmrStop, OS_TMR*, OS_OPT, void*, OS_ERR*); + +/****** MISCELLANEOUS ******/ + +DEFINE_FAKE_VOID_FUNC(OSInit, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSIntEnter); + +DEFINE_FAKE_VOID_FUNC(OSIntExit); + +DEFINE_FAKE_VOID_FUNC(OSSafetyCriticalStart); + +DEFINE_FAKE_VOID_FUNC(OSSchedRoundRobinCfg, CPU_BOOLEAN, OS_TICK, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSSchedRoundRobinYield, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSSched); + +DEFINE_FAKE_VOID_FUNC(OSSchedLock, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSSchedUnlock, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSStart, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSStatReset, OS_ERR*); + +DEFINE_FAKE_VOID_FUNC(OSStatTaskCPUUsageInit, OS_ERR*); + +DEFINE_FAKE_VALUE_FUNC(CPU_INT16U, OSVersion, OS_ERR*); + +/****** T A R G E T S P E C I F I C F U N C T I O N S ******/ + +DEFINE_FAKE_VOID_FUNC(OSInitHook); + +DEFINE_FAKE_VOID_FUNC(OSTaskCreateHook, OS_TCB*); + +DEFINE_FAKE_VOID_FUNC(OSTaskDelHook, OS_TCB*); + +DEFINE_FAKE_VOID_FUNC(OSIdleTaskHook); + +DEFINE_FAKE_VOID_FUNC(OSTaskReturnHook, OS_TCB*); + +DEFINE_FAKE_VOID_FUNC(OSStatTaskHook); + +DEFINE_FAKE_VALUE_FUNC(CPU_STK*, OSTaskStkInit, OS_TASK_PTR, void*, CPU_STK*, CPU_STK*, CPU_STK_SIZE, OS_OPT); + +DEFINE_FAKE_VOID_FUNC(OSTaskSwHook); + +DEFINE_FAKE_VOID_FUNC(OSTimeTickHook); \ No newline at end of file diff --git a/Tests/UnitTests/Mocks/RTOS/os.h b/Tests/UnitTests/Mocks/RTOS/os.h new file mode 100644 index 000000000..1b7906aef --- /dev/null +++ b/Tests/UnitTests/Mocks/RTOS/os.h @@ -0,0 +1,215 @@ +///////////////////////////////////////////// +////// MOCK ////// +///////////////////////////////////////////// + +#pragma once + +/* +************************************************************************************************************************ +* uC/OS-III VERSION NUMBER +************************************************************************************************************************ +*/ + +#define OS_VERSION 30405u /* Version of uC/OS-III (Vx.yy.zz mult. by 10000) */ + +/* + +/* +************************************************************************************************************************ +* INCLUDE HEADER FILES +************************************************************************************************************************ +*/ +#include "fff.h" +#include_next "os.h" +#include +#include +#include +#include "os_type.h" +#include +#if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN == DEF_ENABLED)) +#include +#endif + +/****** EVENT FLAGS *******/ + +DECLARE_FAKE_VOID_FUNC(OSFlagCreate, OS_FLAG_GRP*, CPU_CHAR*, OS_FLAGS, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSFlagDel, OS_FLAG_GRP*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_FLAGS, OSFlagPend, OS_FLAG_GRP*, OS_FLAGS, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSFlagPendAbort, OS_FLAG_GRP*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_FLAGS, OSFlagPendGetFlagsRdy, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_FLAGS, OSFlagPost, OS_FLAG_GRP*, OS_FLAGS, OS_OPT, OS_ERR*); + +/****** FIXED SIZE MEMORY BLOCK MANAGEMENT ******/ + +DECLARE_FAKE_VOID_FUNC(OSMemCreate, OS_MEM*, CPU_CHAR*, void*, OS_MEM_QTY, OS_MEM_SIZE, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(void*, OSMemGet, OS_MEM*, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSMemPut, OS_MEM*, void*, OS_ERR*); + +/****** MUTUAL EXCLUSION SEMAPHORES ******/ + +DECLARE_FAKE_VOID_FUNC(OSMutexCreate, OS_MUTEX*, char* , OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSMutexDel, OS_MUTEX*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSMutexPend, OS_MUTEX*, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSMutexPendAbort, OS_MUTEX*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSMutexPost, OS_MUTEX*, OS_OPT, OS_ERR*); + +/****** MULTI PEND ******/ + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSPendMulti, OS_PEND_DATA*, OS_OBJ_QTY, OS_TICK, OS_OPT, OS_ERR*); + +/****** MESSAGE QUEUES ******/ + +DECLARE_FAKE_VOID_FUNC(OSQCreate, OS_Q*, CPU_CHAR*, OS_MSG_QTY, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSQDel, OS_Q*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_MSG_QTY, OSQFlush, OS_Q*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(void*, OSQPend, OS_Q*, OS_TICK, OS_OPT, OS_MSG_SIZE*, CPU_TS*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSQPendAbort, OS_Q*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSQPost, OS_Q*, void*, OS_MSG_SIZE, OS_OPT, OS_ERR*); + +/****** SEMAPHORES ******/ + +DECLARE_FAKE_VOID_FUNC(OSSemCreate, OS_SEM*, CPU_CHAR*, OS_SEM_CTR, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSSemDel, OS_SEM*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSSemPend, OS_SEM*, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_OBJ_QTY, OSSemPendAbort, OS_SEM*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSSemPost, OS_SEM*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSSemSet, OS_SEM*, OS_SEM_CTR, OS_ERR*); + +/****** TASK MANAGEMENT ******/ + +DECLARE_FAKE_VOID_FUNC(OSTaskChangePrio, OS_TCB*, OS_PRIO, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskCreate, OS_TCB*, CPU_CHAR*, OS_TASK_PTR, void*, OS_PRIO, CPU_STK*, CPU_STK_SIZE, CPU_STK_SIZE, OS_MSG_QTY, OS_TICK, void*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskDel, OS_TCB*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_MSG_QTY, OSTaskQFlush, OS_TCB*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(void*, OSTaskQPend, OS_TICK, OS_OPT, OS_MSG_SIZE*, CPU_TS*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTaskQPendAbort, OS_TCB*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskQPost, OS_TCB*, void*, OS_MSG_SIZE, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_REG, OSTaskRegGet, OS_TCB*, OS_REG_ID, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_REG_ID, OSTaskRegGetID, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskRegSet, OS_TCB*, OS_REG_ID, OS_REG, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskResume, OS_TCB*, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskSuspend, OS_TCB*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSTaskSemPend, OS_TICK, OS_OPT, CPU_TS*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTaskSemPendAbort, OS_TCB*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSTaskSemPost, OS_TCB*, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_SEM_CTR, OSTaskSemSet, OS_TCB*, OS_SEM_CTR, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskStkChk, OS_TCB*, CPU_STK_SIZE*, CPU_STK_SIZE*, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTaskTimeQuantaSet, OS_TCB*, OS_TICK, OS_ERR*); + +/****** TASK LOCAL STORAGE (TLS) SUPPORT *******/ + +// Not currently used + +/****** TIME MANAGEMENT ******/ + +DECLARE_FAKE_VOID_FUNC(OSTimeDly, OS_TICK, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTimeDlyHMSM, CPU_INT16U, CPU_INT16U, CPU_INT16U, CPU_INT32U, OS_OPT, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTimeDlyResume, OS_TCB*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_TICK, OSTimeGet, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTimeSet, OS_TICK, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSTimeTick); + +/****** TIMER MANAGEMENT ******/ + +DECLARE_FAKE_VOID_FUNC(OSTmrCreate, OS_TMR*, CPU_CHAR*, OS_TICK, OS_TICK, OS_OPT, OS_TMR_CALLBACK_PTR, void*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTmrDel, OS_TMR*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_TICK, OSTmrRemainGet, OS_TMR*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTmrStart, OS_TMR*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(OS_STATE, OSTmrStateGet, OS_TMR*, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(CPU_BOOLEAN, OSTmrStop, OS_TMR*, OS_OPT, void*, OS_ERR*); + +/****** MISCELLANEOUS ******/ + +DECLARE_FAKE_VOID_FUNC(OSInit, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSIntEnter); + +DECLARE_FAKE_VOID_FUNC(OSIntExit); + +DECLARE_FAKE_VOID_FUNC(OSSafetyCriticalStart); + +DECLARE_FAKE_VOID_FUNC(OSSchedRoundRobinCfg, CPU_BOOLEAN, OS_TICK, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSSchedRoundRobinYield, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSSched); + +DECLARE_FAKE_VOID_FUNC(OSSchedLock, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSSchedUnlock, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSStart, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSStatReset, OS_ERR*); + +DECLARE_FAKE_VOID_FUNC(OSStatTaskCPUUsageInit, OS_ERR*); + +DECLARE_FAKE_VALUE_FUNC(CPU_INT16U, OSVersion, OS_ERR*); + +/****** T A R G E T S P E C I F I C F U N C T I O N S ******/ + +DECLARE_FAKE_VOID_FUNC(OSInitHook); + +DECLARE_FAKE_VOID_FUNC(OSTaskCreateHook, OS_TCB*); + +DECLARE_FAKE_VOID_FUNC(OSTaskDelHook, OS_TCB*); + +DECLARE_FAKE_VOID_FUNC(OSIdleTaskHook); + +DECLARE_FAKE_VOID_FUNC(OSTaskReturnHook, OS_TCB*); + +DECLARE_FAKE_VOID_FUNC(OSStatTaskHook); + +DECLARE_FAKE_VALUE_FUNC(CPU_STK*, OSTaskStkInit, OS_TASK_PTR, void*, CPU_STK*, CPU_STK*, CPU_STK_SIZE, OS_OPT); + +DECLARE_FAKE_VOID_FUNC(OSTaskSwHook); + +DECLARE_FAKE_VOID_FUNC(OSTimeTickHook); diff --git a/Tests/UnitTests/Tests/Test_Contactors.c b/Tests/UnitTests/Tests/Test_Contactors.c new file mode 100644 index 000000000..3e6d079fa --- /dev/null +++ b/Tests/UnitTests/Tests/Test_Contactors.c @@ -0,0 +1,159 @@ +/** + * @copyright Copyright (c) 2018-2024 UT Longhorn Racing Solar + * @file Test_Contactors.c + * @brief An annotated example unit test written for the driver Contactors.c + * Thing tested: Contactors functions + * Mocks used: BSP, OS (though all things not tested are still mocked) + */ + +#include "unity.h" // Contains assertions for testing +#include "Contactors.h" // Header of the source file to test +#include "os.h" + +// Global variables for FFF; must be included once per unit-test file +DEFINE_FFF_GLOBALS; + +// Defines for the test +#define BOOL_STATES 2 + + +// Special function required by Unity that will run before each test +void setUp(void){ + // Left blank because we don't need it +} + + +// Another required function from Unity that will run after each test +void tearDown(void){ + // Reset the fakes' call and argument history between tests + // This is important if you'll be using this functions in multiple tests + // In our case we don't need them since we don't use functions between tests, + // but this is what you would do: + RESET_FAKE(BspGpioWritePin) + RESET_FAKE(BspGpioInit) + RESET_FAKE(BspGpioGetState) + RESET_FAKE(OSMutexPend) + RESET_FAKE(OSMutexPost) +} + + +// **** Helper functions **** // +static uint32_t count_instances_int(int match, int* array, uint32_t numElems) { + uint32_t num = 0; + for (uint16_t i = 0; i < numElems; i++) { + if (array[i] == match) { + num++; + } + } + return num; +} + +static uint32_t count_instances_uint16(uint16_t match, uint16_t* array, uint32_t numElems) { + uint32_t num = 0; + for (uint16_t i = 0; i < numElems; i++) { + if (array[i] == match) { + num++; + } + } + return num; +} + + +static uint32_t count_instances_bool(bool match, bool* array, uint32_t numElems) { + uint32_t num = 0; + for (uint16_t i = 0; i < numElems; i++) { + if (array[i] == match) { + num++; + } + } + return num; +} + + + +// **** Tests ****// + +void test_ContactorsInit(){ + ContactorsInit(); + // Check that BspGpioInit was called to initialize + // Contactors port for Array and Motor Precharge pins to be outputs + TEST_ASSERT_EQUAL(1, BspGpioInit_fake.call_count); // Should have called BspGpioInit once + TEST_ASSERT_EQUAL(CONTACTORS_PORT, BspGpioInit_fake.arg0_val); // First argument to BspGpioInit should be CONTACTORS_PORT + TEST_ASSERT_EQUAL((ARRAY_PRECHARGE_BYPASS_PIN | MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN), BspGpioInit_fake.arg1_val); + TEST_ASSERT_EQUAL (1, BspGpioInit_fake.arg2_val); + + // Check that all pins were set to OFF + // Don't worry about order as long both pins show up in the last two call arguments + TEST_ASSERT_EQUAL(BspGpioWritePin_fake.call_count, kNumContactors); + TEST_ASSERT_EQUAL(kNumContactors, count_instances_int(CONTACTORS_PORT, (int *)BspGpioWritePin_fake.arg0_history, kNumContactors)); + TEST_ASSERT_EQUAL(1, count_instances_uint16(ARRAY_PRECHARGE_BYPASS_PIN, BspGpioWritePin_fake.arg1_history, kNumContactors)); + TEST_ASSERT_EQUAL(1, count_instances_uint16(MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN, BspGpioWritePin_fake.arg1_history, kNumContactors)); + TEST_ASSERT_EQUAL(2, count_instances_bool(OFF, (bool *)BspGpioWritePin_fake.arg2_history, kNumContactors)); +} + +void test_ContactorsGet(){ + // Make sure ContactorsGet returns the right thing + BspGpioGetState_fake.return_val = ON; // Test array and motor contactor when ON + TEST_ASSERT_EQUAL(ON, ContactorsGet(kArrayPrechargeBypassContactor)); + TEST_ASSERT_EQUAL(ON, ContactorsGet(kMotorControllerPrechargeBypassContactor)); + + BspGpioGetState_fake.return_val = OFF; // Test array and motor contactor when OFF + TEST_ASSERT_EQUAL(OFF, ContactorsGet(kArrayPrechargeBypassContactor)); + TEST_ASSERT_EQUAL(OFF, ContactorsGet(kMotorControllerPrechargeBypassContactor)); + + TEST_ASSERT_EQUAL(4, BspGpioGetState_fake.call_count); +} + + +void test_ContactorsSet(){ + + int mutex_calls = 0; + + // Test all input combinations + for (uint8_t contactor = 0; contactor < kNumContactors; contactor++) { + for (uint8_t state = 0; state < BOOL_STATES; state++) { + for (uint8_t blocking = 0; blocking < BOOL_STATES; blocking++) { + + uint16_t pin_mask = 0; + + // Set which pin we should see targeted + if (contactor == kArrayPrechargeBypassContactor) { + pin_mask = ARRAY_PRECHARGE_BYPASS_PIN; + } else if (contactor == kMotorControllerPrechargeBypassContactor) { + pin_mask = MOTOR_CONTROLLER_PRECHARGE_BYPASS_PIN; + } + + // Run ContactorsSet and check that BspGpioWritePin was called with the correct parameters + ContactorsSet((Contactor)contactor, (bool)state, (bool)blocking); + TEST_ASSERT_EQUAL(CONTACTORS_PORT, BspGpioWritePin_fake.arg0_val); + TEST_ASSERT_EQUAL(pin_mask, BspGpioWritePin_fake.arg1_val); + TEST_ASSERT_EQUAL(state, BspGpioWritePin_fake.arg2_val); + + // Check if the call followed the blocking/non-blocking parameter value + if (blocking){ + TEST_ASSERT_EQUAL(OS_OPT_PEND_BLOCKING, OSMutexPend_fake.arg2_val); + } else { + TEST_ASSERT_EQUAL(OS_OPT_PEND_NON_BLOCKING, OSMutexPend_fake.arg2_val); + } + + // Check that we pended and posted to a mutex + mutex_calls++; + TEST_ASSERT_EQUAL(mutex_calls, OSMutexPend_fake.call_count); + TEST_ASSERT_EQUAL(mutex_calls, OSMutexPost_fake.call_count); + + } + } + } + + // Check that BspGpioWritePin was called once for each call to ContactorsSet + TEST_ASSERT_EQUAL(kNumContactors * BOOL_STATES * BOOL_STATES, BspGpioWritePin_fake.call_count); +} + +// Runs the tests +int main(void) { + UNITY_BEGIN(); // UNITY_BEGIN and UNITY_END are required + RUN_TEST(test_ContactorsInit); + RUN_TEST(test_ContactorsGet); + RUN_TEST(test_ContactorsSet); + return UNITY_END(); +} \ No newline at end of file diff --git a/Tests/UnitTests/Tests/Test_Pedals_Example.c b/Tests/UnitTests/Tests/Test_Pedals_Example.c new file mode 100644 index 000000000..cf3c5b859 --- /dev/null +++ b/Tests/UnitTests/Tests/Test_Pedals_Example.c @@ -0,0 +1,72 @@ +/** + * + *@copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file Test_Pedals.c + * @brief An example containing the basic format of a unit test. + * Though not a functional test, it still contains some major elements + * that are necessary in any unit test. + * Thing tested (if test were complete): Pedals functions + * Mocks used:BSP functions (though all things not tested are still mocked) +*/ + +// Unity: the unit testing framework we are using +// Unity contains the assertions required for this testing format +#include "unity.h" + +// The header file we are unit testing +#include "Pedals.h" + +// Fake Function Framework: helps us generate mocks and store data +// We need the header here for DEFINE_FFF_GLOBALS +#include "fff.h" + +// This defines global variables used for test data +// (and therefore can't be defined multiple times in a build) +DEFINE_FFF_GLOBALS; + +// Special function from Unity that runs before each test +void setUp(void) {} + +// Special function from Unity that runs after each test +void tearDown(void) {} + +// A test for PedalsInit which we wrote ourselves and which gets called in main +// This example calls PedalsInit but doesn't actually verify anthing +void test_UnitTestPedalsInit(void){ + PedalsInit(); +} + +// Another test, this time for PedalsRead, which just demos using fake functions +void test_UnitTestPedalsRead(void){ + for(int x = 500; x < 1000; x+=100){ + + // We have defined mock functions (found in the Mocks folder) using fff + // When we unit test, we include the mock functions in place of the real ones + // One of the things we can do with mocks is set their return value + BspAdcGetMillivoltage_fake.return_val = x; + // Now whenever BspAdcGetMillivoltage is called, the mock will return x + + PedalsRead(1); + printf("\n\r%d\r", PedalsRead(1)); + } +} + +// A test that will always fail +void test_UnitTestPedals_Read_This_Will_Fail(void){ + // Unity gives us asserts to verify values + // When an assert fails, Unity will tell us our test has failed + TEST_ASSERT_EQUAL(PedalsRead(1), 30); +} + + + +/*=======MAIN=====*/ +// Here we use Unity's framework to run the tests we've written +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_UnitTestPedalsInit); + RUN_TEST(test_UnitTestPedalsRead); + RUN_TEST(test_UnitTestPedals_Read_This_Will_Fail); + return UNITY_END(); +} \ No newline at end of file diff --git a/Tests/UnitTests/Tests/Test_ReadCarCan_Example.c b/Tests/UnitTests/Tests/Test_ReadCarCan_Example.c new file mode 100644 index 000000000..6dcc6fce6 --- /dev/null +++ b/Tests/UnitTests/Tests/Test_ReadCarCan_Example.c @@ -0,0 +1,89 @@ +/** + * + *@copyright Copyright (c) 2018-2023 UT Longhorn Racing Solar + * @file Test_ReadCarCan.c + * @brief Additional unit testing example for ReadCanCan. + * While not a full test, it introduces a couple test strategies + * Thing tested (if test were complete): ReadCarCan + * Mocks used:CanBus, UpdateDisplay (though all things not tested are still mocked) + * Note: not a real test, so we don't really mind that it fails +*/ +// Unity required for this testing format +#include "unity.h" + +// The header file we are unit testing: +#include "ReadCarCan.h" + +// fff header so we can DEFINE_FFF_GLOBALS +// (can only happen once per test) +#include "fff.h" + +// Mock headers +#include "UpdateDisplay.h" +#include "CanBus.h" + +DEFINE_FFF_GLOBALS; + + +/*** CAN Messages ***/ +static CanData bps_trip_msg = {.id=kBpsTrip, .idx=0, .data={1}}; +//static CANDATA_t supp_voltage_msg = {.ID=SUPPLEMENTAL_VOLTAGE, .idx=0, .data={100}}; +// static CANDATA_t state_of_charge_msg = {.ID=STATE_OF_CHARGE, .idx=0, .data={0}}; +// static CANDATA_t HV_Array_Msg = {.ID=BPS_CONTACTOR, .idx=0, .data={0b001}}; +static CanData HV_Disable_Msg = {.id=kBpsContactor, .idx=0, .data={0b000}}; +// static CANDATA_t HV_MC_Msg = {.ID=BPS_CONTACTOR, .idx=0, .data={0b110}}; +// static CANDATA_t HV_Enabled_Msg = {.ID=BPS_CONTACTOR, .idx=0, .data={0b111}}; + +void setUp(void) { + FFF_RESET_HISTORY(); +} + +void tearDown(void) {} + +// We can use a custom fake to dictate what happens when our mock function is called +// A default mock doesn't do anything, but defining a custom mock lets us do things +// like store a message in a CanData argument to simulate a message being read +ErrorStatus CANbus_Custom_fake_bps(CanData* data, bool blocking, Can bus){ + *data = bps_trip_msg; + return SUCCESS; +} + +ErrorStatus CANbus_Custom_fake_bpscontactor(CanData* data, bool blocking, Can bus){ + *data = HV_Disable_Msg; + return SUCCESS; +} + +void test_UnitTest_bsptrip(void){ + TaskInit(NULL); + CanBusRead_fake.custom_fake = CANbus_Custom_fake_bps; // Set CanBusRead to use our custom fake + TaskReadCarCan(NULL); + printf("\n\r%d\n\r", CanBusRead_fake.call_count); + + TEST_ASSERT_EQUAL(3, ThrowTaskError_fake.arg0_history[0]); + TEST_ASSERT_EQUAL(4, ThrowTaskError_fake.arg0_history[1]); + printf("%d", ThrowTaskError_fake.call_count); + TEST_ASSERT_EQUAL(false, UpdateDisplaySetArray_fake.arg0_history[0]); + TEST_ASSERT_EQUAL(2, DisplayEvac_fake.call_count); +} + +void test_UnitTest_bspcontactor(void){ + TaskInit(NULL); + CanBusRead_fake.custom_fake = CANbus_Custom_fake_bpscontactor; // Set CanBusRead to a different custom fake + TaskReadCarCan(NULL); + printf("\n\r%d\n\r", CanBusRead_fake.call_count); + + TEST_ASSERT_EQUAL(3, ThrowTaskError_fake.arg0_history[0]); + TEST_ASSERT_EQUAL(4, ThrowTaskError_fake.arg0_history[1]); + printf("%d", ThrowTaskError_fake.call_count); + TEST_ASSERT_EQUAL(false, UpdateDisplaySetArray_fake.arg0_history[0]); +} + + +/*=======MAIN=====*/ +int main(void) +{ + UNITY_BEGIN(); + RUN_TEST(test_UnitTest_bspcontactor); + RUN_TEST(test_UnitTest_bsptrip); + return UNITY_END(); +} diff --git a/Tests/UnitTests/Unity/unity.c b/Tests/UnitTests/Unity/unity.c new file mode 100644 index 000000000..14b558ebc --- /dev/null +++ b/Tests/UnitTests/Unity/unity.c @@ -0,0 +1,2487 @@ +/* ========================================================================= + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +============================================================================ */ + +#include "unity.h" + +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0) + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; +#else +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; +#ifndef UNITY_EXCLUDE_DETAILS +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +#endif +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ + const char* pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (style == UNITY_DISPLAY_STYLE_CHAR) + { + /* printable characters plus CR & LF are printed */ + UNITY_OUTPUT_CHAR('\''); + if ((number <= 126) && (number >= 32)) + { + UNITY_OUTPUT_CHAR((int)number); + } + /* write escaped carriage returns */ + else if (number == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (number == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 2); + } + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrintNumber(number); + } + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned((UNITY_UINT)number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (~number) + 1; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (does not handle negative zero) */ + if (number < 0.0f) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (UNITY_IS_NAN(number)) + { + UnityPrint("nan"); + } + else if (UNITY_IS_INF(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits <= decimals)) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + + /* print out buffer (backwards) */ + while (digits > 0) + { + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE + UNITY_OUTPUT_CHAR('('); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(')'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH + UnityPrint("'); + UnityPrint(Unity.CurrentTestName); + UnityPrint(" "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR + UnityPrint("file://"); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ +#ifdef UNITY_PRINT_TEST_CONTEXT + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + } +#endif + if (msg) + { + UnityPrint(UnityStrSpacer); + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, + const char* actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char* msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) { return 0; } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; } + if ((threshold == actual)) { failed = 1; } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + else /* UINT or HEX */ + { + if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); } + UnityPrintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +do { \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; \ +} while (0) + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (UNITY_IS_INF(expected) && UNITY_IS_INF(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \ + if (UNITY_NAN_CHECK) return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) (diff) = -(diff); \ + if ((delta) < 0) (delta) = -(delta); \ + return !(UNITY_IS_NAN(diff) || UNITY_IS_INF(diff) || ((diff) > (delta))) + /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN + #define UNITY_NAN_CHECK UNITY_IS_NAN(expected) && UNITY_IS_NAN(actual) +#else + #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while (0) +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (UNITY_IS_INF(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (UNITY_IS_NAN(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = UNITY_IS_INF(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = UNITY_IS_INF(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = UNITY_IS_NAN(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !UNITY_IS_INF(actual) && !UNITY_IS_NAN(actual); + break; + + case UNITY_FLOAT_INVALID_TRAIT: /* Supress warning */ + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual; + increment = sizeof(UNITY_UINT8); + } + break; + + case 2: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual; + increment = sizeof(UNITY_UINT16); + } + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual; + increment = sizeof(UNITY_UINT64); + } + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual; + increment = sizeof(UNITY_UINT32); + } + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* fail if either null but not if both */ + if (expected || actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* expd = NULL; + const char* act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char*)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier { + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ +do { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ +} while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + +/*----------------------------------------------- + * printf helper function + *-----------------------------------------------*/ +static void UnityPrintFVA(const char* format, va_list va) +{ + const char* pch = format; + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + + switch (*pch) + { + case 'd': + case 'i': + { + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); + break; + } + case 'b': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, number); + break; + } + case 'x': + case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, UNITY_MAX_NIBBLES); + break; + } + case 'p': + { + UNITY_UINT number; + char nibbles_to_print = 8; + if (UNITY_POINTER_WIDTH == 64) + { + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + nibbles_to_print = 16; + } + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, nibbles_to_print); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char * string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } +} + +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if(format != NULL) + { + UnityPrint(": "); + va_list va; + va_start(va, format); + UnityPrintFVA(format, va); + va_end(va); + } + UNITY_PRINT_EOL(); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifdef UNITY_PRINT_TEST_CONTEXT + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +/* If we have not defined our own test runner, then include our default test runner to make life easier */ +#ifndef UNITY_SKIP_DEFAULT_RUNNER +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} +#endif + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char* filename) +{ + Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ + int i; + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + /* Now display help */ + /* FALLTHRU */ + case 'h': + UnityPrint("Options: "); UNITY_PRINT_EOL(); + UnityPrint("-l List all tests and exit"); UNITY_PRINT_EOL(); + UnityPrint("-f NAME Filter to run only tests whose name includes NAME"); UNITY_PRINT_EOL(); + UnityPrint("-n NAME (deprecated) alias of -f"); UNITY_PRINT_EOL(); + UnityPrint("-h show this Help menu"); UNITY_PRINT_EOL(); + UnityPrint("-q Quiet/decrease verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-v increase Verbosity"); UNITY_PRINT_EOL(); + UnityPrint("-x NAME eXclude tests whose name includes NAME"); UNITY_PRINT_EOL(); + UNITY_OUTPUT_FLUSH(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; + + if (*sptr == '*') + { + return 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + /* We're done if we match the entire string or up to a wildcard */ + if (*sptr == '*') + return 1; + if (*sptr == ',') + return 1; + if (*sptr == '"') + return 1; + if (*sptr == '\'') + return 1; + if (*sptr == ':') + return 2; + if (*sptr == 0) + return 1; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +int UnityStringArgumentMatches(const char* str) +{ + int retval; + const char* ptr1; + const char* ptr2; + const char* ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ \ No newline at end of file diff --git a/Tests/UnitTests/Unity/unity.h b/Tests/UnitTests/Unity/unity.h new file mode 100644 index 000000000..4079f259e --- /dev/null +++ b/Tests/UnitTests/Unity/unity.h @@ -0,0 +1,697 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 6 +#define UNITY_VERSION_BUILD 0 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), ##__VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/*------------------------------------------------------- + * Build Directives + *------------------------------------------------------- + + * These macros do nothing, but they are useful for additional build context. + * Tools (like Ceedling) can scan for these directives and make use of them for + * per-test-executable #include search paths and linking. */ + +/* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ +#define TEST_SOURCE_FILE(a) + +/* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ +#define TEST_INCLUDE_PATH(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/Tests/UnitTests/Unity/unity_internals.h b/Tests/UnitTests/Unity/unity_internals.h new file mode 100644 index 000000000..65938ff76 --- /dev/null +++ b/Tests/UnitTests/Unity/unity_internals.h @@ -0,0 +1,1169 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +#ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #include + #define UNITY_NORETURN noreturn + #endif + #endif +#endif +#ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(__noreturn__) +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isnan macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_NAN +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define UNITY_IS_NAN(n) ((n != n) ? 1 : 0) +#else +#define UNITY_IS_NAN(n) isnan(n) +#endif +#endif + +/* isinf macro should be provided by math.h. Override if not macro */ +#ifndef UNITY_IS_INF +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define UNITY_IS_INF(n) (UNITY_IS_NAN((n) - (n)) && !UNITY_IS_NAN(n)) +#else +#define UNITY_IS_INF(n) isinf(n) +#endif +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifdef UNITY_TEST_PROTECT +#define TEST_PROTECT() UNITY_TEST_PROTECT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#else +#define TEST_PROTECT() 1 +#endif +#endif + +#ifdef UNITY_TEST_ABORT +#define TEST_ABORT() UNITY_TEST_ABORT() +#else +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_ABORT() return +#endif +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #if !defined(TEST_MATRIX) && !defined(UNITY_EXCLUDE_TEST_MATRIX) + #define TEST_MATRIX(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (UNITY_LINE_TYPE)(line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (const UNITY_FLOAT*)(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (const UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (const UNITY_DOUBLE*)(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (const UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/Tests/UnitTests/fff.h b/Tests/UnitTests/fff.h new file mode 100644 index 000000000..6601f846f --- /dev/null +++ b/Tests/UnitTests/fff.h @@ -0,0 +1,6588 @@ +/* +LICENSE + +The MIT License (MIT) + +Copyright (c) 2010 Michael Long + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#ifndef FAKE_FUNCTIONS +#define FAKE_FUNCTIONS + +#include +#include /* For memset and memcpy */ + +#define FFF_MAX_ARGS (20u) +#ifndef FFF_ARG_HISTORY_LEN + #define FFF_ARG_HISTORY_LEN (50u) +#endif +#ifndef FFF_CALL_HISTORY_LEN + #define FFF_CALL_HISTORY_LEN (50u) +#endif +#ifndef FFF_GCC_FUNCTION_ATTRIBUTES + #define FFF_GCC_FUNCTION_ATTRIBUTES +#endif +#ifndef CUSTOM_FFF_FUNCTION_TEMPLATE +#define CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN, FUNCNAME, ...) \ + RETURN(*FUNCNAME)(__VA_ARGS__) +#endif /* CUSTOM_FFF_FUNCTION_TEMPLATE */ +/* -- INTERNAL HELPER MACROS -- */ +#define SET_RETURN_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \ + FUNCNAME##_fake.return_val_seq = ARRAY_POINTER; \ + FUNCNAME##_fake.return_val_seq_len = ARRAY_LEN; +#define SET_CUSTOM_FAKE_SEQ(FUNCNAME, ARRAY_POINTER, ARRAY_LEN) \ + FUNCNAME##_fake.custom_fake_seq = ARRAY_POINTER; \ + FUNCNAME##_fake.custom_fake_seq_len = ARRAY_LEN; + +/* Defining a function to reset a fake function */ +#define RESET_FAKE(FUNCNAME) { \ + FUNCNAME##_reset(); \ +} \ + + +#define DECLARE_ARG(type, n, FUNCNAME) \ + type arg##n##_val; \ + type arg##n##_history[FFF_ARG_HISTORY_LEN]; + +#define DECLARE_ALL_FUNC_COMMON \ + unsigned int call_count; \ + unsigned int arg_history_len; \ + unsigned int arg_histories_dropped; \ + +#define DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + RETURN_TYPE return_val_history[FFF_ARG_HISTORY_LEN]; + +#define SAVE_ARG(FUNCNAME, n) \ + memcpy((void*)&FUNCNAME##_fake.arg##n##_val, (void*)&arg##n, sizeof(arg##n)); + +#define ROOM_FOR_MORE_HISTORY(FUNCNAME) \ + FUNCNAME##_fake.call_count < FFF_ARG_HISTORY_LEN + +#define SAVE_RET_HISTORY(FUNCNAME, RETVAL) \ + if ((FUNCNAME##_fake.call_count - 1) < FFF_ARG_HISTORY_LEN) \ + memcpy((void *)&FUNCNAME##_fake.return_val_history[FUNCNAME##_fake.call_count - 1], (const void *) &RETVAL, sizeof(RETVAL)); \ + +#define SAVE_ARG_HISTORY(FUNCNAME, ARGN) \ + memcpy((void*)&FUNCNAME##_fake.arg##ARGN##_history[FUNCNAME##_fake.call_count], (void*)&arg##ARGN, sizeof(arg##ARGN)); + +#define HISTORY_DROPPED(FUNCNAME) \ + FUNCNAME##_fake.arg_histories_dropped++ + +#define DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + RETURN_TYPE return_val; \ + int return_val_seq_len; \ + int return_val_seq_idx; \ + RETURN_TYPE * return_val_seq; \ + +#define DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + int custom_fake_seq_len; \ + int custom_fake_seq_idx; \ + +#define INCREMENT_CALL_COUNT(FUNCNAME) \ + FUNCNAME##_fake.call_count++ + +#define RETURN_FAKE_RESULT(FUNCNAME) \ + if (FUNCNAME##_fake.return_val_seq_len){ /* then its a sequence */ \ + if(FUNCNAME##_fake.return_val_seq_idx < FUNCNAME##_fake.return_val_seq_len) { \ + SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx]) \ + return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_idx++]; \ + } \ + SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]) \ + return FUNCNAME##_fake.return_val_seq[FUNCNAME##_fake.return_val_seq_len-1]; /* return last element */ \ + } \ + SAVE_RET_HISTORY(FUNCNAME, FUNCNAME##_fake.return_val) \ + return FUNCNAME##_fake.return_val; \ + +#ifdef __cplusplus + #define FFF_EXTERN_C extern "C"{ + #define FFF_END_EXTERN_C } +#else /* ansi c */ + #define FFF_EXTERN_C + #define FFF_END_EXTERN_C +#endif /* cpp/ansi c */ + +#define DEFINE_RESET_FUNCTION(FUNCNAME) \ + void FUNCNAME##_reset(void){ \ + memset((void*)&FUNCNAME##_fake, 0, sizeof(FUNCNAME##_fake) - sizeof(FUNCNAME##_fake.custom_fake) - sizeof(FUNCNAME##_fake.custom_fake_seq)); \ + FUNCNAME##_fake.custom_fake = NULL; \ + FUNCNAME##_fake.custom_fake_seq = NULL; \ + FUNCNAME##_fake.arg_history_len = FFF_ARG_HISTORY_LEN; \ + } +/* -- END INTERNAL HELPER MACROS -- */ + +typedef void (*fff_function_t)(void); +typedef struct { + fff_function_t call_history[FFF_CALL_HISTORY_LEN]; + unsigned int call_history_idx; +} fff_globals_t; + +FFF_EXTERN_C +extern fff_globals_t fff; +FFF_END_EXTERN_C + +#define DEFINE_FFF_GLOBALS \ + FFF_EXTERN_C \ + fff_globals_t fff; \ + FFF_END_EXTERN_C + +#define FFF_RESET_HISTORY() \ + fff.call_history_idx = 0; \ + memset(fff.call_history, 0, sizeof(fff.call_history)); + +#define REGISTER_CALL(function) \ + if(fff.call_history_idx < FFF_CALL_HISTORY_LEN) \ + fff.call_history[fff.call_history_idx++] = (fff_function_t)function; + +#define DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, void); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, void); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(void); \ + +#define DEFINE_FAKE_VOID_FUNC0(FUNCNAME) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(void){ \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC0(FUNCNAME) \ + DECLARE_FAKE_VOID_FUNC0(FUNCNAME) \ + DEFINE_FAKE_VOID_FUNC0(FUNCNAME) \ + + +#define DECLARE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0); \ + +#define DEFINE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + DECLARE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + DEFINE_FAKE_VOID_FUNC1(FUNCNAME, ARG0_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1); \ + +#define DEFINE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DECLARE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DEFINE_FAKE_VOID_FUNC2(FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \ + +#define DEFINE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DECLARE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DEFINE_FAKE_VOID_FUNC3(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \ + +#define DEFINE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DECLARE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DEFINE_FAKE_VOID_FUNC4(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \ + +#define DEFINE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DECLARE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DEFINE_FAKE_VOID_FUNC5(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \ + +#define DEFINE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DECLARE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DEFINE_FAKE_VOID_FUNC6(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \ + +#define DEFINE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DECLARE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DEFINE_FAKE_VOID_FUNC7(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \ + +#define DEFINE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DECLARE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DEFINE_FAKE_VOID_FUNC8(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \ + +#define DEFINE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DECLARE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DEFINE_FAKE_VOID_FUNC9(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \ + +#define DEFINE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DECLARE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DEFINE_FAKE_VOID_FUNC10(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \ + +#define DEFINE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DECLARE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DEFINE_FAKE_VOID_FUNC11(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \ + +#define DEFINE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DECLARE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DEFINE_FAKE_VOID_FUNC12(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \ + +#define DEFINE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DECLARE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DEFINE_FAKE_VOID_FUNC13(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \ + +#define DEFINE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DECLARE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DEFINE_FAKE_VOID_FUNC14(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \ + +#define DEFINE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DECLARE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DEFINE_FAKE_VOID_FUNC15(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \ + +#define DEFINE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DECLARE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DEFINE_FAKE_VOID_FUNC16(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \ + +#define DEFINE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DECLARE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DEFINE_FAKE_VOID_FUNC17(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \ + +#define DEFINE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DECLARE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DEFINE_FAKE_VOID_FUNC18(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \ + +#define DEFINE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DECLARE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DEFINE_FAKE_VOID_FUNC19(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ARG(ARG19_TYPE, 19, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \ + +#define DEFINE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + SAVE_ARG(FUNCNAME, 19); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + SAVE_ARG_HISTORY(FUNCNAME, 19); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + } \ + else{ \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DECLARE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DEFINE_FAKE_VOID_FUNC20(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, void); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, void); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(void); \ + +#define DEFINE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(void){ \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + DECLARE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + DEFINE_FAKE_VALUE_FUNC0(RETURN_TYPE, FUNCNAME) \ + + +#define DECLARE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0); \ + +#define DEFINE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + DECLARE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + DEFINE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1); \ + +#define DEFINE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DECLARE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + DEFINE_FAKE_VALUE_FUNC2(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2); \ + +#define DEFINE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DECLARE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + DEFINE_FAKE_VALUE_FUNC3(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3); \ + +#define DEFINE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DECLARE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + DEFINE_FAKE_VALUE_FUNC4(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4); \ + +#define DEFINE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DECLARE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + DEFINE_FAKE_VALUE_FUNC5(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5); \ + +#define DEFINE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DECLARE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + DEFINE_FAKE_VALUE_FUNC6(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6); \ + +#define DEFINE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DECLARE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + DEFINE_FAKE_VALUE_FUNC7(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7); \ + +#define DEFINE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DECLARE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + DEFINE_FAKE_VALUE_FUNC8(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8); \ + +#define DEFINE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DECLARE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + DEFINE_FAKE_VALUE_FUNC9(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9); \ + +#define DEFINE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DECLARE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + DEFINE_FAKE_VALUE_FUNC10(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10); \ + +#define DEFINE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DECLARE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + DEFINE_FAKE_VALUE_FUNC11(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11); \ + +#define DEFINE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DECLARE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + DEFINE_FAKE_VALUE_FUNC12(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12); \ + +#define DEFINE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DECLARE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + DEFINE_FAKE_VALUE_FUNC13(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13); \ + +#define DEFINE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DECLARE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + DEFINE_FAKE_VALUE_FUNC14(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14); \ + +#define DEFINE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DECLARE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + DEFINE_FAKE_VALUE_FUNC15(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15); \ + +#define DEFINE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DECLARE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + DEFINE_FAKE_VALUE_FUNC16(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16); \ + +#define DEFINE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DECLARE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + DEFINE_FAKE_VALUE_FUNC17(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17); \ + +#define DEFINE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DECLARE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + DEFINE_FAKE_VALUE_FUNC18(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18); \ + +#define DEFINE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DECLARE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + DEFINE_FAKE_VALUE_FUNC19(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE) \ + + +#define DECLARE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ARG(ARG19_TYPE, 19, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19); \ + +#define DEFINE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ARG19_TYPE arg19){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + SAVE_ARG(FUNCNAME, 19); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + SAVE_ARG_HISTORY(FUNCNAME, 19); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + else{ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + } \ + if (FUNCNAME##_fake.custom_fake != NULL){ \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DECLARE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + DEFINE_FAKE_VALUE_FUNC20(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ARG19_TYPE) \ + + +#define DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ...); \ + +#define DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg0); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg0); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg0); \ + FUNCNAME##_fake.custom_fake(arg0, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC2_VARARG(FUNCNAME, ARG0_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...); \ + +#define DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg1); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg1); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg1); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC3_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...); \ + +#define DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg2); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg2); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg2); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC4_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...); \ + +#define DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg3); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg3); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg3); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC5_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...); \ + +#define DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg4); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg4); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg4); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC6_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...); \ + +#define DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg5); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg5); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg5); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC7_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...); \ + +#define DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg6); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg6); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg6); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC8_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...); \ + +#define DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg7); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg7); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg7); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC9_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...); \ + +#define DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg8); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg8); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg8); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC10_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...); \ + +#define DEFINE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg9); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg9); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg9); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC11_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...); \ + +#define DEFINE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg10); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg10); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg10); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC12_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...); \ + +#define DEFINE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg11); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg11); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg11); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC13_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...); \ + +#define DEFINE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg12); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg12); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg12); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC14_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...); \ + +#define DEFINE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg13); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg13); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg13); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC15_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...); \ + +#define DEFINE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg14); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg14); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg14); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC16_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...); \ + +#define DEFINE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg15); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg15); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg15); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC17_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...); \ + +#define DEFINE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg16); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg16); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg16); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC18_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...); \ + +#define DEFINE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg17); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg17); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg17); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC19_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + + +#define DECLARE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(void, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...); \ + +#define DEFINE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + void FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg18); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \ + va_end(ap); \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg18); \ + FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \ + va_end(ap); \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + va_list ap; \ + va_start(ap, arg18); \ + FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \ + va_end(ap); \ + } \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DECLARE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DEFINE_FAKE_VOID_FUNC20_VARARG(FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg0); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg0); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg0); \ + ret = FUNCNAME##_fake.custom_fake(arg0, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC2_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg1); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg1); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg1); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC3_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg2); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg2); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg2); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC4_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg3); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg3); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg3); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC5_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg4); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg4); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg4); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC6_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg5); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg5); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg5); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC7_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg6); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg6); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg6); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC8_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg7); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg7); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg7); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC9_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg8); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg8); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg8); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC10_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg9); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg9); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg9); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC11_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg10); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg10); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg10); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC12_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg11); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg11); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg11); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC13_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg12); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg12); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg12); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC14_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg13); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg13); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg13); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC15_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg14); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg14); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg14); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC16_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg15); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg15); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg15); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC17_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg16); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg16); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg16); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC18_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg17); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg17); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg17); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC19_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ...) \ + + +#define DECLARE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + typedef struct FUNCNAME##_Fake { \ + DECLARE_ARG(ARG0_TYPE, 0, FUNCNAME) \ + DECLARE_ARG(ARG1_TYPE, 1, FUNCNAME) \ + DECLARE_ARG(ARG2_TYPE, 2, FUNCNAME) \ + DECLARE_ARG(ARG3_TYPE, 3, FUNCNAME) \ + DECLARE_ARG(ARG4_TYPE, 4, FUNCNAME) \ + DECLARE_ARG(ARG5_TYPE, 5, FUNCNAME) \ + DECLARE_ARG(ARG6_TYPE, 6, FUNCNAME) \ + DECLARE_ARG(ARG7_TYPE, 7, FUNCNAME) \ + DECLARE_ARG(ARG8_TYPE, 8, FUNCNAME) \ + DECLARE_ARG(ARG9_TYPE, 9, FUNCNAME) \ + DECLARE_ARG(ARG10_TYPE, 10, FUNCNAME) \ + DECLARE_ARG(ARG11_TYPE, 11, FUNCNAME) \ + DECLARE_ARG(ARG12_TYPE, 12, FUNCNAME) \ + DECLARE_ARG(ARG13_TYPE, 13, FUNCNAME) \ + DECLARE_ARG(ARG14_TYPE, 14, FUNCNAME) \ + DECLARE_ARG(ARG15_TYPE, 15, FUNCNAME) \ + DECLARE_ARG(ARG16_TYPE, 16, FUNCNAME) \ + DECLARE_ARG(ARG17_TYPE, 17, FUNCNAME) \ + DECLARE_ARG(ARG18_TYPE, 18, FUNCNAME) \ + DECLARE_ALL_FUNC_COMMON \ + DECLARE_VALUE_FUNCTION_VARIABLES(RETURN_TYPE) \ + DECLARE_RETURN_VALUE_HISTORY(RETURN_TYPE) \ + DECLARE_CUSTOM_FAKE_SEQ_VARIABLES \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, custom_fake, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, va_list ap); \ + CUSTOM_FFF_FUNCTION_TEMPLATE(RETURN_TYPE, *custom_fake_seq, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, va_list ap); \ + } FUNCNAME##_Fake; \ + extern FUNCNAME##_Fake FUNCNAME##_fake; \ + void FUNCNAME##_reset(void); \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...); \ + +#define DEFINE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + FUNCNAME##_Fake FUNCNAME##_fake; \ + RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0, ARG1_TYPE arg1, ARG2_TYPE arg2, ARG3_TYPE arg3, ARG4_TYPE arg4, ARG5_TYPE arg5, ARG6_TYPE arg6, ARG7_TYPE arg7, ARG8_TYPE arg8, ARG9_TYPE arg9, ARG10_TYPE arg10, ARG11_TYPE arg11, ARG12_TYPE arg12, ARG13_TYPE arg13, ARG14_TYPE arg14, ARG15_TYPE arg15, ARG16_TYPE arg16, ARG17_TYPE arg17, ARG18_TYPE arg18, ...){ \ + SAVE_ARG(FUNCNAME, 0); \ + SAVE_ARG(FUNCNAME, 1); \ + SAVE_ARG(FUNCNAME, 2); \ + SAVE_ARG(FUNCNAME, 3); \ + SAVE_ARG(FUNCNAME, 4); \ + SAVE_ARG(FUNCNAME, 5); \ + SAVE_ARG(FUNCNAME, 6); \ + SAVE_ARG(FUNCNAME, 7); \ + SAVE_ARG(FUNCNAME, 8); \ + SAVE_ARG(FUNCNAME, 9); \ + SAVE_ARG(FUNCNAME, 10); \ + SAVE_ARG(FUNCNAME, 11); \ + SAVE_ARG(FUNCNAME, 12); \ + SAVE_ARG(FUNCNAME, 13); \ + SAVE_ARG(FUNCNAME, 14); \ + SAVE_ARG(FUNCNAME, 15); \ + SAVE_ARG(FUNCNAME, 16); \ + SAVE_ARG(FUNCNAME, 17); \ + SAVE_ARG(FUNCNAME, 18); \ + if(ROOM_FOR_MORE_HISTORY(FUNCNAME)){ \ + SAVE_ARG_HISTORY(FUNCNAME, 0); \ + SAVE_ARG_HISTORY(FUNCNAME, 1); \ + SAVE_ARG_HISTORY(FUNCNAME, 2); \ + SAVE_ARG_HISTORY(FUNCNAME, 3); \ + SAVE_ARG_HISTORY(FUNCNAME, 4); \ + SAVE_ARG_HISTORY(FUNCNAME, 5); \ + SAVE_ARG_HISTORY(FUNCNAME, 6); \ + SAVE_ARG_HISTORY(FUNCNAME, 7); \ + SAVE_ARG_HISTORY(FUNCNAME, 8); \ + SAVE_ARG_HISTORY(FUNCNAME, 9); \ + SAVE_ARG_HISTORY(FUNCNAME, 10); \ + SAVE_ARG_HISTORY(FUNCNAME, 11); \ + SAVE_ARG_HISTORY(FUNCNAME, 12); \ + SAVE_ARG_HISTORY(FUNCNAME, 13); \ + SAVE_ARG_HISTORY(FUNCNAME, 14); \ + SAVE_ARG_HISTORY(FUNCNAME, 15); \ + SAVE_ARG_HISTORY(FUNCNAME, 16); \ + SAVE_ARG_HISTORY(FUNCNAME, 17); \ + SAVE_ARG_HISTORY(FUNCNAME, 18); \ + } \ + else{ \ + HISTORY_DROPPED(FUNCNAME); \ + } \ + INCREMENT_CALL_COUNT(FUNCNAME); \ + REGISTER_CALL(FUNCNAME); \ + if (FUNCNAME##_fake.custom_fake_seq_len){ /* a sequence of custom fakes */ \ + if (FUNCNAME##_fake.custom_fake_seq_idx < FUNCNAME##_fake.custom_fake_seq_len){ \ + va_list ap; \ + va_start(ap, arg18); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_idx++](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + else{ \ + va_list ap; \ + va_start(ap, arg18); \ + RETURN_TYPE ret = FUNCNAME##_fake.custom_fake_seq[FUNCNAME##_fake.custom_fake_seq_len-1](arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + va_end(ap); \ + return ret; \ + } \ + } \ + if(FUNCNAME##_fake.custom_fake){ \ + RETURN_TYPE ret; \ + va_list ap; \ + va_start(ap, arg18); \ + ret = FUNCNAME##_fake.custom_fake(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, ap); \ + va_end(ap); \ + SAVE_RET_HISTORY(FUNCNAME, ret); \ + return ret; \ + } \ + RETURN_FAKE_RESULT(FUNCNAME) \ + } \ + DEFINE_RESET_FUNCTION(FUNCNAME) \ + +#define FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DECLARE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + DEFINE_FAKE_VALUE_FUNC20_VARARG(RETURN_TYPE, FUNCNAME, ARG0_TYPE, ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE, ARG6_TYPE, ARG7_TYPE, ARG8_TYPE, ARG9_TYPE, ARG10_TYPE, ARG11_TYPE, ARG12_TYPE, ARG13_TYPE, ARG14_TYPE, ARG15_TYPE, ARG16_TYPE, ARG17_TYPE, ARG18_TYPE, ...) \ + +/* MSVC expand macro fix */ +#define EXPAND(x) x + +#define PP_NARG_MINUS2(...) EXPAND(PP_NARG_MINUS2_(__VA_ARGS__, PP_RSEQ_N_MINUS2())) + +#define PP_NARG_MINUS2_(...) EXPAND(PP_ARG_MINUS2_N(__VA_ARGS__)) + +#define PP_ARG_MINUS2_N(returnVal, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N + +#define PP_RSEQ_N_MINUS2() 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + +#define PP_NARG_MINUS1(...) EXPAND(PP_NARG_MINUS1_(__VA_ARGS__, PP_RSEQ_N_MINUS1())) + +#define PP_NARG_MINUS1_(...) EXPAND(PP_ARG_MINUS1_N(__VA_ARGS__)) + +#define PP_ARG_MINUS1_N( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N + +#define PP_RSEQ_N_MINUS1() 20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 + + + +/* DECLARE AND DEFINE FAKE FUNCTIONS - PLACE IN TEST FILES */ + +#define FAKE_VALUE_FUNC(...) EXPAND(FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__)) + +#define FUNC_VALUE_(N,...) EXPAND(FUNC_VALUE_N(N,__VA_ARGS__)) + +#define FUNC_VALUE_N(N,...) EXPAND(FAKE_VALUE_FUNC ## N(__VA_ARGS__)) + + +#define FAKE_VOID_FUNC(...) EXPAND(FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__)) + +#define FUNC_VOID_(N,...) EXPAND(FUNC_VOID_N(N,__VA_ARGS__)) + +#define FUNC_VOID_N(N,...) EXPAND(FAKE_VOID_FUNC ## N(__VA_ARGS__)) + + +#define FAKE_VALUE_FUNC_VARARG(...) EXPAND(FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__)) + +#define FUNC_VALUE_VARARG_(N,...) EXPAND(FUNC_VALUE_VARARG_N(N,__VA_ARGS__)) + +#define FUNC_VALUE_VARARG_N(N,...) EXPAND(FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__)) + + +#define FAKE_VOID_FUNC_VARARG(...) EXPAND(FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__)) + +#define FUNC_VOID_VARARG_(N,...) EXPAND(FUNC_VOID_VARARG_N(N,__VA_ARGS__)) + +#define FUNC_VOID_VARARG_N(N,...) EXPAND(FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__)) + + + +/* DECLARE FAKE FUNCTIONS - PLACE IN HEADER FILES */ + +#define DECLARE_FAKE_VALUE_FUNC(...) EXPAND(DECLARE_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__)) + +#define DECLARE_FUNC_VALUE_(N,...) EXPAND(DECLARE_FUNC_VALUE_N(N,__VA_ARGS__)) + +#define DECLARE_FUNC_VALUE_N(N,...) EXPAND(DECLARE_FAKE_VALUE_FUNC ## N(__VA_ARGS__)) + + +#define DECLARE_FAKE_VOID_FUNC(...) EXPAND(DECLARE_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__)) + +#define DECLARE_FUNC_VOID_(N,...) EXPAND(DECLARE_FUNC_VOID_N(N,__VA_ARGS__)) + +#define DECLARE_FUNC_VOID_N(N,...) EXPAND(DECLARE_FAKE_VOID_FUNC ## N(__VA_ARGS__)) + + +#define DECLARE_FAKE_VALUE_FUNC_VARARG(...) EXPAND(DECLARE_FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__)) + +#define DECLARE_FUNC_VALUE_VARARG_(N,...) EXPAND(DECLARE_FUNC_VALUE_VARARG_N(N,__VA_ARGS__)) + +#define DECLARE_FUNC_VALUE_VARARG_N(N,...) EXPAND(DECLARE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__)) + + +#define DECLARE_FAKE_VOID_FUNC_VARARG(...) EXPAND(DECLARE_FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__)) + +#define DECLARE_FUNC_VOID_VARARG_(N,...) EXPAND(DECLARE_FUNC_VOID_VARARG_N(N,__VA_ARGS__)) + +#define DECLARE_FUNC_VOID_VARARG_N(N,...) EXPAND(DECLARE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__)) + + + +/* DEFINE FAKE FUNCTIONS - PLACE IN SOURCE FILES */ + +#define DEFINE_FAKE_VALUE_FUNC(...) EXPAND(DEFINE_FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__)) + +#define DEFINE_FUNC_VALUE_(N,...) EXPAND(DEFINE_FUNC_VALUE_N(N,__VA_ARGS__)) + +#define DEFINE_FUNC_VALUE_N(N,...) EXPAND(DEFINE_FAKE_VALUE_FUNC ## N(__VA_ARGS__)) + + +#define DEFINE_FAKE_VOID_FUNC(...) EXPAND(DEFINE_FUNC_VOID_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__)) + +#define DEFINE_FUNC_VOID_(N,...) EXPAND(DEFINE_FUNC_VOID_N(N,__VA_ARGS__)) + +#define DEFINE_FUNC_VOID_N(N,...) EXPAND(DEFINE_FAKE_VOID_FUNC ## N(__VA_ARGS__)) + + +#define DEFINE_FAKE_VALUE_FUNC_VARARG(...) EXPAND(DEFINE_FUNC_VALUE_VARARG_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__)) + +#define DEFINE_FUNC_VALUE_VARARG_(N,...) EXPAND(DEFINE_FUNC_VALUE_VARARG_N(N,__VA_ARGS__)) + +#define DEFINE_FUNC_VALUE_VARARG_N(N,...) EXPAND(DEFINE_FAKE_VALUE_FUNC ## N ## _VARARG(__VA_ARGS__)) + + +#define DEFINE_FAKE_VOID_FUNC_VARARG(...) EXPAND(DEFINE_FUNC_VOID_VARARG_(PP_NARG_MINUS1(__VA_ARGS__), __VA_ARGS__)) + +#define DEFINE_FUNC_VOID_VARARG_(N,...) EXPAND(DEFINE_FUNC_VOID_VARARG_N(N,__VA_ARGS__)) + +#define DEFINE_FUNC_VOID_VARARG_N(N,...) EXPAND(DEFINE_FAKE_VOID_FUNC ## N ## _VARARG(__VA_ARGS__)) + + + + +#endif /* FAKE_FUNCTIONS */ \ No newline at end of file