0001 #include <cgreen/assertions.h>
0002 #include <cgreen/mocks.h>
0003 #include <cgreen/reporter.h>
0004 #include <cgreen/suite.h>
0005 #include <cgreen/internal/runner_platform.h>
0006 #include <stdarg.h>
0007 #include <stdio.h>
0008 #include <stdlib.h>
0009 #include <string.h>
0010 #include <sys/types.h>
0011 #include <unistd.h>
0012
0013 #include "cgreen/runner.h"
0014
0015 #ifdef __cplusplus
0016 #include <stdexcept>
0017
0018 namespace cgreen {
0019 #endif
0020
0021 static const char* CGREEN_PER_TEST_TIMEOUT_ENVIRONMENT_VARIABLE = "CGREEN_PER_TEST_TIMEOUT";
0022
0023 static void run_every_test(TestSuite *suite, TestReporter *reporter);
0024 static void run_named_test(TestSuite *suite, const char *name, TestReporter *reporter);
0025
0026 static void run_test_in_the_current_process(TestSuite *suite, CgreenTest *test, TestReporter *reporter);
0027
0028 static int per_test_timeout_defined(void);
0029 static int per_test_timeout_value(void);
0030 static void validate_per_test_timeout_value(void);
0031
0032 int run_test_suite(TestSuite *suite, TestReporter *reporter) {
0033 int success;
0034 if (per_test_timeout_defined()) {
0035 validate_per_test_timeout_value();
0036 }
0037
0038 setup_reporting(reporter);
0039 run_every_test(suite, reporter);
0040 success = (reporter->failures == 0) && (reporter->exceptions==0);
0041 return success ? EXIT_SUCCESS : EXIT_FAILURE;
0042 }
0043
0044 int run_single_test(TestSuite *suite, const char *name, TestReporter *reporter) {
0045 int success;
0046 if (per_test_timeout_defined()) {
0047 validate_per_test_timeout_value();
0048 }
0049
0050 setup_reporting(reporter);
0051 run_named_test(suite, name, reporter);
0052 success = (reporter->failures == 0);
0053 return success ? EXIT_SUCCESS : EXIT_FAILURE;
0054 }
0055
0056 static void run_every_test(TestSuite *suite, TestReporter *reporter) {
0057 int i;
0058
0059 run_specified_test_if_child(suite, reporter);
0060
0061 (*reporter->start_suite)(reporter, suite->name, count_tests(suite));
0062 for (i = 0; i < suite->size; i++) {
0063 if (suite->tests[i].type == test_function) {
0064 run_test_in_its_own_process(suite, suite->tests[i].Runnable.test, reporter);
0065 } else {
0066 (*suite->setup)();
0067 run_every_test(suite->tests[i].Runnable.suite, reporter);
0068 (*suite->teardown)();
0069 }
0070 }
0071 send_reporter_completion_notification(reporter);
0072 (*reporter->finish_suite)(reporter, suite->filename, suite->line);
0073 }
0074
0075 static void run_named_test(TestSuite *suite, const char *name, TestReporter *reporter) {
0076 int i;
0077 (*reporter->start_suite)(reporter, suite->name, count_tests(suite));
0078 for (i = 0; i < suite->size; i++) {
0079 if (suite->tests[i].type == test_function) {
0080 if (strcmp(suite->tests[i].name, name) == 0) {
0081 run_test_in_the_current_process(suite, suite->tests[i].Runnable.test, reporter);
0082 }
0083 } else if (has_test(suite->tests[i].Runnable.suite, name)) {
0084 (*suite->setup)();
0085 run_named_test(suite->tests[i].Runnable.suite, name, reporter);
0086 (*suite->teardown)();
0087 }
0088 }
0089 send_reporter_completion_notification(reporter);
0090 (*reporter->finish_suite)(reporter, suite->filename, suite->line);
0091 }
0092
0093
0094 static void run_test_in_the_current_process(TestSuite *suite, CgreenTest *test, TestReporter *reporter) {
0095 (*reporter->start_test)(reporter, test->name);
0096 run_the_test_code(suite, test, reporter);
0097 send_reporter_completion_notification(reporter);
0098 (*reporter->finish_test)(reporter, test->filename, test->line, NULL);
0099 }
0100
0101 static int per_test_timeout_defined() {
0102 return getenv(CGREEN_PER_TEST_TIMEOUT_ENVIRONMENT_VARIABLE) != NULL;
0103 }
0104
0105 static int per_test_timeout_value() {
0106 char* timeout_string;
0107 int timeout_value;
0108
0109 if (!per_test_timeout_defined()) {
0110 die("attempt to fetch undefined value for %s\n", CGREEN_PER_TEST_TIMEOUT_ENVIRONMENT_VARIABLE);
0111 }
0112
0113 timeout_string = getenv(CGREEN_PER_TEST_TIMEOUT_ENVIRONMENT_VARIABLE);
0114 timeout_value = atoi(timeout_string);
0115
0116 return timeout_value;
0117 }
0118
0119 static void validate_per_test_timeout_value() {
0120 int timeout = per_test_timeout_value();
0121
0122 if (timeout <= 0) {
0123 die("invalid value for %s environment variable: %d\n", CGREEN_PER_TEST_TIMEOUT_ENVIRONMENT_VARIABLE, timeout);
0124 }
0125 }
0126
0127 static void run_setup_for(CgreenTest *spec) {
0128 #ifdef __cplusplus
0129 std::string message = "an exception was thrown during setup: ";
0130 try {
0131 #endif
0132 spec->context->setup();
0133 #ifdef __cplusplus
0134 return;
0135 } catch(const std::exception& exception) {
0136 message += '[';
0137 message += exception.what();
0138 message += ']';
0139 } catch(const std::exception* exception) {
0140 message += '[';
0141 message += exception->what();
0142 message += ']';
0143 } catch(const std::string& exception_message) {
0144 message += '[';
0145 message += exception_message;
0146 message += ']';
0147 } catch(const std::string *exception_message) {
0148 message += '[';
0149 message += *exception_message;
0150 message += ']';
0151 } catch(const char *exception_message) {
0152 message += '[';
0153 message += exception_message;
0154 message += ']';
0155 } catch (...) {
0156 message += "unknown exception type";
0157 }
0158 va_list no_arguments;
0159 memset(&no_arguments, 0, sizeof(va_list));
0160 TestReporter *reporter = get_test_reporter();
0161 reporter->show_incomplete(reporter, spec->filename, spec->line, message.c_str(), no_arguments);
0162 send_reporter_exception_notification(reporter);
0163 #endif
0164 }
0165
0166 static void run_teardown_for(CgreenTest *spec) {
0167 #ifdef __cplusplus
0168 std::string message = "an exception was thrown during teardown: ";
0169 try {
0170 #endif
0171 spec->context->teardown();
0172 #ifdef __cplusplus
0173 return;
0174 } catch(const std::exception& exception) {
0175 message += '[';
0176 message += exception.what();
0177 message += ']';
0178 } catch(const std::exception* exception) {
0179 message += '[';
0180 message += exception->what();
0181 message += ']';
0182 } catch(const std::string& exception_message) {
0183 message += '[';
0184 message += exception_message;
0185 message += ']';
0186 } catch(const std::string *exception_message) {
0187 message += '[';
0188 message += *exception_message;
0189 message += ']';
0190 } catch(const char *exception_message) {
0191 message += '[';
0192 message += exception_message;
0193 message += ']';
0194 } catch (...) {
0195 message += "unknown exception type";
0196 }
0197 va_list no_arguments;
0198 memset(&no_arguments, 0, sizeof(va_list));
0199 TestReporter *reporter = get_test_reporter();
0200 reporter->show_incomplete(reporter, spec->filename, spec->line, message.c_str(), no_arguments);
0201 send_reporter_exception_notification(reporter);
0202 #endif
0203 }
0204
0205
0206
0207
0208
0209
0210
0211
0212 static void run(CgreenTest *spec) {
0213 #ifdef __cplusplus
0214 std::string message = "an exception was thrown during test: ";
0215 try {
0216 #endif
0217 spec->run();
0218 #ifdef __cplusplus
0219 return;
0220 } catch(const std::exception& exception) {
0221 message += '[';
0222 message += exception.what();
0223 message += ']';
0224 } catch(const std::exception* exception) {
0225 message += '[';
0226 message += exception->what();
0227 message += ']';
0228 } catch(const std::string& exception_message) {
0229 message += '[';
0230 message += exception_message;
0231 message += ']';
0232 } catch(const std::string *exception_message) {
0233 message += '[';
0234 message += *exception_message;
0235 message += ']';
0236 } catch(const char *exception_message) {
0237 message += '[';
0238 message += exception_message;
0239 message += ']';
0240 } catch (...) {
0241 message += "unknown exception type";
0242 }
0243 va_list no_arguments;
0244 memset(&no_arguments, 0, sizeof(va_list));
0245 TestReporter *reporter = get_test_reporter();
0246 reporter->show_incomplete(reporter, spec->filename, spec->line, message.c_str(), no_arguments);
0247 send_reporter_exception_notification(reporter);
0248 #endif
0249 }
0250
0251 void run_the_test_code(TestSuite *suite, CgreenTest *spec, TestReporter *reporter) {
0252 significant_figures_for_assert_double_are(8);
0253 clear_mocks();
0254
0255 if (per_test_timeout_defined()) {
0256 validate_per_test_timeout_value();
0257
0258 die_in(per_test_timeout_value());
0259 }
0260
0261
0262 if(has_setup(suite)) {
0263 (*suite->setup)();
0264 } else {
0265 if (spec->context->setup != NULL) {
0266 run_setup_for(spec);
0267 }
0268 }
0269
0270 run(spec);
0271
0272 if (suite->teardown != &do_nothing) {
0273 (*suite->teardown)();
0274 } else {
0275 if (spec->context->teardown != NULL) {
0276 run_teardown_for(spec);
0277 }
0278 }
0279
0280 tally_mocks(reporter);
0281 }
0282
0283 void die(const char *message, ...) {
0284 va_list arguments;
0285 va_start(arguments, message);
0286 vprintf(message, arguments);
0287 va_end(arguments);
0288 exit(EXIT_FAILURE);
0289 }
0290
0291 #ifdef __cplusplus
0292 }
0293 #endif
0294
0295