static void library_enter(MuLogger* _self, const char* path, MuLibrary* library) { XmlLogger* self = (XmlLogger*) _self; if (library) { fprintf(self->out, INDENT_LIBRARY "<library file=\"%s\" name=\"%s\">\n", basename_pure(path), mu_library_name(library)); } else { fprintf(self->out, INDENT_LIBRARY "<library file=\"%s\">\n", basename_pure(path)); } }
static void test_log(MuLogger* _self, MuLogEvent* event) { XmlLogger* self = (XmlLogger*) _self; const char* level_str = "unknown"; switch (event->level) { case MU_LEVEL_WARNING: level_str = "warning"; break; case MU_LEVEL_INFO: level_str = "info"; break; case MU_LEVEL_VERBOSE: level_str = "verbose"; break; case MU_LEVEL_DEBUG: level_str = "debug"; break; case MU_LEVEL_TRACE: level_str = "trace"; break; } fprintf(self->out, INDENT_TEST INDENT "<event level=\"%s\"", level_str); fprintf(self->out, " stage=\"%s\"", mu_test_stage_to_string(event->stage)); if (event->file) fprintf(self->out, " file=\"%s\"", basename_pure(event->file)); if (event->line) fprintf(self->out, " line=\"%u\"", event->line); fprintf(self->out, ">"); fprintf(self->out, "<![CDATA[%s]]>", event->message); fprintf(self->out, "</event>\n"); }
// Opens a library and returns a handle static struct MuLibrary* sh_open (struct MuLoader* self, const char* path, MuError** err) { ShLibrary* library = NULL; Process handle; array* tests = NULL; char* line = NULL; char* dot = NULL; unsigned int len; struct stat statbuf; /* As a sanity check, make sure the file is actually valid */ if (stat(path, &statbuf) != 0) { MU_RAISE_GOTO(error, err, MU_ERROR_LOAD_LIBRARY, "%s: %s", path, strerror(errno)); } if (!S_ISREG(statbuf.st_mode)) { MU_RAISE_GOTO(error, err, MU_ERROR_LOAD_LIBRARY, "%s: not a file", path); } library = calloc(1, sizeof(ShLibrary)); library->base.loader = self; library->path = strdup(path); library->name = strdup(basename_pure(path)); dot = strrchr(library->name, '.'); if (dot) { *dot = '\0'; } mu_sh_exec(&handle, path, "mu_enum_test_functions >& ${MU_CMD_OUT}"); while ((len = process_channel_read_line(&handle, 4, &line))) { ShTest* test = calloc(1, sizeof(ShTest)); char* div1, *div2; line[len-1] = '\0'; div1 = strchr(line, '_'); div2 = strchr(div1+1, '_'); if (div1 && div2) { test->base.loader = self; test->base.library = (MuLibrary*) library; test->function = strdup(line); *div1 = *div2 = '\0'; test->suite = strdup(div1+1); test->name = strdup(div2+1); tests = array_append(tests, test); } free(line); } process_close(&handle); library->tests = (ShTest**) tests; error: return (MuLibrary*) library; }
MuLibrary* cloader_open(MuLoader* _self, const char* path, MuError** _err) { CLibrary* library = xmalloc(sizeof (CLibrary)); MuError* err = NULL; void (*stub_hook)(MuEntryInfo*** es); char *last_dot; if (!library) { MU_RAISE_GOTO(error, _err, MU_ERROR_MEMORY, "Out of memory"); } library->base.loader = _self; library->tests = NULL; library->fixture_setups = NULL; library->fixture_teardowns = NULL; library->library_setup = NULL; library->library_teardown = NULL; library->library_construct = NULL; library->library_destruct = NULL; library->path = strdup(path); library->name = NULL; library->dlhandle = mu_dlopen(library->path, RTLD_NOW); if (!library->dlhandle) { MU_RAISE_GOTO(error, _err, MU_ERROR_LOAD_LIBRARY, "%s", dlerror()); } if ((stub_hook = dlsym(library->dlhandle, "__mu_stub_hook"))) { int i; MuEntryInfo** entries; stub_hook(&entries); for (i = 0; entries[i]; i++) { if (!add(entries[i], library, &err)) { MU_RERAISE_GOTO(error, _err, err); } } } #ifdef HAVE_LIBELF else if (!cloader_scan(_self, library, &err)) { MU_RERAISE_GOTO(error, _err, err); } #else else { MU_RAISE_GOTO(error, _err, MU_ERROR_LOAD_LIBRARY, "Library did not contain a loading stub " "and reflection is unavailable"); } #endif /* If an explicit library name was not available, create one */ if (!library->name) { library->name = strdup(basename_pure(path)); if (!library->name) { MU_RAISE_GOTO(error, _err, MU_ERROR_MEMORY, "Out of memory"); } last_dot = strrchr(library->name, '.'); if (last_dot) { *last_dot = '\0'; } } return (MuLibrary*) library; error: if (library) { cloader_close(_self, (MuLibrary*) library); } return NULL; }
static void test_leave(MuLogger* _self, MuTest* test, MuTestResult* summary) { XmlLogger* self = (XmlLogger*) _self; const char* stage; FILE* out = self->out; bool result = summary->status == summary->expected; const char* result_str; if (summary->status == MU_STATUS_DEBUG) { result_str = "debug"; } else if (result) { switch (summary->status) { case MU_STATUS_SUCCESS: result_str = "pass"; break; case MU_STATUS_SKIPPED: result_str = "skip"; break; default: result_str = "xfail"; break; } } else { switch (summary->status) { case MU_STATUS_SUCCESS: result_str = "xpass"; break; case MU_STATUS_SKIPPED: result_str = "skip"; break; default: result_str = "fail"; break; } } if (summary->status == MU_STATUS_SUCCESS) { fprintf(out, INDENT_TEST INDENT "<result status=\"%s\"/>\n", result_str); } else { stage = mu_test_stage_to_string(summary->stage); if (summary->reason) { fprintf(out, INDENT_TEST INDENT "<result status=\"%s\" stage=\"%s\"", result_str, stage); if (summary->file) fprintf(out, " file=\"%s\"", basename_pure(summary->file)); if (summary->line) fprintf(out, " line=\"%i\"", summary->line); fprintf(out, ">"); fprintf(out, "<![CDATA[%s]]>", summary->reason); fprintf(out, "</result>\n"); } else { fprintf(out, INDENT_TEST INDENT "<result status=\"fail\" stage=\"%s\"", stage); if (summary->file) fprintf(out, " file=\"%s\"", basename_pure(summary->file)); if (summary->line) fprintf(out, " line=\"%i\"", summary->line); fprintf(out, "/>\n"); } } if (summary->backtrace) { MuBacktrace* frame; fprintf(out, INDENT_TEST INDENT "<backtrace>\n"); for (frame = summary->backtrace; frame; frame = frame->up) { fprintf(out, INDENT_TEST INDENT INDENT "<frame"); if (frame->file_name) { fprintf(out, " binary_file=\"%s\"", frame->file_name); } if (frame->func_name) { fprintf(out, " function=\"%s\"", frame->func_name); } if (frame->func_addr) { fprintf(out, " func_addr=\"%lx\"", frame->func_addr); } if (frame->return_addr) { fprintf(out, " return_addr=\"%lx\"", frame->return_addr); } fprintf(out, "/>\n"); } fprintf(out, INDENT_TEST " </backtrace>\n"); } fprintf(out, INDENT_TEST "</test>\n"); }