int64_t mock_return_from_call()

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;
}