forked from cgreen-devs/cgreen
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
365 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,108 @@ | ||
#include "discoverer.h" | ||
|
||
#include "io.h" | ||
|
||
#include <dlfcn.h> | ||
#include <link.h> | ||
#include <string.h> | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
|
||
#include <cgreen/internal/unit_implementation.h> | ||
|
||
#include "../src/utils.h" | ||
|
||
|
||
#include "dl_adapter.h" | ||
#include "test_item.h" | ||
|
||
#ifdef UNITTESTING | ||
int printf_unittesting(const char *fmt, ...); | ||
#ifdef printf | ||
#undef printf | ||
#endif | ||
#define printf printf_unittesting | ||
#endif | ||
|
||
static const char *cgreen_spec_start_of(const char *line) { | ||
return strstr(line, CGREEN_SPEC_PREFIX CGREEN_SEPARATOR); | ||
} | ||
|
||
static bool contains_cgreen_spec(const char *line) { | ||
return cgreen_spec_start_of(line) != NULL; | ||
static bool starts_with_cgreen_spec(const char *line) { | ||
return cgreen_spec_start_of(line) == line; | ||
} | ||
|
||
static bool is_definition(const char *line) { | ||
return strstr(line, " D ") != NULL; | ||
} | ||
|
||
static bool complete_line_read(char line[]) { | ||
return line[strlen(line)-1] == '\n'; | ||
} | ||
|
||
|
||
static void strip_newline_from(char *name) { | ||
if (name[strlen(name)-1] == '\n') | ||
name[strlen(name)-1] = '\0'; | ||
} | ||
|
||
static void add_all_tests_from(FILE *nm_output_pipe, CgreenVector *tests, bool verbose) { | ||
char line[1000]; | ||
int length = read_line(nm_output_pipe, line, sizeof(line)-1); | ||
while (length > -1) { /* TODO: >0 ? */ | ||
if (!complete_line_read(line)) | ||
PANIC("Too long line in nm output"); | ||
if (contains_cgreen_spec(line) && is_definition(line)) { | ||
strip_newline_from(line); | ||
TestItem *test_item = create_test_item_from(cgreen_spec_start_of(line)); | ||
static void add_all_tests_from(ElfW(Sym) *symbols, char *symbol_str, long symbol_size, CgreenVector *tests, bool verbose) { | ||
int size = symbol_str - (char *)symbols; | ||
for (int k = 0; k < size / symbol_size; ++k) | ||
{ | ||
ElfW(Sym) * sym = &symbols[k]; | ||
// If sym is function | ||
if ((ELF64_ST_TYPE(symbols[k].st_info) == STT_OBJECT) | ||
&& starts_with_cgreen_spec(&symbol_str[sym->st_name])) | ||
{ | ||
TestItem *test_item = create_test_item_from(cgreen_spec_start_of(&symbol_str[sym->st_name])); | ||
if (verbose) | ||
printf("Discovered %s:%s (%s)\n", test_item->context_name, test_item->test_name, | ||
test_item->specification_name); | ||
cgreen_vector_add(tests, test_item); | ||
} | ||
length = read_line(nm_output_pipe, line, sizeof(line)-1); | ||
} | ||
} | ||
|
||
/* Read in the dynamic symbols. */ | ||
static ElfW(Sym) *get_symbols_table(struct link_map *map, long *symbol_size, char **symbol_str) | ||
{ | ||
ElfW(Sym) *symtab = NULL; | ||
*symbol_size = 0; | ||
for (ElfW(Dyn) *section = map->l_ld; section->d_tag != DT_NULL; ++section) | ||
{ | ||
if (section->d_tag == DT_SYMTAB) | ||
{ | ||
symtab = (ElfW(Sym) *)section->d_un.d_ptr; | ||
} | ||
else if (section->d_tag == DT_STRTAB) | ||
{ | ||
*symbol_str = (char*)section->d_un.d_ptr; | ||
} | ||
else if (section->d_tag == DT_SYMENT) | ||
{ | ||
*symbol_size = section->d_un.d_val; | ||
} | ||
} | ||
return symtab; | ||
} | ||
|
||
CgreenVector *discover_tests_in(const char *filename, bool verbose) { | ||
FILE *library = open_file(filename, "r"); | ||
if (library == NULL) | ||
void *handle = dl_adapter_open(filename, RTLD_LAZY | RTLD_GLOBAL); | ||
if (!handle) { | ||
if (verbose) | ||
printf("%s: dl_adapter_open failed\n", filename); | ||
return NULL; | ||
} | ||
|
||
struct link_map *map = NULL; | ||
int loadInforResult = dl_adapter_info(handle, RTLD_DI_LINKMAP, &map); | ||
if (loadInforResult == -1) { | ||
if (verbose) | ||
printf("%s: dl_atapter_info failed\n", filename); | ||
dl_adapter_close(handle); | ||
return NULL; | ||
close_file(library); | ||
} | ||
|
||
ElfW(Sym) *symbols = NULL; | ||
char *symbol_str = NULL; | ||
long symbol_size = 0; | ||
symbols = get_symbols_table(handle, &symbol_size, &symbol_str); | ||
|
||
char nm_command[1000]; | ||
sprintf(nm_command, "/usr/bin/nm '%s'", filename); | ||
FILE *nm_output_pipe = open_process(nm_command, "r"); | ||
if (nm_output_pipe == NULL) | ||
if ((symbols == NULL) || (symbol_str == NULL) || (symbol_size <= 0)) { | ||
if (verbose) | ||
printf("%s: couldn't find any symbol\n", filename); | ||
dl_adapter_close(handle); | ||
return NULL; | ||
} | ||
|
||
CgreenVector *tests = create_cgreen_vector((GenericDestructor)&destroy_test_item); | ||
add_all_tests_from(nm_output_pipe, tests, verbose); | ||
close_process(nm_output_pipe); | ||
add_all_tests_from(symbols, symbol_str, symbol_size, tests, verbose); | ||
|
||
dl_adapter_close(handle); | ||
|
||
return tests; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#include "dl_adapter.h" | ||
|
||
#include <dlfcn.h> | ||
#include <link.h> | ||
#include <limits.h> | ||
#include <sys/mman.h> | ||
|
||
void *dl_adapter_open(const char *filename, int flag) | ||
{ | ||
return dlopen(filename, flag); | ||
} | ||
|
||
int dl_adapter_close(void *handle) | ||
{ | ||
return dlclose(handle); | ||
} | ||
|
||
int dl_adapter_info(void *handle, int request, void *p) | ||
{ | ||
return dlinfo(handle, request, p); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef DL_ADAPTER_H | ||
#define DL_ADAPTER_H | ||
|
||
#include <dlfcn.h> | ||
|
||
#ifdef UNITTESTING | ||
#define dl_adapter_open dl_adapter_open_unittesting | ||
#define dl_adapter_close dl_adapter_close_unittesting | ||
#define dl_adapter_info dl_adapter_info_unittesting | ||
#endif | ||
|
||
void *dl_adapter_open(const char *filename, int flag); | ||
int dl_adapter_close(void *handle); | ||
|
||
int dl_adapter_info(void *handle, int request, void *p); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#include "dl_adapter.h" | ||
|
||
#include <cgreen/cgreen.h> | ||
#include <cgreen/mocks.h> | ||
|
||
/* Adapter to dl */ | ||
void *dl_adapter_open(const char *filename, int flag) { | ||
return (void *) mock(filename, flag); | ||
} | ||
|
||
int dl_adapter_close(void *handle) | ||
{ | ||
return (int) mock(handle); | ||
} | ||
|
||
int dl_adapter_info(void *handle, int request, void *p) | ||
{ | ||
return (int) mock(handle, request, p); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.