void cloader_destruct(MuLoader* _self, MuLibrary* _library, MuError** err) { CLibrary* library = (CLibrary*) _library; MuTestResult* result = NULL; if (library->library_destruct) { result = cloader_run_thunk_inproc(library->library_destruct->run); if (result->status != MU_STATUS_SUCCESS) { MU_RAISE_GOTO(error, err, MU_ERROR_CONSTRUCT_LIBRARY, "%s", result->reason); } } error: if (result) { cloader_free_result(_self, result); } }
// 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; }