diff --git a/libc-test/src/functional/test-malloc-info-stats-print.h b/libc-test/src/functional/test-malloc-info-stats-print.h index e32bed40c4ca4cd217d45899606f36a86cf8d83f..8a00ac8a3fef748503b1674ed07edca8c2141926 100644 --- a/libc-test/src/functional/test-malloc-info-stats-print.h +++ b/libc-test/src/functional/test-malloc-info-stats-print.h @@ -40,9 +40,11 @@ typedef struct static void stderr_stats_cb(void); -static int populate_thread_stats(const char *input, const char *thread_id, malloc_thread_stats_t *stats); +static int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats); -static int populate_total_free_heap_space(const char *input, long long *total_free_heap_space); +static int populate_total_free_heap_space(const char *output, long long *total_free_heap_space); + +static int is_thread_in_output(const char *output, const char *thread_id); static void print_to_file(void *fp, const char *s) { @@ -190,7 +192,7 @@ static int validate_different_threads_test_results(test_results_t *test_results) malloc_thread_stats_t thread_stats; result &= populate_thread_stats(test_results->stats_after_allocations, test_results->threads[i], &thread_stats); result &= validate_allocated_size(sizes[i], &thread_stats); - if (strstr(test_results->stats_after_free, test_results->threads[i]) != NULL) + if (is_thread_in_output(test_results->stats_after_free, test_results->threads[i])) { t_error("Thread %s did not disappear from output\n", test_results->threads[i]); result = 0; diff --git a/libc-test/src/functional/test-malloc-info.c b/libc-test/src/functional/test-malloc-info.c index e069c19d6e572a2add244c8a6899c3c3d6ff65a0..e2a37f293cc871db029c5b0ceff689e4ede47a39 100644 --- a/libc-test/src/functional/test-malloc-info.c +++ b/libc-test/src/functional/test-malloc-info.c @@ -103,24 +103,24 @@ static long long parse_amount(const char *s) return result; } -static int populate_thread_stats(const char *input, const char *thread_id, malloc_thread_stats_t *stats) +static xmlNodePtr find_thread_in_document(xmlDocPtr doc_ptr, const char *thread_id) { - xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *)input); - if (doc_ptr == NULL) - { - return 0; - } xmlNodePtr root_element = xmlDocGetRootElement(doc_ptr); - xmlNodePtr thread_root; if (strcmp(thread_id, "abandoned") == 0) { - thread_root = find_child_node("abandoned", root_element); + return find_child_node("abandoned", root_element); } - else + return find_child_node_with_attr("thread", "id", thread_id, find_child_node("threads", root_element)); +} + +static int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats) +{ + xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *)output); + if (doc_ptr == NULL) { - xmlNodePtr threads = find_child_node("threads", root_element); - thread_root = find_child_node_with_attr("thread", "id", thread_id, threads); + return 0; } + xmlNodePtr thread_root = find_thread_in_document(doc_ptr, thread_id); long long total_allocated_memory = parse_amount(get_node_text(find_child_node("total_allocated_memory", thread_root))); long long total_mmapped_memory = @@ -139,9 +139,9 @@ static int populate_thread_stats(const char *input, const char *thread_id, mallo return 1; } -static int populate_total_free_heap_space(const char *input, long long *total_free_heap_space) +static int populate_total_free_heap_space(const char *output, long long *total_free_heap_space) { - xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *)input); + xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *)output); if (doc_ptr == NULL) { return 0; @@ -156,4 +156,15 @@ static int populate_total_free_heap_space(const char *input, long long *total_fr } *total_free_heap_space = total_free_heap_space_parsed; return 1; +} +static int is_thread_in_output(const char *output, const char *thread_id) +{ + xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *)output); + if (doc_ptr == NULL) + { + return 0; + } + int result = find_thread_in_document(doc_ptr, thread_id) != NULL; + xmlFreeDoc(doc_ptr); + return result; } \ No newline at end of file diff --git a/libc-test/src/functional/test-malloc-stats-print.c b/libc-test/src/functional/test-malloc-stats-print.c index 0a4976c03bc4b0c441bf382c1e9ed0a67bdacde5..c6469a695ec79cfecd6833e46aaa307f29d3e90f 100644 --- a/libc-test/src/functional/test-malloc-stats-print.c +++ b/libc-test/src/functional/test-malloc-stats-print.c @@ -13,14 +13,18 @@ * limitations under the License. */ +#include #include "test-malloc-info-stats-print.h" +#define THREAD_DATA_REGEX_LEN (MAX_TID_LEN + 43) +#define REGEX_NMATCH 1 + static void stderr_stats_cb(void) { malloc_stats_print(print_to_file, stderr, ""); } -static int parse_amount(char **s, long long *destination) +static int parse_amount(const char **s, long long *destination) { char *end_ptr = NULL; long long result = strtoll(*s, &end_ptr, 10); @@ -35,27 +39,53 @@ static int parse_amount(char **s, long long *destination) return 1; } -static int populate_thread_stats(const char *input, const char *thread_id, malloc_thread_stats_t *stats) +static const char * find_thread_in_output(const char *output, const char *thread_id) +{ + char thread_data_regex_s[THREAD_DATA_REGEX_LEN + 1]; + snprintf(thread_data_regex_s, THREAD_DATA_REGEX_LEN, "^%s([[:space:]]+[[:digit:]]+){3}[[:space:]]*$", thread_id); + regex_t thread_data_regex; + if (regcomp(&thread_data_regex, thread_data_regex_s, REG_EXTENDED | REG_NEWLINE) != 0) { + t_error("Failed to compile regex %s", thread_data_regex_s); + return NULL; + } + + regmatch_t pmatch[REGEX_NMATCH]; + int match_result = regexec(&thread_data_regex, output, REGEX_NMATCH, pmatch, 0); + regfree(&thread_data_regex); + if (match_result != 0) { + return NULL; + } + return output + pmatch[0].rm_so; +} + +static int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats) { - char *thread_id_start = strstr(input, thread_id); - if (thread_id_start == NULL) { + const char *thread_data_start = find_thread_in_output(output, thread_id); + if (thread_data_start == NULL) { + t_error("Failed to find thread id %s in output", thread_id); return 0; } - thread_id_start += strlen(thread_id); + + thread_data_start += strlen(thread_id); int result = 1; - result &= parse_amount(&thread_id_start, &stats->total_allocated_memory); - result &= parse_amount(&thread_id_start, &stats->total_mmapped_memory); - result &= parse_amount(&thread_id_start, &stats->mmapped_regions); + result &= parse_amount(&thread_data_start, &stats->total_allocated_memory); + result &= parse_amount(&thread_data_start, &stats->total_mmapped_memory); + result &= parse_amount(&thread_data_start, &stats->mmapped_regions); return result; } -static int populate_total_free_heap_space(const char *input, long long *total_free_heap_space) +static int populate_total_free_heap_space(const char *output, long long *total_free_heap_space) { - char *free_heap_space_start = strstr(input, "total free heap space:"); + const char *free_heap_space_start = strstr(output, "total free heap space:"); if (free_heap_space_start == NULL) { return 0; } free_heap_space_start += strlen("total free heap space:"); return parse_amount(&free_heap_space_start, total_free_heap_space); } + +static int is_thread_in_output(const char *output, const char *thread_id) +{ + return find_thread_in_output(output, thread_id) != NULL; +} \ No newline at end of file