in testing/mock.c [1072:1166]
int64_t mock_return_from_call (struct mock *mock, struct mock_call *call)
{
struct mock_call *expected;
int64_t status = 0;
int i;
size_t out_len;
int64_t value_ptr;
bool update_value;
if (call == NULL) {
return MOCK_NO_MEMORY;
}
mock_push_call (mock, call);
expected = mock->next_call;
while ((expected != NULL) && (expected->func != call->func)) {
expected = expected->next;
}
if (expected != NULL) {
/* Call any external action registered with the expectation. */
if (expected->action) {
status = expected->action (expected, call);
}
for (i = 0; i < expected->argc; i++) {
update_value = false;
/* Dereference pointer parameters. */
if ((call->argv[i].value != 0) && (expected->argv[i].flags & MOCK_ARG_FLAG_PTR_PTR)) {
value_ptr = (int64_t) ((uintptr_t) (*((int**) ((uintptr_t) call->argv[i].value))));
if ((expected->argv[i].out_data == NULL) ||
(expected->argv[i].flags & MOCK_ARG_FLAG_OUT_PTR_PTR)) {
call->argv[i].value = value_ptr;
call->argv[i].flags |= MOCK_ARG_FLAG_PTR_PTR;
}
else {
update_value = true;
}
}
/* Save the contents of a pointer parameter. */
if ((expected->argv[i].ptr_value_len != 0) && (call->argv[i].value != 0)) {
expected->argv[i].alloc (&expected->argv[i], &call->argv[i]);
call->argv[i].free = expected->argv[i].free;
}
/* Fill an output parameter with data. */
if ((expected->argv[i].out_data != NULL) && (call->argv[i].value != 0)) {
if (expected->argv[i].size_arg < 0) {
out_len = expected->argv[i].out_len;
}
else if (expected->argv[i].out_len >
(size_t) call->argv[expected->argv[i].size_arg].value) {
out_len = call->argv[expected->argv[i].size_arg].value;
}
else {
out_len = expected->argv[i].out_len;
}
expected->argv[i].copy (&expected->argv[i], &call->argv[i], out_len);
}
/* Save argument values. */
if (expected->argv[i].save_arg >= 0) {
struct mock_save_arg *save = mock_find_save_arg (mock, expected->argv[i].save_arg);
if (save && !save->saved) {
save->value = call->argv[i].value;
save->saved = true;
if (save->shared) {
save->shared->value = save->value;
save->shared->saved = true;
}
}
}
/* We are done with the argument that was passed. Store the dereferenced pointer. */
if (update_value) {
call->argv[i].value = value_ptr;
call->argv[i].flags |= MOCK_ARG_FLAG_PTR_PTR;
}
}
if (status == 0) {
status = expected->return_val;
}
mock->next_call = expected->next;
}
return status;
}