void apply_any_constraints(RecordedExpectation *expectation, const char *parameter, intptr_t actual) { int i; for (i = 0; i < cgreen_vector_size(expectation->constraints); i++) { Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, i); if (is_constraint_parameter(constraint, parameter)) { switch(constraint->constraint_type) { case CG_CONSTRAINT_WANT: test_constraint( constraint, expectation->function, actual, expectation->test_file, expectation->test_line, get_test_reporter()); break; case CG_CONSTRAINT_SET: *((int *)actual) = (int)constraint->out_value; break; case CG_CONSTRAINT_FILL: memcpy((void *)actual, (void *)constraint->out_value, constraint->copy_size); break; } } } }
void add_tests_(TestSuite *suite, const char *names, ...) { CgreenVector *test_names = create_vector_of_names(names); int i; va_list tests; va_start(tests, names); for (i = 0; i < cgreen_vector_size(test_names); i++) { add_test_(suite, (char *)(cgreen_vector_get(test_names, i)), va_arg(tests, CgreenTest *)); } va_end(tests); destroy_cgreen_vector(test_names); }
static CgreenVector *create_equal_value_constraints_for(CgreenVector *parameter_names, CgreenVector *actual_values) { int i; CgreenVector *constraints = create_constraints_vector(); for (i = 0; i < cgreen_vector_size(parameter_names); i++) { const char* parameter_name = (const char*)cgreen_vector_get(parameter_names, i); uintptr_t actual = (uintptr_t)cgreen_vector_get(actual_values, i); Constraint *constraint = create_equal_to_value_constraint((intptr_t)actual, parameter_name); cgreen_vector_add(constraints, constraint); } return constraints; }
intptr_t stored_result_or_default_for(CgreenVector* constraints) { int i; for (i = 0; i < cgreen_vector_size(constraints); i++) { Constraint *constraint = (Constraint *)cgreen_vector_get(constraints, i); if (constraint->type == RETURN_VALUE) { return constraint->expected_value; } } return 0; }
RecordedExpectation *find_expectation(const char *function) { int i; for (i = 0; i < cgreen_vector_size(global_expectation_queue); i++) { RecordedExpectation *expectation = (RecordedExpectation *)cgreen_vector_get(global_expectation_queue, i); if (strcmp(expectation->function, function) == 0) { return expectation; } } return NULL; }
static bool successfully_mocked_call(const char *function_name) { int i; for (i = 0; i < cgreen_vector_size(successfully_mocked_calls); i++) { const char *successfully_mocked_function_name = (const char *)cgreen_vector_get(successfully_mocked_calls, i); if (strcmp(successfully_mocked_function_name, function_name) == 0) { return true; } } return false; }
int number_of_parameter_constraints_in(const CgreenVector* constraints) { int i, parameters = 0; for (i = 0; i < cgreen_vector_size(constraints); i++) { Constraint *constraint = (Constraint *)cgreen_vector_get(constraints, i); if (is_comparing(constraint)) { parameters++; } } return parameters; }
void print_learned_mocks(void) { int e, c; CgreenBreadcrumb *breadcrumb = get_test_reporter()->breadcrumb; printf("%s: learned mocks:\n", get_current_from_breadcrumb(breadcrumb)); if (cgreen_vector_size(learned_mock_calls) == 0) { printf("\t<none>\n"); return; } for (e = 0; e < cgreen_vector_size(learned_mock_calls); e++) { RecordedExpectation *expectation = (RecordedExpectation*)cgreen_vector_get(learned_mock_calls, e); const char *function_name = expectation->function; printf("\texpect(%s", function_name); for (c = 0; c < cgreen_vector_size(expectation->constraints); c++) { Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, c); printf(", when(%s, is_equal_to(%" PRIdPTR "))", constraint->expected_value_name, constraint->expected_value); } printf(");\n"); } }
RecordedResult *find_result(const char *function) { int i; for (i = 0; i < cgreen_vector_size(result_queue); i++) { RecordedResult *result = (RecordedResult *)cgreen_vector_get(result_queue, i); if (strcmp(result->function, function) == 0) { if (! result->should_keep) { return (RecordedResult *) cgreen_vector_remove(result_queue, i); } return result; } } return NULL; }
RecordedExpectation *find_expectation(const char *function) { int i; for (i = 0; i < cgreen_vector_size(expectation_queue); i++) { RecordedExpectation *expectation = (RecordedExpectation *)cgreen_vector_get(expectation_queue, i); if (strcmp(expectation->function, function) == 0) { if (! expectation->should_keep) { return (RecordedExpectation *) cgreen_vector_remove(expectation_queue, i); } return expectation; } } return NULL; }
bool have_never_call_expectation_for(const char* function) { int i; for (i = 0; i < cgreen_vector_size(global_expectation_queue); i++) { RecordedExpectation *expectation = (RecordedExpectation *)cgreen_vector_get(global_expectation_queue, i); if (strcmp(expectation->function, function) == 0) { if (is_never_call(expectation)) { return true; } } } return false; }
static void unwanted_check(const char *function) { int i; for (i = 0; i < cgreen_vector_size(unwanted_calls); i++) { UnwantedCall *unwanted = (UnwantedCall *) cgreen_vector_get(unwanted_calls, i); if (strcmp(unwanted->function, function) == 0) { (*get_test_reporter()->assert_true)( get_test_reporter(), unwanted->test_file, unwanted->test_line, 0, "Unexpected call to function [%s]", function); } } }
void trigger_unfulfilled_expectations(CgreenVector *expect_queue, TestReporter *reporter) { int i; for (i = 0; i < cgreen_vector_size(expectation_queue); i++) { RecordedExpectation *expectation = cgreen_vector_get(expect_queue, i); if (! expectation->should_keep) { (*reporter->assert_true)( reporter, expectation->test_file, expectation->test_line, 0, "Call was not made to function [%s]", expectation->function); } } }
int mock_enabled_(const char *function) { int i; if (all_mocks_disabled) { // Mocks disabled by default, check for any that are enabled for (i = 0; i < cgreen_vector_size(enabled_mocks); i++) { char *enabled_mock = (char *)cgreen_vector_get(enabled_mocks, i); if (strcmp(enabled_mock, function) == 0) { return 1; } } return 0; } else { // Mocks enabled by default, check for any that are disabled for (i = 0; i < cgreen_vector_size(disabled_mocks); i++) { char *disabled_mock = (char *)cgreen_vector_get(disabled_mocks, i); if (strcmp(disabled_mock, function) == 0) { return 0; } } return 1; } // Should never reach here return 1; }
void remove_expectation_for(const char *function) { int i; for (i = 0; i < cgreen_vector_size(global_expectation_queue); i++) { RecordedExpectation *expectation = (RecordedExpectation *)cgreen_vector_get(global_expectation_queue, i); if (NULL == expectation) { printf("*** CGREEN: NULL expectation found -- maybe a previous incorrect removal?"); continue; } if (strcmp(expectation->function, function) == 0) { cgreen_vector_remove(global_expectation_queue, i); return; } } }
void clear_mocks() { if (global_expectation_queue != NULL) { destroy_cgreen_vector(global_expectation_queue); global_expectation_queue = NULL; } if (learned_mock_calls != NULL) { int i; for (i = 0; i < cgreen_vector_size(learned_mock_calls); i++) { RecordedExpectation *expectation = (RecordedExpectation*)cgreen_vector_get(learned_mock_calls, i); destroy_expectation(expectation); } destroy_cgreen_vector(learned_mock_calls); learned_mock_calls = NULL; } }
bool constraint_is_for_parameter_in(const Constraint *constraint, const char *names) { int i; bool found = false; CgreenVector *parameter_names = create_vector_of_names(names); if (!is_parameter(constraint)) return false; for (i = 0; i < cgreen_vector_size(parameter_names); i++) { const char *mock_parameter_name = (const char *)cgreen_vector_get(parameter_names, i); if (constraint_is_for_parameter(constraint, mock_parameter_name)) { found = true; break; } } destroy_cgreen_vector(parameter_names); return found; }
intptr_t mock_(const char *function, const char *parameters, ...) { RecordedExpectation *expectation = NULL; unwanted_check(function); expectation = find_expectation(function); if (expectation != NULL) { CgreenVector *names = create_vector_of_names(parameters); int i; va_list actual; va_start(actual, parameters); for (i = 0; i < cgreen_vector_size(names); i++) { apply_any_constraints(expectation, (const char *)cgreen_vector_get(names, i), va_arg(actual, intptr_t)); } va_end(actual); destroy_cgreen_vector(names); if (! expectation->should_keep) { destroy_expectation(expectation); } } return stubbed_result(function); }
void trigger_unfulfilled_expectations(CgreenVector *expectation_queue, TestReporter *reporter) { int i; for (i = 0; i < cgreen_vector_size(expectation_queue); i++) { RecordedExpectation *expectation = (RecordedExpectation *)cgreen_vector_get(expectation_queue, i); if (NULL == expectation) { fprintf(stderr, "*** NULL unfulfilled cgreen expectation found -- maybe a previous incorrect removal?"); continue; } if (is_always_call(expectation) || is_never_call(expectation)) { continue; } (*reporter->assert_true)( reporter, expectation->test_file, expectation->test_line, 0, "Expected call was not made to mocked function [%s]", expectation->function); } }
void apply_any_content_setting_parameter_constraints(RecordedExpectation *expectation, const char *parameter, intptr_t actual, TestReporter* test_reporter) { int i; for (i = 0; i < cgreen_vector_size(expectation->constraints); i++) { Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, i); if (constraint_is_not_for_parameter(constraint, parameter)) { continue; } if (constraint->type != CONTENT_SETTER) { continue; } constraint->execute( constraint, expectation->function, actual, expectation->test_file, expectation->test_line, test_reporter); } }
intptr_t mock_(TestReporter* test_reporter, const char *function, const char *mock_file, int mock_line, const char *parameters, ...) { va_list actuals; CgreenVector *actual_values; CgreenVector *parameter_names; int failures_before_read_only_constraints_executed; int failures_after_read_only_constraints_executed; int i; intptr_t stored_result; RecordedExpectation *expectation = find_expectation(function); va_start(actuals, parameters); actual_values = create_vector_of_actuals(actuals, number_of_parameters_in(parameters)); va_end(actuals); parameter_names = create_vector_of_names(parameters); if (expectation == NULL) { handle_missing_expectation_for(function, mock_file, mock_line, parameter_names, actual_values, test_reporter); destroy_cgreen_vector(actual_values); destroy_cgreen_vector(parameter_names); return 0; } if (is_never_call(expectation)) { report_violated_never_call(test_reporter, expectation); destroy_cgreen_vector(actual_values); destroy_cgreen_vector(parameter_names); return 0; } ensure_successfully_mocked_calls_list_exists(); cgreen_vector_add(successfully_mocked_calls, (void*)function); stored_result = stored_result_or_default_for(expectation->constraints); for (i = 0; i < cgreen_vector_size(expectation->constraints); i++) { Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, i); if (!is_parameter(constraint)) continue; if (!constraint_is_for_parameter_in(constraint, parameters)) { // if expectation parameter name isn't in parameter_names, // fail test and skip applying constraints unlikely to match report_mock_parameter_name_not_found(test_reporter, expectation, constraint->parameter_name); destroy_expectation_if_time_to_die(expectation); destroy_cgreen_vector(actual_values); destroy_cgreen_vector(parameter_names); return stored_result; } } // if read-only constraints aren't matching, content-setting ones might corrupt memory // apply read-only ones first, and if they don't fail, then do the deeper constraints failures_before_read_only_constraints_executed = test_reporter->failures; for (i = 0; i < cgreen_vector_size(parameter_names); i++) { const char* parameter_name = (const char*)cgreen_vector_get(parameter_names, i); uintptr_t actual = (uintptr_t)cgreen_vector_get(actual_values, i); apply_any_read_only_parameter_constraints(expectation, parameter_name, actual, test_reporter); } failures_after_read_only_constraints_executed = test_reporter->failures; // FIXME: this comparison doesn't work because only parent processes' pass/fail counts are updated, // and even then only once they read from the pipe if (failures_before_read_only_constraints_executed == failures_after_read_only_constraints_executed) { for (i = 0; i < cgreen_vector_size(parameter_names); i++) { const char* parameter_name = (const char*)cgreen_vector_get(parameter_names, i); uintptr_t actual = (uintptr_t)cgreen_vector_get(actual_values, i); apply_any_content_setting_parameter_constraints(expectation, parameter_name, actual, test_reporter); } } destroy_cgreen_vector(parameter_names); destroy_cgreen_vector(actual_values); destroy_expectation_if_time_to_die(expectation); return stored_result; }