Back to home page

Enduro/X

 
 

    


0001 #include <assert.h>
0002 #include <cgreen/breadcrumb.h>
0003 #include <cgreen/mocks.h>
0004 #include <cgreen/parameters.h>
0005 #include <inttypes.h>
0006 /* TODO: report PC-Lint bug about undeserved 451*/
0007 #include <stdarg.h>
0008 #include <stdio.h>
0009 #include <stdlib.h>
0010 #include <string.h>
0011 
0012 #ifdef __cplusplus
0013 namespace cgreen {
0014 #endif
0015 
0016 typedef struct RecordedExpectation_ {
0017     const char *function;
0018     const char *test_file;
0019     int test_line;
0020     int time_to_live;
0021     CgreenVector *constraints;
0022 } RecordedExpectation;
0023 
0024 const int UNLIMITED_TIME_TO_LIVE = 0x0f314159;
0025 static CgreenMockMode cgreen_mocks_are_ = strict_mocks;
0026 static CgreenVector *learned_mock_calls = NULL;
0027 static CgreenVector *successfully_mocked_calls = NULL;
0028 static CgreenVector *global_expectation_queue = NULL;
0029 
0030 static CgreenVector *create_vector_of_actuals(va_list actuals, int count);
0031 static CgreenVector *create_equal_value_constraints_for(CgreenVector *parameter_names, CgreenVector *actual_values);
0032 static CgreenVector *create_constraints_vector(void);
0033 static RecordedExpectation *create_recorded_expectation(const char *function, const char *test_file, int test_line, CgreenVector *constraints);
0034 static CgreenVector *constraints_vector_from_va_list(va_list constraints);
0035 static void destroy_expectation(RecordedExpectation *expectation);
0036 static void ensure_expectation_queue_exists(void);
0037 static void ensure_learned_mock_calls_list_exists(void);
0038 static void ensure_successfully_mocked_calls_list_exists(void);
0039 void remove_expectation_for(const char *function);
0040 void trigger_unfulfilled_expectations(CgreenVector *expectation_queue, TestReporter *reporter);
0041 RecordedExpectation *find_expectation(const char *function);
0042 void apply_any_read_only_parameter_constraints(RecordedExpectation *expectation, const char *parameter, intptr_t actual, TestReporter* test_reporter);
0043 void apply_any_content_setting_parameter_constraints(RecordedExpectation *expectation, const char *parameter, intptr_t actual, TestReporter* test_reporter);
0044 intptr_t stored_result_or_default_for(CgreenVector* constraints);
0045 int number_of_parameter_constraints_in(const CgreenVector* constraints);
0046 static int number_of_parameters_in(const char *parameter_list);
0047 bool is_always_call(RecordedExpectation* expectation);
0048 bool have_always_expectation_for(const char* function);
0049 
0050 bool is_never_call(RecordedExpectation* expectation);
0051 bool have_never_call_expectation_for(const char* function);
0052 
0053 void report_violated_never_call(TestReporter*, RecordedExpectation*);
0054 void report_unexpected_call(TestReporter*, RecordedExpectation*);
0055 void report_mock_parameter_name_not_found(TestReporter *test_reporter, RecordedExpectation *expectation, const char *parameter);
0056 void destroy_expectation_if_time_to_die(RecordedExpectation *expectation);
0057 
0058 void cgreen_mocks_are(CgreenMockMode mock_mode) {
0059     cgreen_mocks_are_ = mock_mode;
0060 }
0061 
0062 static int number_of_parameters_in(const char *parameter_list) {
0063     int count = 1;
0064     const char *current = parameter_list;
0065     
0066     if (strlen(parameter_list) == 0) return 0;
0067 
0068     while (*current != '\0') {
0069         if (*current == ',') count++;
0070         current++;
0071     }
0072 
0073     return count;
0074 }
0075 
0076 int number_of_parameter_constraints_in(const CgreenVector* constraints) {
0077     int i, parameters = 0;
0078 
0079     for (i = 0; i < cgreen_vector_size(constraints); i++) {
0080         Constraint *constraint = (Constraint *)cgreen_vector_get(constraints, i);
0081 
0082         if (is_comparing(constraint)) {
0083            parameters++; 
0084         }
0085     }
0086 
0087     return parameters;
0088 }
0089 
0090 void learn_mock_call_for(const char *function, const char *mock_file, int mock_line, CgreenVector *parameter_names, CgreenVector *actual_values) {
0091     CgreenVector *constraints = create_equal_value_constraints_for(parameter_names, actual_values);
0092 
0093     RecordedExpectation *expectation = create_recorded_expectation(function, mock_file, mock_line, constraints);
0094     ensure_learned_mock_calls_list_exists();
0095     cgreen_vector_add(learned_mock_calls, (void*)expectation);
0096 }
0097 
0098 void handle_missing_expectation_for(const char *function, const char *mock_file, int mock_line, CgreenVector *parameter_names, CgreenVector *actual_values, TestReporter *test_reporter) {
0099     RecordedExpectation *expectation;
0100     CgreenVector *no_constraints;
0101 
0102     switch (cgreen_mocks_are_) {
0103     case loose_mocks:
0104         break;
0105 
0106     case learning_mocks:
0107         learn_mock_call_for(function, mock_file, mock_line, parameter_names, actual_values);
0108         break;
0109 
0110     case strict_mocks:
0111         no_constraints = create_constraints_vector();
0112         expectation = create_recorded_expectation(function, mock_file, mock_line, no_constraints);
0113         report_unexpected_call(test_reporter, expectation);
0114 
0115         destroy_expectation(expectation);
0116         break;
0117     }
0118 }
0119 
0120 intptr_t mock_(TestReporter* test_reporter, const char *function, const char *mock_file, int mock_line, const char *parameters, ...) {
0121     va_list actuals;
0122     CgreenVector *actual_values;
0123     CgreenVector *parameter_names;
0124     int failures_before_read_only_constraints_executed;
0125     int failures_after_read_only_constraints_executed;
0126     int i;
0127     intptr_t stored_result;
0128     RecordedExpectation *expectation = find_expectation(function);
0129 
0130     va_start(actuals, parameters);
0131     actual_values = create_vector_of_actuals(actuals, number_of_parameters_in(parameters));
0132     va_end(actuals);
0133     parameter_names = create_vector_of_names(parameters);
0134 
0135     if (expectation == NULL) {
0136         handle_missing_expectation_for(function, mock_file, mock_line, parameter_names, actual_values, test_reporter);
0137         destroy_cgreen_vector(actual_values);
0138         destroy_cgreen_vector(parameter_names);
0139         return 0;
0140     }
0141 
0142     if (is_never_call(expectation)) {
0143         report_violated_never_call(test_reporter, expectation);
0144         destroy_cgreen_vector(actual_values);
0145         destroy_cgreen_vector(parameter_names);
0146         return 0;
0147     }
0148 
0149     ensure_successfully_mocked_calls_list_exists();
0150     cgreen_vector_add(successfully_mocked_calls, (void*)function);
0151 
0152     stored_result = stored_result_or_default_for(expectation->constraints);
0153 
0154     for (i = 0; i < cgreen_vector_size(expectation->constraints); i++) {
0155         Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, i);
0156 
0157         if (!is_parameter(constraint)) continue;
0158 
0159         if (!constraint_is_for_parameter_in(constraint, parameters)) {
0160             /* if expectation parameter name isn't in parameter_names,
0161              * fail test and skip applying constraints unlikely to match
0162              */
0163             report_mock_parameter_name_not_found(test_reporter, expectation, constraint->parameter_name);
0164             destroy_expectation_if_time_to_die(expectation);
0165             destroy_cgreen_vector(actual_values);
0166             destroy_cgreen_vector(parameter_names);
0167 
0168             return stored_result;
0169         }
0170     }
0171 
0172     /* if read-only constraints aren't matching, content-setting ones might corrupt memory
0173      * apply read-only ones first, and if they don't fail, then do the deeper constraints
0174      */
0175     failures_before_read_only_constraints_executed = test_reporter->failures;
0176 
0177     for (i = 0; i < cgreen_vector_size(parameter_names); i++) {
0178         const char* parameter_name = (const char*)cgreen_vector_get(parameter_names, i);
0179         uintptr_t actual = (uintptr_t)cgreen_vector_get(actual_values, i);
0180         apply_any_read_only_parameter_constraints(expectation, parameter_name, actual, test_reporter);
0181     }
0182 
0183     failures_after_read_only_constraints_executed = test_reporter->failures;
0184 
0185     /* FIXME: this comparison doesn't work because only parent processes' pass/fail counts are updated,
0186             and even then only once they read from the pipe
0187      */
0188     if (failures_before_read_only_constraints_executed == failures_after_read_only_constraints_executed) {
0189         for (i = 0; i < cgreen_vector_size(parameter_names); i++) {
0190             const char* parameter_name = (const char*)cgreen_vector_get(parameter_names, i);
0191             uintptr_t actual = (uintptr_t)cgreen_vector_get(actual_values, i);
0192             apply_any_content_setting_parameter_constraints(expectation, parameter_name, actual, test_reporter);
0193         }
0194     }
0195 
0196     destroy_cgreen_vector(parameter_names);
0197     destroy_cgreen_vector(actual_values);
0198 
0199     destroy_expectation_if_time_to_die(expectation);
0200 
0201     return stored_result;
0202 }
0203 
0204 
0205 static CgreenVector *create_vector_of_actuals(va_list actuals, int count) {
0206     int i;
0207     CgreenVector *actual_values = create_cgreen_vector(NULL);
0208     for (i = 0; i < count; i++) {
0209         uintptr_t actual = va_arg(actuals, uintptr_t);
0210         cgreen_vector_add(actual_values, (void*)actual);
0211     }
0212     return actual_values;
0213 }
0214 
0215 
0216 static CgreenVector *create_equal_value_constraints_for(CgreenVector *parameter_names, CgreenVector *actual_values) {
0217     int i;
0218     CgreenVector *constraints = create_constraints_vector();
0219     for (i = 0; i < cgreen_vector_size(parameter_names); i++) {
0220         const char* parameter_name = (const char*)cgreen_vector_get(parameter_names, i);
0221         uintptr_t actual = (uintptr_t)cgreen_vector_get(actual_values, i);
0222         Constraint *constraint = create_equal_to_value_constraint((intptr_t)actual, parameter_name);
0223         cgreen_vector_add(constraints, constraint);
0224     }
0225     return constraints;
0226 }
0227 
0228 
0229 Constraint *when_(const char *parameter, Constraint* constraint) {
0230     constraint->parameter_name = parameter;
0231     return constraint;
0232 }
0233 
0234 void destroy_expectation_if_time_to_die(RecordedExpectation *expectation) {
0235 
0236     if (is_always_call(expectation)) {
0237         return;
0238     }
0239 
0240     /* TODO: expectation->decrement_time_to_live_if_necessary(); if (expectation->time_to_die()) { ... } */
0241     expectation->time_to_live--;
0242 
0243     if (expectation->time_to_live <= 0) {
0244         remove_expectation_for(expectation->function);
0245         destroy_expectation(expectation);
0246     }
0247 }
0248 
0249 void expect_(TestReporter* test_reporter, const char *function, const char *test_file, int test_line, ...) {
0250     va_list constraints;
0251     RecordedExpectation *expectation;
0252     CgreenVector *constraints_vector;
0253 
0254     if (have_always_expectation_for(function)) {
0255         test_reporter->assert_true(
0256                 test_reporter,
0257                 test_file,
0258                 test_line,
0259                 false,
0260                 "Mocked function [%s] already has an expectation that it will always be called a certain way; "
0261                 "any expectations declared after an always expectation are invalid", function);
0262         va_start(constraints, test_line);
0263         destroy_constraints(constraints);
0264         va_end(constraints);
0265 
0266         return;
0267     }
0268 
0269     if (have_never_call_expectation_for(function)) {
0270         test_reporter->assert_true(
0271                 test_reporter,
0272                 test_file,
0273                 test_line,
0274                 false,
0275                 "Mocked function [%s] already has an expectation that it will never be called; "
0276                 "any expectations declared after a never call expectation are invalid", function);
0277         va_start(constraints, test_line);
0278         destroy_constraints(constraints);
0279         va_end(constraints);
0280 
0281         return;
0282     }
0283 
0284 
0285     va_start(constraints, test_line);
0286     constraints_vector = constraints_vector_from_va_list(constraints);
0287     expectation = create_recorded_expectation(function, test_file, test_line, constraints_vector);
0288     va_end(constraints);
0289     expectation->time_to_live = 1;
0290     cgreen_vector_add(global_expectation_queue, expectation);
0291 }
0292 
0293 void always_expect_(TestReporter* test_reporter, const char *function, const char *test_file, int test_line, ...) {
0294     va_list constraints;
0295     RecordedExpectation *expectation;
0296     CgreenVector *constraints_vector;
0297 
0298     if (have_always_expectation_for(function)) {
0299         test_reporter->assert_true(
0300                 test_reporter,
0301                 test_file,
0302                 test_line,
0303                 false,
0304                 "Mocked function [%s] already has an expectation and will always be called a certain way; "
0305                 "any expectations declared after an always expectation are discarded", function);
0306         va_start(constraints, test_line);
0307         destroy_constraints(constraints);
0308         va_end(constraints);
0309 
0310         return;
0311     }
0312 
0313     if (have_never_call_expectation_for(function)) {
0314         test_reporter->assert_true(
0315                 test_reporter,
0316                 test_file,
0317                 test_line,
0318                 false,
0319                 "Mocked function [%s] already has an expectation that it will never be called; "
0320                 "any expectations declared after a never call expectation are discarded", function);
0321         va_start(constraints, test_line);
0322         destroy_constraints(constraints);
0323         va_end(constraints);
0324 
0325         return;
0326     }
0327 
0328     va_start(constraints, test_line);
0329     constraints_vector = constraints_vector_from_va_list(constraints);
0330     expectation = create_recorded_expectation(function, test_file, test_line, constraints_vector);
0331     va_end(constraints);
0332     expectation->time_to_live = UNLIMITED_TIME_TO_LIVE;
0333     cgreen_vector_add(global_expectation_queue, expectation);
0334 }
0335 
0336 void never_expect_(TestReporter* test_reporter, const char *function, const char *test_file, int test_line, ...) {
0337     va_list constraints;
0338     RecordedExpectation *expectation;
0339     CgreenVector *constraints_vector;
0340 
0341     if (have_always_expectation_for(function)) {
0342         test_reporter->assert_true(
0343                 test_reporter,
0344                 test_file,
0345                 test_line,
0346                 false,
0347                 "Mocked function [%s] already has an expectation and will always be called a certain way; "
0348                 "declaring an expectation after an always expectation is not allowed", function);
0349         va_start(constraints, test_line);
0350         destroy_constraints(constraints);
0351         va_end(constraints);
0352 
0353         return;
0354     }
0355 
0356     if (have_never_call_expectation_for(function)) {
0357         test_reporter->assert_true(
0358                 test_reporter,
0359                 test_file,
0360                 test_line,
0361                 false,
0362                 "Mocked function [%s] already has an expectation that it will never be called; "
0363                 "declaring an expectation for a function after a never call expectation is not allowed", function);
0364         va_start(constraints, test_line);
0365         destroy_constraints(constraints);
0366         va_end(constraints);
0367 
0368         return;
0369     }
0370 
0371     va_start(constraints, test_line);
0372     constraints_vector = constraints_vector_from_va_list(constraints);
0373     expectation = create_recorded_expectation(function, test_file, test_line, constraints_vector);
0374     expectation->time_to_live = -UNLIMITED_TIME_TO_LIVE;
0375     cgreen_vector_add(global_expectation_queue, expectation);
0376 }
0377 
0378 
0379 void report_violated_never_call(TestReporter *test_reporter, RecordedExpectation* expectation) {
0380     test_reporter->assert_true(
0381             test_reporter,
0382             expectation->test_file,
0383             expectation->test_line,
0384             false,
0385             "Mocked function [%s] has an expectation that it will never be called, but it was",
0386             expectation->function);
0387 }
0388 
0389 
0390 static bool successfully_mocked_call(const char *function_name) {
0391     int i;
0392 
0393     for (i = 0; i < cgreen_vector_size(successfully_mocked_calls); i++) {
0394         const char *successfully_mocked_function_name = (const char *)cgreen_vector_get(successfully_mocked_calls, i);
0395         if (strcmp(successfully_mocked_function_name, function_name) == 0) {
0396             return true;
0397         }
0398     }
0399 
0400     return false;
0401 }
0402 
0403 
0404 void report_unexpected_call(TestReporter *test_reporter, RecordedExpectation* expectation) {
0405     const char *message;
0406     if (successfully_mocked_call(expectation->function)) {
0407        message = "Mocked function [%s] was called too many times";
0408     } else {
0409        message = "Mocked function [%s] did not have an expectation that it would be called";
0410     }
0411 
0412     test_reporter->assert_true(
0413         test_reporter,
0414         expectation->test_file,
0415         expectation->test_line,
0416         false,
0417         message,
0418         expectation->function);
0419 }
0420 
0421 void clear_mocks(void) {
0422     if (global_expectation_queue != NULL) {
0423         destroy_cgreen_vector(global_expectation_queue);
0424         global_expectation_queue = NULL;
0425     }
0426 
0427     if (learned_mock_calls != NULL) {
0428         int i;
0429         for (i = 0; i < cgreen_vector_size(learned_mock_calls); i++) {
0430             RecordedExpectation *expectation = (RecordedExpectation*)cgreen_vector_get(learned_mock_calls, i);
0431             destroy_expectation(expectation);
0432         }
0433 
0434         destroy_cgreen_vector(learned_mock_calls);
0435         learned_mock_calls = NULL;
0436     }
0437 }
0438 
0439 void print_learned_mocks(void) {
0440     int e, c;
0441     CgreenBreadcrumb *breadcrumb = get_test_reporter()->breadcrumb;
0442     printf("%s: learned mocks:\n",
0443            get_current_from_breadcrumb(breadcrumb));
0444 
0445     if (cgreen_vector_size(learned_mock_calls) == 0) {
0446         printf("\t<none>\n");
0447         return;
0448     }
0449 
0450     for (e = 0; e < cgreen_vector_size(learned_mock_calls); e++) {
0451         RecordedExpectation *expectation = (RecordedExpectation*)cgreen_vector_get(learned_mock_calls, e);
0452         const char *function_name = expectation->function;
0453         printf("\texpect(%s", function_name);
0454         for (c = 0; c < cgreen_vector_size(expectation->constraints); c++) {
0455             Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, c);
0456             printf(", when(%s, is_equal_to(%" PRIdPTR "))", constraint->expected_value_name, constraint->expected_value);
0457         }
0458         printf(");\n");
0459     }
0460 }
0461 
0462 void tally_mocks(TestReporter *reporter) {
0463     if (cgreen_mocks_are_ == learning_mocks) {
0464         print_learned_mocks();
0465     }
0466 
0467     trigger_unfulfilled_expectations(global_expectation_queue, reporter);
0468     clear_mocks();
0469 }
0470 
0471 
0472 static CgreenVector *create_constraints_vector(void) {
0473     return create_cgreen_vector((GenericDestructor)&destroy_constraint);
0474 }
0475 
0476 
0477 static CgreenVector *constraints_vector_from_va_list(va_list constraints) {
0478     CgreenVector *vector = create_constraints_vector();
0479     Constraint *constraint;
0480     while ((constraint = va_arg(constraints, Constraint *)) != (Constraint *)0) {
0481         cgreen_vector_add(vector, constraint);
0482     }
0483     return vector;
0484 }
0485 
0486 
0487 static RecordedExpectation *create_recorded_expectation(const char *function, const char *test_file, int test_line, CgreenVector *constraints) {
0488     RecordedExpectation *expectation;
0489 
0490     ensure_expectation_queue_exists();
0491     expectation = (RecordedExpectation *)malloc(sizeof(RecordedExpectation));
0492     expectation->function = function;
0493     expectation->test_file = test_file;
0494     expectation->test_line = test_line;
0495     expectation->constraints = constraints;
0496 
0497     return expectation;
0498 }
0499 
0500 static void destroy_expectation(RecordedExpectation *expectation) {
0501     destroy_cgreen_vector(expectation->constraints);
0502     expectation->constraints = NULL;
0503     expectation->function = NULL;
0504     expectation->test_file = NULL;
0505     expectation->test_line = 0;
0506     expectation->time_to_live = 0;
0507 
0508     free(expectation);
0509 }
0510 
0511 static void ensure_successfully_mocked_calls_list_exists(void) {
0512     if (successfully_mocked_calls == NULL) {
0513         /* successfully_mocked_calls are __func__, so there's nothing to destroy */
0514         successfully_mocked_calls = create_cgreen_vector(NULL);
0515     }
0516 }
0517 
0518 static void ensure_learned_mock_calls_list_exists(void) {
0519     if (learned_mock_calls == NULL) {
0520         /* learned_mock_calls are __func__, so there's nothing to destroy */
0521         learned_mock_calls = create_cgreen_vector(NULL);
0522     }
0523 }
0524 
0525 static void ensure_expectation_queue_exists(void) {
0526     if (global_expectation_queue == NULL) {
0527         global_expectation_queue = create_cgreen_vector((GenericDestructor)&destroy_expectation);
0528     }
0529 }
0530 
0531 void remove_expectation_for(const char *function) {
0532     int i;
0533     for (i = 0; i < cgreen_vector_size(global_expectation_queue); i++) {
0534         RecordedExpectation *expectation = (RecordedExpectation *)cgreen_vector_get(global_expectation_queue, i);
0535 
0536         if (NULL == expectation) {
0537             printf("*** CGREEN: NULL expectation found -- maybe a previous incorrect removal?");
0538             continue;
0539         }
0540 
0541         if (strcmp(expectation->function, function) == 0) {
0542             cgreen_vector_remove(global_expectation_queue, i);
0543             return;
0544         }
0545     }
0546 }
0547 
0548 void trigger_unfulfilled_expectations(CgreenVector *expectation_queue, TestReporter *reporter) {
0549     int i;
0550     for (i = 0; i < cgreen_vector_size(expectation_queue); i++) {
0551         RecordedExpectation *expectation = (RecordedExpectation *)cgreen_vector_get(expectation_queue, i);
0552 
0553         if (NULL == expectation) {
0554             fprintf(stderr, "*** NULL unfulfilled cgreen expectation found -- maybe a previous incorrect removal?");
0555             continue;
0556         }
0557 
0558         if (is_always_call(expectation) || is_never_call(expectation)) {
0559             continue;
0560         }
0561 
0562         (*reporter->assert_true)(
0563                 reporter,
0564                 expectation->test_file,
0565                 expectation->test_line,
0566                 0,
0567                 "Expected call was not made to mocked function [%s]", expectation->function);
0568     }
0569 }
0570 
0571 RecordedExpectation *find_expectation(const char *function) {
0572     int i;
0573     for (i = 0; i < cgreen_vector_size(global_expectation_queue); i++) {
0574         RecordedExpectation *expectation =
0575             (RecordedExpectation *)cgreen_vector_get(global_expectation_queue, i);
0576 
0577         if (strcmp(expectation->function, function) == 0) {
0578             return expectation;
0579         }
0580     }
0581     return NULL;
0582 }
0583 
0584 void report_mock_parameter_name_not_found(TestReporter *test_reporter, RecordedExpectation *expectation, const char *constraint_parameter_name) {
0585 
0586     test_reporter->assert_true(
0587         test_reporter,
0588         expectation->test_file,
0589         expectation->test_line,
0590         false,
0591         "Mocked function [%s] did not define a parameter named [%s]. Did you misspell it in the expectation or forget it in the mock's argument list?",
0592         expectation->function,
0593         constraint_parameter_name);
0594 }
0595 
0596 void apply_any_read_only_parameter_constraints(RecordedExpectation *expectation, const char *parameter, intptr_t actual, TestReporter* test_reporter) {
0597     int i;
0598 
0599     for (i = 0; i < cgreen_vector_size(expectation->constraints); i++) {
0600         Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, i);
0601 
0602         if (constraint_is_not_for_parameter(constraint, parameter)) {
0603             continue;
0604         }
0605 
0606         if (constraint->type == CONTENT_SETTER) {
0607             continue;
0608         }
0609 
0610         constraint->execute(
0611             constraint,
0612             expectation->function,
0613             actual,
0614             expectation->test_file,
0615             expectation->test_line,
0616             test_reporter);
0617     }
0618 }
0619 
0620 void apply_any_content_setting_parameter_constraints(RecordedExpectation *expectation, const char *parameter, intptr_t actual, TestReporter* test_reporter) {
0621     int i;
0622     for (i = 0; i < cgreen_vector_size(expectation->constraints); i++) {
0623         Constraint *constraint = (Constraint *)cgreen_vector_get(expectation->constraints, i);
0624 
0625         if (constraint_is_not_for_parameter(constraint, parameter)) {
0626             continue;
0627         }
0628 
0629         if (constraint->type != CONTENT_SETTER) {
0630             continue;
0631         }
0632 
0633         constraint->execute(
0634             constraint,
0635             expectation->function,
0636             actual,
0637             expectation->test_file,
0638             expectation->test_line,
0639             test_reporter);
0640     }
0641 }
0642 
0643 intptr_t stored_result_or_default_for(CgreenVector* constraints) {
0644     int i;
0645     for (i = 0; i < cgreen_vector_size(constraints); i++) {
0646         Constraint *constraint = (Constraint *)cgreen_vector_get(constraints, i);
0647 
0648         if (constraint->type == RETURN_VALUE) {
0649             return constraint->expected_value;
0650         }
0651     }
0652 
0653     return 0;
0654 }
0655 
0656 bool is_always_call(RecordedExpectation* expectation) {
0657     return expectation->time_to_live == UNLIMITED_TIME_TO_LIVE;
0658 }
0659 
0660 bool have_always_expectation_for(const char* function) {
0661     int i;
0662     for (i = 0; i < cgreen_vector_size(global_expectation_queue); i++) {
0663         RecordedExpectation *expectation =
0664                 (RecordedExpectation *)cgreen_vector_get(global_expectation_queue, i);
0665         if (strcmp(expectation->function, function) == 0) {
0666             if (is_always_call(expectation)) {
0667                 return true;
0668             }
0669         }
0670     }
0671 
0672     return false;
0673 }
0674 
0675 bool is_never_call(RecordedExpectation* expectation) {
0676     return expectation->time_to_live == -UNLIMITED_TIME_TO_LIVE;
0677 }
0678 
0679 bool have_never_call_expectation_for(const char* function) {
0680     int i;
0681     for (i = 0; i < cgreen_vector_size(global_expectation_queue); i++) {
0682         RecordedExpectation *expectation =
0683                 (RecordedExpectation *)cgreen_vector_get(global_expectation_queue, i);
0684         if (strcmp(expectation->function, function) == 0) {
0685             if (is_never_call(expectation)) {
0686                 return true;
0687             }
0688         }
0689     }
0690 
0691     return false;
0692 }
0693 
0694 #ifdef __cplusplus
0695 } /* namespace cgreen */
0696 #endif
0697 
0698 /* vim: set ts=4 sw=4 et cindent: */