1570af302Sopenharmony_ci/*
2570af302Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4570af302Sopenharmony_ci * you may not use this file except in compliance with the License.
5570af302Sopenharmony_ci * You may obtain a copy of the License at
6570af302Sopenharmony_ci *
7570af302Sopenharmony_ci *    http://www.apache.org/licenses/LICENSE-2.0
8570af302Sopenharmony_ci *
9570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12570af302Sopenharmony_ci * See the License for the specific language governing permissions and
13570af302Sopenharmony_ci * limitations under the License.
14570af302Sopenharmony_ci */
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci#include <regex.h>
17570af302Sopenharmony_ci#include "test-malloc-info-stats-print.h"
18570af302Sopenharmony_ci
19570af302Sopenharmony_ci#define THREAD_DATA_REGEX_LEN (MAX_TID_LEN + 43)
20570af302Sopenharmony_ci#define REGEX_NMATCH 1
21570af302Sopenharmony_ci
22570af302Sopenharmony_cistatic void stderr_stats_cb(void)
23570af302Sopenharmony_ci{
24570af302Sopenharmony_ci	malloc_stats_print(print_to_file, stderr, "");
25570af302Sopenharmony_ci}
26570af302Sopenharmony_ci
27570af302Sopenharmony_cistatic int parse_amount(const char **s, long long *destination)
28570af302Sopenharmony_ci{
29570af302Sopenharmony_ci	char *end_ptr = NULL;
30570af302Sopenharmony_ci	long long result = strtoll(*s, &end_ptr, 10);
31570af302Sopenharmony_ci	if (end_ptr == *s) {
32570af302Sopenharmony_ci		return 0;
33570af302Sopenharmony_ci	}
34570af302Sopenharmony_ci	*s = end_ptr;
35570af302Sopenharmony_ci	if ((!isspace(*end_ptr) && *end_ptr != '\n' && *end_ptr != '\0') || result < 0) {
36570af302Sopenharmony_ci		return 0;
37570af302Sopenharmony_ci	}
38570af302Sopenharmony_ci	*destination = result;
39570af302Sopenharmony_ci	return 1;
40570af302Sopenharmony_ci}
41570af302Sopenharmony_ci
42570af302Sopenharmony_cistatic const char *find_thread_in_output(const char *output, const char *thread_id)
43570af302Sopenharmony_ci{
44570af302Sopenharmony_ci	char thread_data_regex_s[THREAD_DATA_REGEX_LEN + 1];
45570af302Sopenharmony_ci	snprintf(thread_data_regex_s, THREAD_DATA_REGEX_LEN, "^%s([[:space:]]+[[:digit:]]+){3}[[:space:]]*$", thread_id);
46570af302Sopenharmony_ci	regex_t thread_data_regex;
47570af302Sopenharmony_ci	if (regcomp(&thread_data_regex, thread_data_regex_s, REG_EXTENDED | REG_NEWLINE) != 0) {
48570af302Sopenharmony_ci		t_error("Failed to compile regex %s", thread_data_regex_s);
49570af302Sopenharmony_ci		return NULL;
50570af302Sopenharmony_ci	}
51570af302Sopenharmony_ci
52570af302Sopenharmony_ci	regmatch_t pmatch[REGEX_NMATCH];
53570af302Sopenharmony_ci	int match_result = regexec(&thread_data_regex, output, REGEX_NMATCH, pmatch, 0);
54570af302Sopenharmony_ci	regfree(&thread_data_regex);
55570af302Sopenharmony_ci	if (match_result != 0) {
56570af302Sopenharmony_ci		return NULL;
57570af302Sopenharmony_ci	}
58570af302Sopenharmony_ci	return output + pmatch[0].rm_so;
59570af302Sopenharmony_ci}
60570af302Sopenharmony_ci
61570af302Sopenharmony_cistatic int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats)
62570af302Sopenharmony_ci{
63570af302Sopenharmony_ci	const char *thread_data_start = find_thread_in_output(output, thread_id);
64570af302Sopenharmony_ci	if (thread_data_start == NULL) {
65570af302Sopenharmony_ci		t_error("Failed to find thread id %s in output", thread_id);
66570af302Sopenharmony_ci		return 0;
67570af302Sopenharmony_ci	}
68570af302Sopenharmony_ci
69570af302Sopenharmony_ci	thread_data_start += strlen(thread_id);
70570af302Sopenharmony_ci	int result = 1;
71570af302Sopenharmony_ci	result &= parse_amount(&thread_data_start, &stats->total_allocated_memory);
72570af302Sopenharmony_ci	result &= parse_amount(&thread_data_start, &stats->total_mmapped_memory);
73570af302Sopenharmony_ci	result &= parse_amount(&thread_data_start, &stats->mmapped_regions);
74570af302Sopenharmony_ci
75570af302Sopenharmony_ci	return result;
76570af302Sopenharmony_ci}
77570af302Sopenharmony_ci
78570af302Sopenharmony_cistatic int populate_total_free_heap_space(const char *output, long long *total_free_heap_space)
79570af302Sopenharmony_ci{
80570af302Sopenharmony_ci	const char *free_heap_space_start = strstr(output, "total free heap space:");
81570af302Sopenharmony_ci	if (free_heap_space_start == NULL) {
82570af302Sopenharmony_ci		return 0;
83570af302Sopenharmony_ci	}
84570af302Sopenharmony_ci	free_heap_space_start += strlen("total free heap space:");
85570af302Sopenharmony_ci	return parse_amount(&free_heap_space_start, total_free_heap_space);
86570af302Sopenharmony_ci}
87570af302Sopenharmony_ci
88570af302Sopenharmony_cistatic int is_thread_in_output(const char *output, const char *thread_id)
89570af302Sopenharmony_ci{
90570af302Sopenharmony_ci	return find_thread_in_output(output, thread_id) != NULL;
91570af302Sopenharmony_ci}