Skip to content

Commit

Permalink
WIP: Adding stub override support
Browse files Browse the repository at this point in the history
Added function to check for override.
Added set hook functions to provide override.
Created new entry type for stub override.
Added private function for set hook overrides to both use
for setting the override stub entry.
Implemented both set hook override functions (standard and Va)
Implemented public access to override check function.
  • Loading branch information
asgibson committed Mar 5, 2021
1 parent ff4f523 commit 81b167c
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
37 changes: 37 additions & 0 deletions ut_assert/inc/utstubs.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ typedef int32 (*UT_VaHookFunc_t)(void *UserObj, int32 StubRetcode, uint32 CallCo
*/
void UT_ResetState(UT_EntryKey_t FuncKey);

/**
* A value to indicate if the currently running stub's behavior after
* a hook call should be run or not.
*
* \param Retcode The boolean value indicating the override. When 'true'
* indicates remaining stub code should not be run, it is in override.
*/
bool UT_StubIsOverridden(UT_EntryKey_t FuncKey);

/**
* Add a deferred return code entry for the given stub function
*
Expand Down Expand Up @@ -239,6 +248,18 @@ void UT_ClearForceFail(UT_EntryKey_t FuncKey);
*/
void UT_SetHookFunction(UT_EntryKey_t FuncKey, UT_HookFunc_t HookFunc, void *UserObj);

/**
* Set a Hook function for a particular call, but override any remaining stub functionality
*
* This triggers a callback to a user-defined function when the stub is invoked.
* Upon return to the original stub the OverrideStub will be true and any remaining
* code lines in stub (that are purposefully bypassed by the stub) will not be executed.
*
* \param FuncKey The stub function to add the hook to.
* \param HookFunc User defined hook function. Set NULL to delete/clear an entry.
* \param UserObj Arbitrary user data object to pass to the hook function
*/void UT_SetHookOverrideStubFunction(UT_EntryKey_t FuncKey, UT_HookFunc_t HookFunc, void *UserObj);

/**
* Set a variable-argument Hook function for a particular call
*
Expand All @@ -257,6 +278,22 @@ void UT_SetHookFunction(UT_EntryKey_t FuncKey, UT_HookFunc_t HookFunc, void *Use
*/
void UT_SetVaHookFunction(UT_EntryKey_t FuncKey, UT_VaHookFunc_t HookFunc, void *UserObj);

/**
* Set a Hook function for a particular call, but override any remaining stub functionality
* for va_list using functions. However, some systems have limited support for va_list, so
* this might not be available on those systems. Tests should use the generic (non-va) hook
* function unless the arguments are truly necessary.
*
* This triggers a callback to a user-defined function when the stub is invoked.
* Upon return to the original stub the OverrideStub will be true and any remaining
* code lines in stub (that are purposefully bypassed by the stub) will not be executed.
*
* \param FuncKey The stub function to add the hook to.
* \param HookFunc User defined hook function. Set NULL to delete/clear an entry.
* \param UserObj Arbitrary user data object to pass to the hook function
*/
void UT_SetVaHookOverrideStubFunction(UT_EntryKey_t FuncKey, UT_VaHookFunc_t HookFunc, void *UserObj);

/**
* Get a count for the number of times a stub was invoked, at its most recent return value
*
Expand Down
44 changes: 44 additions & 0 deletions ut_assert/src/utstubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef enum
UT_ENTRYTYPE_CALLBACK_HOOK, /**< Pointer to a custom callback/hook function */
UT_ENTRYTYPE_CALLBACK_CONTEXT, /**< Context data for callback/hook function */
UT_ENTRYTYPE_CALL_ONCE, /**< Records a "call once" directive */
UT_ENTRYTYPE_OVERRIDE_STUB, /**< Records when stub after hook call behavior should not be used */
} UT_EntryType_t;

typedef struct
Expand Down Expand Up @@ -183,6 +184,24 @@ static UT_StubTableEntry_t *UT_GetStubEntry(UT_EntryKey_t FuncKey, UT_EntryType_
return (StubPtr);
}

static void UT_DoSetOverride(UT_EntryKey_t FuncKey)
{
UT_StubTableEntry_t *StubPtr;

/* check if there is already an entry */
StubPtr = UT_GetStubEntry(FuncKey, UT_ENTRYTYPE_OVERRIDE_STUB);

/* If NULL, then this is the first set, set a UT_ENTRYTYPE_OVERRIDE_STUB */
if (StubPtr == NULL)
{
StubPtr = UT_GetStubEntry(FuncKey, UT_ENTRYTYPE_UNUSED);

StubPtr->FuncKey = FuncKey;
StubPtr->EntryType = UT_ENTRYTYPE_OVERRIDE_STUB;
}

}

void UT_ResetState(UT_EntryKey_t FuncKey)
{
UT_StubTableEntry_t *StubPtr;
Expand Down Expand Up @@ -602,6 +621,13 @@ void UT_SetHookFunction(UT_EntryKey_t FuncKey, UT_HookFunc_t HookFunc, void *Use
UT_DoSetHookFunction(FuncKey, Value, UserObj, false);
}

void UT_SetHookOverrideStubFunction(UT_EntryKey_t FuncKey, UT_HookFunc_t HookFunc, void *UserObj)
{
UT_DoSetOverride(FuncKey);

UT_SetHookFunction(FuncKey, HookFunc, UserObj);
}

void UT_SetVaHookFunction(UT_EntryKey_t FuncKey, UT_VaHookFunc_t HookFunc, void *UserObj)
{
UT_HookFuncPtr_t Value;
Expand All @@ -611,6 +637,13 @@ void UT_SetVaHookFunction(UT_EntryKey_t FuncKey, UT_VaHookFunc_t HookFunc, void
UT_DoSetHookFunction(FuncKey, Value, UserObj, true);
}

void UT_SetVaHookOverrideStubFunction(UT_EntryKey_t FuncKey, UT_VaHookFunc_t HookFunc, void *UserObj)
{
UT_DoSetOverride(FuncKey);

UT_SetVaHookFunction(FuncKey, HookFunc, UserObj);
}

const void *UT_Hook_GetArgPtr(const UT_StubContext_t *ContextPtr, const char *Name, size_t ExpectedTypeSize)
{
uint32 i;
Expand Down Expand Up @@ -853,3 +886,14 @@ int32 UT_DefaultStubImpl(const char *FunctionName, UT_EntryKey_t FuncKey, int32

return Retcode;
}

bool UT_StubIsOverridden(UT_EntryKey_t FuncKey)
{
UT_StubTableEntry_t *StubPtr;

/* get override status */
StubPtr = UT_GetStubEntry(FuncKey, UT_ENTRYTYPE_OVERRIDE_STUB);

/* StubPtr will be NULL when override is not set */
return (StubPtr != NULL);
}

0 comments on commit 81b167c

Please sign in to comment.