0001 #ifdef WIN32
0002 #include "runner.h"
0003 #include "cgreen/internal/runner_platform.h"
0004 #include "cgreen/messaging.h"
0005 #include "wincompat.h"
0006
0007 #ifdef __cplusplus
0008 namespace cgreen {
0009 #endif
0010
0011
0012 #include "Strsafe.h"
0013 #define SECOND (1000)
0014 static void run_named_test_child(TestSuite *suite, const char *name, TestReporter *reporter);
0015 static void run_test_in_its_own_process_child(TestSuite *suite, CgreenTest *test, TestReporter *reporter);
0016
0017
0018 static void CALLBACK stop(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
0019 {
0020 _exit(EXIT_SUCCESS);
0021 }
0022
0023 void die_in(unsigned int seconds) {
0024 MMRESULT signal_result = timeSetEvent(seconds*SECOND,SECOND,&stop,0,TIME_ONESHOT);
0025 if (0 == signal_result){
0026 fprintf(stderr, "could not set alarm signal hander\n");
0027 return;
0028 }
0029 }
0030
0031 static void run_test_in_the_current_process_child(TestSuite *suite, CgreenTest *test, TestReporter *reporter) {
0032 (*reporter->start_test)(reporter, test->name);
0033 run_the_test_code(suite, test, reporter);
0034 send_reporter_completion_notification(reporter);
0035 stop(0, 0, 0, 0, 0);
0036 }
0037
0038 static void run_named_test_child(TestSuite *suite, const char *name, TestReporter *reporter) {
0039 int i;
0040
0041 for (i = 0; i < suite->size; i++) {
0042 if (suite->tests[i].type == test_function) {
0043 if (strcmp(suite->tests[i].name, name) == 0) {
0044 run_test_in_the_current_process_child(suite, suite->tests[i].Runnable.test, reporter);
0045 }
0046 } else if (has_test(suite->tests[i].Runnable.suite, name)) {
0047 TestSuite* newSuite=suite->tests[i].Runnable.suite;
0048 (*suite->setup)();
0049
0050
0051
0052 (*reporter->start_suite)(reporter, newSuite->name, count_tests(newSuite));
0053 run_named_test_child(newSuite, name, reporter);
0054 (*reporter->finish_suite)(reporter, newSuite->filename, newSuite->line);
0055 (*suite->teardown)();
0056 }
0057 }
0058 send_reporter_completion_notification(reporter);
0059 }
0060
0061 void run_specified_test_if_child(TestSuite *suite, TestReporter *reporter){
0062
0063 char testName[256];
0064 DWORD result = GetEnvironmentVariableA(CGREEN_TEST_TO_RUN,testName,sizeof(testName));
0065
0066 if (result)
0067 {
0068
0069
0070
0071
0072 reporter_start(reporter, testName);
0073 run_named_test_child(suite, testName, reporter);
0074 reporter_finish(reporter, suite->filename, suite->line, NULL);
0075
0076 return;
0077 }
0078
0079 }
0080
0081 struct environment
0082 {
0083 char env[MAX_PATH];
0084 char *p_head;
0085 };
0086
0087 struct environment* create_environment()
0088 {
0089 struct environment* p = (struct environment*)malloc(sizeof(struct environment));
0090 memset(p->env, 0, sizeof(p->env));
0091 p->p_head = p->env;
0092 return p;
0093 }
0094
0095 static void AddEnvironmentVariable(struct environment* env,const char* varName, const char* valueString)
0096 {
0097 size_t len;
0098 size_t envSize = MAX_PATH - (env->p_head-env->env);
0099 StringCbCopyA(env->p_head, envSize, varName);
0100 StringCbCatA(env->p_head, envSize, "=");
0101 StringCbCatA(env->p_head, envSize, valueString);
0102 StringCbCatA(env->p_head, envSize, "\0");
0103 len = strnlen_s(env->p_head, envSize);
0104 env->p_head += (len + 1);
0105 }
0106
0107 static const char* get_environment_block(const struct environment* env)
0108 {
0109 return env->env;
0110 }
0111
0112 static void dispose_environment(struct environment* env)
0113 {
0114 free(env);
0115 }
0116
0117
0118 void run_test_in_its_own_process(TestSuite *suite, CgreenTest *test, TestReporter *reporter) {
0119 #define COMMAND_LINE_LENGTH (2*MAX_PATH)
0120 BOOL success;
0121 char fname[MAX_PATH+1];
0122 struct environment* p_environment = create_environment();
0123 char handleString[256];
0124
0125 STARTUPINFOA siStartupInfo;
0126 PROCESS_INFORMATION piProcessInfo;
0127
0128
0129 GetModuleFileNameA(NULL, fname,MAX_PATH);
0130
0131
0132 memset(&siStartupInfo, 0, sizeof(siStartupInfo));
0133 memset(&piProcessInfo, 0, sizeof(piProcessInfo));
0134 siStartupInfo.cb = sizeof(siStartupInfo);
0135
0136 sprintf_s(handleString,sizeof(handleString), "%i", get_pipe_read_handle());
0137 AddEnvironmentVariable(p_environment, CGREEN_READ_HANDLE, handleString);
0138
0139 sprintf_s(handleString,sizeof(handleString), "%i", get_pipe_write_handle());
0140 AddEnvironmentVariable(p_environment, CGREEN_WRITE_HANDLE, handleString);
0141
0142
0143 AddEnvironmentVariable(p_environment, CGREEN_TEST_TO_RUN, test->name);
0144
0145 (*reporter->start_test)(reporter, test->name);
0146
0147 success = CreateProcessA(fname, NULL, NULL, NULL, true, NORMAL_PRIORITY_CLASS , p_environment, NULL, &siStartupInfo, &piProcessInfo);
0148 dispose_environment(p_environment);
0149 WaitForSingleObject(piProcessInfo.hProcess,INFINITE);
0150 (*reporter->finish_test)(reporter, test->filename, test->line, NULL);
0151
0152 return;
0153 }
0154
0155
0156 #ifdef __cplusplus
0157 }
0158 #endif
0159
0160 #endif
0161