0001 #include <cgreen/breadcrumb.h>
0002 #include <cgreen/cdash_reporter.h>
0003 #include <cgreen/reporter.h>
0004 #include <errno.h>
0005 #include <sys/types.h>
0006 #include <sys/stat.h>
0007 #include <stdlib.h>
0008 #include <stdio.h>
0009 #include <string.h>
0010 #include <time.h>
0011
0012 #ifdef _MSC_VER
0013 #include <wincompat.h>
0014 #endif
0015
0016 #ifdef __cplusplus
0017 namespace cgreen {
0018 #endif
0019
0020 typedef int Printer(FILE *, const char *format, ...);
0021 typedef time_t Timer(char *strtime);
0022 typedef double DiffTimer(time_t t1, time_t t2);
0023
0024 typedef struct {
0025 CDashInfo *cdash;
0026 Printer *printer;
0027 Timer *timer;
0028 DiffTimer *difftimer;
0029 int pipe_fd[2];
0030 time_t begin;
0031 time_t startdatetime;
0032 time_t enddatetime;
0033 time_t teststarted;
0034 time_t testfinished;
0035 FILE *f_reporter;
0036 } CdashMemo;
0037
0038 static void cdash_destroy_reporter(TestReporter *reporter);
0039 static void cdash_reporter_suite_started(TestReporter *reporter, const char *name, const int number_of_tests);
0040 static void cdash_reporter_testcase_started(TestReporter *reporter, const char *name);
0041
0042 static void show_failed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
0043 static void show_passed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
0044 static void show_incomplete(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments);
0045
0046 static void cdash_reporter_testcase_finished(TestReporter *reporter, const char *filename, int line, const char *message);
0047 static void cdash_reporter_suite_finished(TestReporter *reporter, const char *filename, int line);
0048
0049 static time_t cdash_build_stamp(char *sbuildstamp, size_t sb);
0050 static time_t cdash_current_time(char *strtime);
0051 static double cdash_enlapsed_time(time_t t1, time_t t2);
0052
0053 TestReporter *create_cdash_reporter(CDashInfo *cdash) {
0054 TestReporter *reporter;
0055 CdashMemo *memo;
0056 FILE *fd;
0057 char sbuildstamp[15];
0058 char strstart[30];
0059 char reporter_path[255];
0060 int rep_dir, strsize;
0061
0062 if (!cdash)
0063 return NULL;
0064
0065 reporter = create_reporter();
0066 if (!reporter)
0067 return NULL;
0068
0069 memo = (CdashMemo *) malloc(sizeof(CdashMemo));
0070 if (!memo)
0071 return NULL;
0072
0073 memo->cdash = (CDashInfo *) cdash;
0074
0075 memo->printer = fprintf;
0076 memo->timer = cdash_current_time;
0077 memo->difftimer = cdash_enlapsed_time;
0078 memo->begin = cdash_build_stamp(sbuildstamp, 15);
0079
0080 rep_dir = mkdir("./Testing", S_IXUSR|S_IRUSR|S_IWUSR|S_IXGRP|S_IRGRP|S_IXOTH);
0081
0082 if (rep_dir) {
0083 if (errno != EEXIST) {
0084 free(memo);
0085 return NULL;
0086 }
0087 }
0088
0089 fd = fopen("./Testing/TAG", "w+");
0090 if (fd == NULL) {
0091 free(memo);
0092 return NULL;
0093 }
0094
0095 fprintf(fd,"%s\n%s\n", sbuildstamp, memo->cdash->type);
0096
0097 fclose(fd);
0098
0099 strsize = snprintf(reporter_path, sizeof(reporter_path) - 1, "./Testing/%s", sbuildstamp);
0100
0101 rep_dir = mkdir(reporter_path, S_IXUSR|S_IRUSR|S_IWUSR|S_IXGRP|S_IRGRP|S_IXOTH);
0102
0103 if (rep_dir) {
0104 if (errno != EEXIST) {
0105 free(memo);
0106 return NULL;
0107 }
0108 }
0109
0110 snprintf( (char *) (reporter_path + strsize), (255 - strsize), "/Test.xml");
0111
0112 fd = fopen(reporter_path, "w+");
0113 if (fd == NULL) {
0114 free(memo);
0115 return NULL;
0116 }
0117
0118
0119 memo->f_reporter = fd;
0120
0121 memo->startdatetime = cdash_current_time(strstart);
0122
0123 memo->printer(memo->f_reporter,
0124 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
0125 " <Site BuildName=\"%s\" BuildStamp=\"%s-%s\" Name=\"%s\" Generator=\"%s\""
0126 " OSName=\"%s\" Hostname=\"%s\" OSRelease=\"%s\""
0127 " OSVersion=\"%s\" OSPlatform=\"%s\""
0128 " Is64Bits=\"\" VendorString=\"\" VendorID=\"\""
0129 " FamilyID=\"\" ModelID=\"\" ProcessorCacheSize=\"\" NumberOfLogicalCPU=\"\""
0130 " NumberOfPhysicalCPU=\"\" TotalVirtualMemory=\"\" TotalPhysicalMemory=\"\""
0131 " LogicalProcessorsPerPhysical=\"\" ProcessorClockFrequency=\"\" >\n"
0132 " <Testing>\n"
0133 " <StartDateTime>%s</StartDateTime>\n"
0134 " <TestList>\n"
0135 " <Test></Test>\n"
0136 " </TestList>\n",
0137 memo->cdash->build, sbuildstamp, memo->cdash->type, memo->cdash->name, "Cgreen1.0.0",
0138 memo->cdash->os_name, memo->cdash->hostname, memo->cdash->os_release,
0139 memo->cdash->os_version, memo->cdash->os_platform, strstart);
0140
0141 fflush(memo->f_reporter);
0142
0143 reporter->destroy = &cdash_destroy_reporter;
0144 reporter->start_suite = &cdash_reporter_suite_started;
0145 reporter->start_test = &cdash_reporter_testcase_started;
0146 reporter->show_fail = &show_failed;
0147 reporter->show_pass = &show_passed;
0148 reporter->show_incomplete = &show_incomplete;
0149 reporter->finish_test = &cdash_reporter_testcase_finished;
0150 reporter->finish_suite = &cdash_reporter_suite_finished;
0151 reporter->memo = memo;
0152
0153 return reporter;
0154 }
0155
0156 static void cdash_destroy_reporter(TestReporter *reporter) {
0157 char endtime[30];
0158
0159 CdashMemo *memo = (CdashMemo *)reporter->memo;
0160
0161 memo->enddatetime = cdash_current_time(endtime);
0162
0163 memo->printer(memo->f_reporter, " <EndDateTime>%s</EndDateTime>\n"
0164 " <ElapsedMinutes>%.2f</ElapsedMinutes>\n"
0165 " </Testing>\n"
0166 "</Site>\n", endtime, memo->difftimer(memo->startdatetime, memo->enddatetime));
0167
0168 destroy_reporter(reporter);
0169 }
0170
0171
0172 static void cdash_reporter_suite_started(TestReporter *reporter, const char *name, const int number_of_tests) {
0173 (void)number_of_tests;
0174
0175 reporter_start(reporter, name);
0176 }
0177
0178 static void cdash_reporter_testcase_started(TestReporter *reporter, const char *name) {
0179 CdashMemo *memo = (CdashMemo *)reporter->memo;
0180 memo->teststarted = memo->timer(NULL);
0181 reporter_start(reporter, name);
0182 }
0183
0184 static void show_failed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments) {
0185 const char *name;
0186 char buffer[1000];
0187 float exectime;
0188 CdashMemo *memo;
0189
0190 memo = (CdashMemo *)reporter->memo;
0191
0192 memo->testfinished = memo->timer(NULL);
0193
0194 exectime = (float)memo->difftimer(memo->teststarted, memo->testfinished);
0195
0196 name = get_current_from_breadcrumb((CgreenBreadcrumb *)reporter->breadcrumb);
0197
0198 memo->printer(memo->f_reporter,
0199 " <Test Status=\"failed\">\n");
0200 memo->printer(memo->f_reporter,
0201 " <Name>%s</Name>\n"
0202 " <Path>%s</Path>\n"
0203 " <FullName>%s</FullName>\n"
0204 " <FullCommandLine>at [%s] line [%d]</FullCommandLine>\n", name, file, file, file, line);
0205 memo->printer(memo->f_reporter,
0206 " <Results>\n"
0207 " <NamedMeasurement type=\"numeric/double\" name=\"Execution Time\"><Value>%f</Value></NamedMeasurement>\n"
0208 " <NamedMeasurement type=\"text/string\" name=\"Completion Status\"><Value>Completed</Value></NamedMeasurement>\n"
0209 " <NamedMeasurement type=\"text/string\" name=\"Command Line\"><Value>%s</Value></NamedMeasurement>\n"
0210 " <Measurement>\n"
0211 " <Value>", exectime, name);
0212 vsprintf(buffer, (message == NULL ? "Problem" : message), arguments);
0213 memo->printer(memo->f_reporter, "%s", buffer);
0214 memo->printer(memo->f_reporter, "</Value>\n"
0215 " </Measurement>\n"
0216 " </Results>\n"
0217 " </Test>\n");
0218 }
0219
0220 static void show_passed(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments) {
0221 double exectime;
0222 CdashMemo *memo;
0223 const char *name = get_current_from_breadcrumb((CgreenBreadcrumb *)reporter->breadcrumb);
0224 (void)message;
0225 (void)arguments;
0226 memo = (CdashMemo *)reporter->memo;
0227
0228 memo->testfinished = memo->timer(NULL);
0229 exectime = memo->difftimer(memo->teststarted, memo->testfinished);
0230
0231 memo->printer(memo->f_reporter,
0232 " <Test Status=\"passed\">\n");
0233 memo->printer(memo->f_reporter, ""
0234 " <Name>%s</Name>\n"
0235 " <Path>%s</Path>\n"
0236 " <FullName>%s</FullName>\n"
0237 " <FullCommandLine>at [%s] line [%d]</FullCommandLine>\n", name, file, file, file, line);
0238 memo->printer(memo->f_reporter,
0239 " <Results>\n"
0240 " <NamedMeasurement type=\"numeric/double\" name=\"Execution Time\"><Value>%f</Value></NamedMeasurement>\n"
0241 " <NamedMeasurement type=\"text/string\" name=\"Completion Status\"><Value>Completed</Value></NamedMeasurement>\n"
0242 " <NamedMeasurement type=\"text/string\" name=\"Command Line\"><Value>%s</Value></NamedMeasurement>\n"
0243 " <Measurement>\n"
0244 " <Value></Value>\n"
0245 " </Measurement>\n"
0246 " </Results>\n"
0247 " </Test>\n", exectime, name);
0248 }
0249
0250 static void show_incomplete(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments) {
0251 (void)reporter;
0252 (void)file;
0253 (void)line;
0254 (void)message;
0255 (void)arguments;
0256 }
0257
0258
0259 static void cdash_reporter_testcase_finished(TestReporter *reporter, const char *filename, int line, const char *message) {
0260 reporter_finish(reporter, filename, line, message);
0261 }
0262
0263
0264 static void cdash_reporter_suite_finished(TestReporter *reporter, const char *filename, int line) {
0265 reporter_finish(reporter, filename, line, NULL);
0266 }
0267
0268 static time_t cdash_build_stamp(char *sbuildstamp, size_t sb) {
0269 time_t t1;
0270 struct tm d1;
0271 char s[15];
0272
0273 t1 = time(0);
0274 gmtime_r(&t1, &d1);
0275
0276 strftime(s, sizeof(s), "%Y%m%d-%H%M", &d1);
0277 snprintf(sbuildstamp, sb, "%s", s);
0278
0279 return t1;
0280 }
0281
0282 static time_t cdash_current_time(char *strtime) {
0283 time_t t1;
0284 struct tm d1;
0285 char s[20];
0286 size_t i;
0287
0288 t1 = time(0);
0289 gmtime_r(&t1, &d1);
0290
0291 if(strtime == NULL)
0292 return t1;
0293
0294 i = strftime(s, 20, "%b %d %H:%M EDT", &d1);
0295
0296 strncpy(strtime, s, i+1);
0297
0298 return t1;
0299 }
0300
0301 static double cdash_enlapsed_time(time_t t1, time_t t2) {
0302 double diff;
0303
0304 diff = difftime(t2, t1);
0305 return (diff == 0 ? 0 : (diff / 60));
0306 }
0307
0308 #ifdef __cplusplus
0309 }
0310 #endif