Back to home page

Enduro/X

 
 

    


0001 #include <cgreen/assertions.h>
0002 #include <cgreen/boxed_double.h>
0003 #include <cgreen/constraint.h>
0004 #include <cgreen/message_formatting.h>
0005 #include <cgreen/string_comparison.h>
0006 #include <cgreen/parameters.h>
0007 #include <cgreen/vector.h>
0008 #include <inttypes.h>
0009 #ifndef __cplusplus
0010 #include <stdbool.h>
0011 #endif
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <string.h>
0015 
0016 #ifdef _MSC_VER
0017 #include "wincompat.h"
0018 #endif
0019 
0020 #include "utils.h"
0021 
0022 #ifdef __cplusplus
0023 namespace cgreen {
0024 #endif
0025 
0026 static bool compare_want_greater_value(Constraint *constraint, intptr_t actual);
0027 
0028 static bool compare_want_lesser_value(Constraint *constraint, intptr_t actual);
0029 
0030 static bool compare_want_contents(Constraint *constraint, intptr_t actual);
0031 
0032 static bool compare_do_not_want_contents(Constraint *constraint, intptr_t actual);
0033 
0034 static bool compare_true(Constraint *constraint, intptr_t actual);
0035 static void test_true(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter);
0036 
0037 static bool compare_want_string(Constraint *constraint, intptr_t actual);
0038 static bool compare_do_not_want_string(Constraint *constraint, intptr_t actual);
0039 
0040 static bool compare_want_substring(Constraint *constraint, intptr_t actual);
0041 static bool compare_do_not_want_substring(Constraint *constraint, intptr_t actual);
0042 
0043 static bool compare_want_beginning_of_string(Constraint *constraint, intptr_t actual);
0044 
0045 
0046 static bool compare_want_double(Constraint *constraint, intptr_t actual);
0047 static void test_want_double(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter);
0048 static bool compare_do_not_want_double(Constraint *constraint, intptr_t actual);
0049 static void test_do_not_want_double(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter);
0050 static void set_contents(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter);
0051 
0052 
0053 static const char *default_expected_value_message = "\t\texpected value:\t\t\t[%" PRIdPTR "]";
0054 
0055 Constraint *create_constraint() {
0056     Constraint *constraint = (Constraint *)malloc(sizeof(Constraint));
0057     /* TODO: setting this to NULL as an implicit type check :( */
0058     constraint->parameter_name = NULL;
0059     constraint->destroy = &destroy_empty_constraint;
0060     constraint->failure_message = &failure_message_for;
0061     constraint->expected_value_name = NULL;
0062     constraint->expected_value_message = default_expected_value_message;
0063 
0064     return constraint;
0065 }
0066 
0067 static Constraint *create_constraint_expecting(intptr_t expected_value, const char *expected_value_name) {
0068     Constraint *constraint = create_constraint();
0069 
0070     constraint->expected_value = expected_value;
0071     constraint->expected_value_name = string_dup(expected_value_name);
0072 
0073     return constraint;
0074 }
0075 
0076 void destroy_empty_constraint(Constraint *constraint) {
0077     constraint->name = NULL;
0078     constraint->parameter_name = NULL;
0079     constraint->compare = NULL;
0080     constraint->execute = NULL;
0081     constraint->destroy = NULL;
0082 
0083     if (constraint->expected_value_name != NULL)
0084         free((void *)constraint->expected_value_name);
0085 
0086     free(constraint);
0087 }
0088 
0089 void destroy_static_constraint(Constraint *constraint) {
0090     /* static constraints helpers (e.g. is_null) act as singletons, and are never destroyed */
0091     (void)constraint;
0092 }
0093 
0094 void destroy_constraint(Constraint *constraint) {
0095     if (constraint->destroy != NULL)
0096         (*constraint->destroy)(constraint);
0097 }
0098 
0099 void destroy_constraints(va_list constraints) {
0100     Constraint *constraint = NULL;
0101     while ((constraint = va_arg(constraints, Constraint *)) != (Constraint *)0) {
0102         destroy_constraint(constraint); 
0103     }
0104 }
0105 
0106 bool constraint_is_for_parameter(const Constraint *constraint, const char *parameter) {
0107     return !constraint_is_not_for_parameter(constraint, parameter);
0108 }
0109 
0110 bool constraint_is_not_for_parameter(const Constraint *constraint, const char *parameter) {
0111     if (is_not_comparing(constraint) && is_not_content_setting(constraint)) {
0112         return true;
0113     }
0114 
0115     return strcmp(constraint->parameter_name, parameter) != 0;
0116 }
0117 
0118 Constraint *create_equal_to_value_constraint(intptr_t expected_value, const char *expected_value_name) {
0119     Constraint *constraint = create_constraint_expecting(expected_value, expected_value_name);
0120     constraint->type = VALUE_COMPARER;
0121 
0122     constraint->compare = &compare_want_value;
0123     constraint->execute = &test_want;
0124     constraint->name = "equal";
0125     constraint->size_of_expected_value = sizeof(intptr_t);
0126 
0127     return constraint;
0128 }
0129 
0130 Constraint *create_not_equal_to_value_constraint(intptr_t expected_value, const char *expected_value_name) {
0131     Constraint *constraint = create_constraint_expecting(expected_value, expected_value_name);
0132     constraint->type = VALUE_COMPARER;
0133 
0134     constraint->compare = &compare_do_not_want_value;
0135     constraint->execute = &test_want;
0136     constraint->name = "not equal";
0137     constraint->size_of_expected_value = sizeof(intptr_t);
0138 
0139     return constraint;
0140 }
0141 
0142 Constraint *create_less_than_value_constraint(intptr_t expected_value, const char *expected_value_name) {
0143     Constraint *constraint = create_constraint_expecting(expected_value, expected_value_name);
0144     constraint->type = VALUE_COMPARER;
0145 
0146     constraint->compare = &compare_want_lesser_value;
0147     constraint->execute = &test_true;
0148     constraint->name = "be less than";
0149     constraint->expected_value_message = "\t\texpected to be less than:\t[%" PRIdPTR "]";
0150     constraint->size_of_expected_value = sizeof(intptr_t);
0151 
0152     return constraint;
0153 }
0154 
0155 Constraint *create_greater_than_value_constraint(intptr_t expected_value, const char *expected_value_name) {
0156     Constraint *constraint = create_constraint_expecting(expected_value, expected_value_name);
0157     constraint->type = VALUE_COMPARER;
0158 
0159     constraint->compare = &compare_want_greater_value;
0160     constraint->execute = &test_true;
0161     constraint->name = "be greater than";
0162     constraint->expected_value_message = "\t\texpected to be greater than:\t[%" PRIdPTR "]";
0163     constraint->size_of_expected_value = sizeof(intptr_t);
0164 
0165     return constraint;
0166 }
0167 
0168 Constraint *create_equal_to_contents_constraint(void *pointer_to_compare, size_t size_to_compare, const char *compared_pointer_name) {
0169     Constraint *constraint = create_constraint_expecting((intptr_t)pointer_to_compare, compared_pointer_name);
0170     constraint->type = CONTENT_COMPARER;
0171 
0172     constraint->compare = &compare_want_contents;
0173     constraint->execute = &test_want;
0174     constraint->name = "equal contents of";
0175     constraint->size_of_expected_value = size_to_compare;
0176 
0177     return constraint;
0178 }
0179 
0180 Constraint *create_not_equal_to_contents_constraint(void *pointer_to_compare, size_t size_to_compare, const char *compared_pointer_name) {
0181     Constraint *constraint = create_constraint_expecting((intptr_t)pointer_to_compare, compared_pointer_name);
0182     constraint->type = CONTENT_COMPARER;
0183 
0184     constraint->compare = &compare_do_not_want_contents;
0185     constraint->execute = &test_want;
0186     constraint->name = "not equal contents of";
0187     constraint->size_of_expected_value = size_to_compare;
0188 
0189     return constraint;
0190 }
0191 
0192 Constraint *create_equal_to_string_constraint(const char* expected_value, const char *expected_value_name) {
0193     Constraint *constraint = create_constraint_expecting((intptr_t)expected_value, expected_value_name);
0194     constraint->type = STRING_COMPARER;
0195 
0196     constraint->compare = &compare_want_string;
0197     constraint->execute = &test_want;
0198     constraint->name = "equal string";
0199     constraint->expected_value_message = "\t\texpected to equal:\t\t[\"%s\"]";
0200 
0201     return constraint;
0202 }
0203 
0204 Constraint *create_not_equal_to_string_constraint(const char* expected_value, const char *expected_value_name) {
0205     Constraint *constraint = create_constraint_expecting((intptr_t)expected_value, expected_value_name);
0206     constraint->type = STRING_COMPARER;
0207 
0208     constraint->compare = &compare_do_not_want_string;
0209     constraint->execute = &test_want;
0210     constraint->name = "not equal string";
0211     constraint->expected_value_message = "\t\texpected to not equal:\t[\"%s\"]";
0212 
0213     return constraint;
0214 }
0215 
0216 Constraint *create_contains_string_constraint(const char* expected_value, const char *expected_value_name) {
0217     Constraint *constraint = create_constraint_expecting((intptr_t)expected_value, expected_value_name);
0218     constraint->type = STRING_COMPARER;
0219 
0220     constraint->compare = &compare_want_substring;
0221     constraint->execute = &test_want;
0222     constraint->name = "contain string";
0223     constraint->expected_value_message = "\t\texpected to contain:\t\t[\"%s\"]";
0224 
0225     return constraint;
0226 }
0227 
0228 Constraint *create_begins_with_string_constraint(const char* expected_value, const char *expected_value_name) {
0229     Constraint *constraint = create_constraint_expecting((intptr_t)expected_value, expected_value_name);
0230     constraint->type = STRING_COMPARER;
0231 
0232     constraint->compare = &compare_want_beginning_of_string;
0233     constraint->execute = &test_want;
0234     constraint->name = "begin with string";
0235     constraint->expected_value_message = "\t\texpected to begin with:\t\t[\"%s\"]";
0236 
0237     return constraint;
0238 }
0239 
0240 Constraint *create_does_not_contain_string_constraint(const char* expected_value, const char *expected_value_name) {
0241     Constraint *constraint = create_constraint_expecting((intptr_t)expected_value, expected_value_name);
0242     constraint->type = STRING_COMPARER;
0243 
0244     constraint->compare = &compare_do_not_want_substring;
0245     constraint->execute = &test_want;
0246     constraint->name = "not contain string";
0247     constraint->expected_value_message = "\t\texpected to not contain:\t[\"%s\"]";
0248 
0249     return constraint;
0250 }
0251 
0252 Constraint *create_equal_to_double_constraint(double expected_value, const char *expected_value_name) {
0253     Constraint *constraint = create_constraint_expecting(box_double(expected_value), expected_value_name);
0254     constraint->type = DOUBLE_COMPARER;
0255 
0256     constraint->compare = &compare_want_double;
0257     constraint->execute = &test_want_double;
0258     constraint->name = "equal double";
0259     constraint->destroy = &destroy_double_constraint;
0260 
0261     return constraint;
0262 }
0263 
0264 Constraint *create_not_equal_to_double_constraint(double expected_value, const char *expected_value_name) {
0265     Constraint *constraint = create_constraint_expecting(box_double(expected_value), expected_value_name);
0266     constraint->type = DOUBLE_COMPARER;
0267 
0268     constraint->compare = &compare_do_not_want_double;
0269     constraint->execute = &test_do_not_want_double;
0270     constraint->name = "not equal double";
0271     constraint->destroy = &destroy_double_constraint;
0272 
0273     return constraint;
0274 }
0275 
0276 Constraint *create_return_value_constraint(intptr_t value_to_return) {
0277     Constraint* constraint = create_constraint();
0278     constraint->type = RETURN_VALUE;
0279 
0280     constraint->compare = &compare_true;
0281     constraint->execute = &test_true;
0282     constraint->name = "return value";
0283     constraint->expected_value = value_to_return;
0284 
0285     return constraint;
0286 }
0287 
0288 Constraint *create_set_parameter_value_constraint(const char *parameter_name, intptr_t value_to_set, size_t size_to_set) {
0289     Constraint* constraint = create_constraint();
0290     constraint->type = CONTENT_SETTER;
0291 
0292     constraint->compare = &compare_true;
0293     constraint->execute = &set_contents;
0294     constraint->name = "set parameter value";
0295     constraint->expected_value = value_to_set;
0296     constraint->size_of_expected_value = size_to_set;
0297     constraint->parameter_name = parameter_name;
0298 
0299     return constraint;
0300 }
0301 
0302 bool compare_want_value(Constraint *constraint, intptr_t actual) {
0303     return constraint->expected_value == actual;
0304 }
0305 
0306 bool compare_do_not_want_value(Constraint *constraint, intptr_t actual) {
0307     return !compare_want_value(constraint, actual);
0308 }
0309 
0310 bool compare_want_greater_value(Constraint *constraint, intptr_t actual) {
0311     return actual > constraint->expected_value ;
0312 }
0313 
0314 bool compare_want_lesser_value(Constraint *constraint, intptr_t actual) {
0315     return actual < constraint->expected_value;
0316 }
0317 
0318 
0319 bool compare_want_contents(Constraint *constraint, intptr_t actual) {
0320     /* we can't inspect the contents of a NULL pointer, so comparison always fails */
0321     if ((void *)actual == NULL) {
0322         return 0;
0323     }
0324 
0325     return 0 == memcmp((void *)constraint->expected_value, (void *)actual, constraint->size_of_expected_value);
0326 }
0327 
0328 bool compare_do_not_want_contents(Constraint *constraint, intptr_t actual) {
0329     /* we can't inspect the contents of a NULL pointer, so comparison always fails */
0330     if ((void *)actual == NULL) {
0331         return 0;
0332     }
0333 
0334     return !compare_want_contents(constraint, actual);
0335 }
0336 
0337 static void set_contents(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter) {
0338     char *message;
0339     (void)function;
0340 
0341     if (parameters_are_not_valid_for(constraint, actual)) {
0342         message = validation_failure_message_for(constraint, actual);
0343 
0344         (*reporter->assert_true)(
0345                 reporter,
0346                 test_file,
0347                 test_line,
0348                 false,
0349                 message);
0350 
0351         free(message);
0352         return;
0353     }
0354 
0355     memmove((void *)actual, (void *)constraint->expected_value, constraint->size_of_expected_value);
0356 }
0357 
0358 
0359 
0360 void test_want(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter) {
0361     char *message;
0362     char parameter_name_actual_string[255];
0363 
0364     if (parameters_are_not_valid_for(constraint, actual)) {
0365         message = validation_failure_message_for(constraint, actual);
0366 
0367         (*reporter->assert_true)(
0368                 reporter,
0369                 test_file,
0370                 test_line,
0371                 false,
0372                 message);
0373 
0374         free(message);
0375 
0376         return;
0377     }
0378 
0379     snprintf(parameter_name_actual_string, sizeof(parameter_name_actual_string) - 1, "[%s] parameter in [%s]", constraint->parameter_name, function);
0380     message = constraint->failure_message(constraint, parameter_name_actual_string, actual);
0381 
0382     (*reporter->assert_true)(
0383             reporter,
0384             test_file,
0385             test_line,
0386             (*constraint->compare)(constraint, actual),
0387             message);
0388 
0389     free(message);
0390 }
0391 
0392 static bool compare_want_string(Constraint *constraint, intptr_t actual) {
0393     return strings_are_equal((const char *)constraint->expected_value, (const char *)actual);
0394 }
0395 
0396 static bool compare_do_not_want_string(Constraint *constraint, intptr_t actual) {
0397     return !compare_want_string(constraint, actual);
0398 }
0399 
0400 static bool compare_do_not_want_substring(Constraint *constraint, intptr_t actual) {
0401     return !compare_want_substring(constraint, actual);
0402 }
0403 
0404 static bool compare_want_substring(Constraint *constraint, intptr_t actual) {
0405     return string_contains((const char *)actual, (const char *)constraint->expected_value);
0406 }
0407 
0408 const int NOT_FOUND = -1;
0409 
0410 static int strpos(const char *haystack, const char *needle)
0411 {
0412     const char *offset = strstr(haystack, needle);
0413     if (offset != NULL) {
0414       return (int)(offset - haystack);
0415     }
0416 
0417     return NOT_FOUND;
0418 }
0419 
0420 static bool compare_want_beginning_of_string(Constraint *constraint, intptr_t actual) {
0421     return strpos((const char *)actual, (const char *)constraint->expected_value) == 0;
0422 }
0423 
0424 static bool compare_want_double(Constraint *constraint, intptr_t actual) {
0425     return doubles_are_equal(as_double(constraint->expected_value), as_double(actual));
0426 }
0427 
0428 static void test_want_double(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter) {
0429     (*reporter->assert_true)(
0430             reporter,
0431             test_file,
0432             test_line,
0433             (*constraint->compare)(constraint, actual),
0434             "Wanted [%d], but got [%d] in function [%s] parameter [%s]",
0435             as_double(constraint->expected_value),
0436             as_double(actual),
0437             function,
0438             constraint->parameter_name);
0439 
0440     (void)unbox_double(actual);
0441 }
0442 
0443 static bool compare_do_not_want_double(Constraint *constraint, intptr_t actual) {
0444     return !compare_want_double(constraint, actual);
0445 }
0446 
0447 static void test_do_not_want_double(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter) {
0448     (*reporter->assert_true)(
0449             reporter,
0450             test_file,
0451             test_line,
0452             (*constraint->compare)(constraint, actual),
0453             "Did not want [%d], but got [%d] in function [%s] parameter [%s]",
0454             as_double(constraint->expected_value),
0455             as_double(actual),
0456             function,
0457             constraint->parameter_name);
0458 
0459     (void)unbox_double(actual);
0460 }
0461 
0462 void destroy_double_constraint(Constraint *constraint) {
0463     (void)unbox_double(constraint->expected_value);
0464     destroy_empty_constraint(constraint);
0465 }
0466 
0467 static bool compare_true(Constraint *constraint, intptr_t actual) {
0468     (void)constraint;
0469     (void)actual;
0470 
0471     return true;
0472 }
0473 
0474 static void test_true(Constraint *constraint, const char *function, intptr_t actual, const char *test_file, int test_line, TestReporter *reporter) {
0475     (void)constraint;
0476     (void)function;
0477     (void)actual;
0478     (void)test_file;
0479     (void)test_line;
0480     (void)reporter;
0481 }
0482 
0483 bool values_are_strings_in(const Constraint *constraint) {
0484     return is_string_comparing(constraint) && (constraint->expected_value != (intptr_t)NULL);
0485 }
0486 
0487 bool no_expected_value_in(const Constraint *constraint) {
0488     return constraint->destroy == destroy_static_constraint;
0489 }
0490 
0491 bool is_content_comparing(const Constraint *constraint) {
0492     return constraint->type == CONTENT_COMPARER;
0493 }
0494 
0495 bool is_content_setting(const Constraint *constraint) {
0496     return constraint->type == CONTENT_SETTER;
0497 }
0498 
0499 bool is_not_content_setting(const Constraint *constraint) {
0500     return !is_content_setting(constraint);
0501 }
0502 
0503 bool is_string_comparing(const Constraint *constraint) {
0504     return constraint->type == STRING_COMPARER;
0505 }
0506 
0507 bool is_double_comparing(const Constraint *constraint) {
0508     return constraint->type == DOUBLE_COMPARER;
0509 }
0510 
0511 bool is_comparing(const Constraint *constraint) {
0512     return is_string_comparing(constraint) ||
0513             is_content_comparing(constraint) ||
0514             is_double_comparing(constraint) ||
0515             constraint->type == VALUE_COMPARER;
0516 }
0517 
0518 bool is_not_comparing(const Constraint *constraint) {
0519     return !is_comparing(constraint);
0520 }
0521 
0522 bool is_parameter(const Constraint *constraint) {
0523     return is_comparing(constraint) || is_content_setting(constraint); 
0524 }
0525 
0526 bool constraint_is_for_parameter_in(const Constraint *constraint, const char *names) {
0527     int i;
0528     bool found = false;
0529 
0530     CgreenVector *parameter_names = create_vector_of_names(names);
0531     if (!is_parameter(constraint)) return false; 
0532 
0533     for (i = 0; i < cgreen_vector_size(parameter_names); i++) {
0534         const char *mock_parameter_name = (const char *)cgreen_vector_get(parameter_names, i);
0535 
0536         if (constraint_is_for_parameter(constraint, mock_parameter_name)) {
0537             found = true;
0538             break;
0539         }
0540     }
0541 
0542     destroy_cgreen_vector(parameter_names);
0543     return found;
0544 }
0545 
0546 
0547 #ifdef __cplusplus
0548 } // namespace cgreen
0549 #endif
0550 
0551 /* vim: set ts=4 sw=4 et cindent: */