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
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
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
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
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 }
0549 #endif
0550
0551