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 <stdlib.h>
17570af302Sopenharmony_ci
18570af302Sopenharmony_ci#include "test-malloc-info-stats-print.h"
19570af302Sopenharmony_ci#include "libxml/parser.h"
20570af302Sopenharmony_ci
21570af302Sopenharmony_cistatic const xmlChar *get_text_from_children(xmlNodePtr children)
22570af302Sopenharmony_ci{
23570af302Sopenharmony_ci	for (xmlNodePtr child_node = children; child_node != NULL; child_node = child_node->next) {
24570af302Sopenharmony_ci		if (child_node->type == XML_TEXT_NODE) {
25570af302Sopenharmony_ci			return child_node->content;
26570af302Sopenharmony_ci		}
27570af302Sopenharmony_ci	}
28570af302Sopenharmony_ci	return NULL;
29570af302Sopenharmony_ci}
30570af302Sopenharmony_ci
31570af302Sopenharmony_cistatic const xmlChar *get_attribute(const char *attr_name, xmlNodePtr node)
32570af302Sopenharmony_ci{
33570af302Sopenharmony_ci	for (xmlAttrPtr curr_attr = node->properties; curr_attr != NULL; curr_attr = curr_attr->next) {
34570af302Sopenharmony_ci		if (xmlStrEqual(curr_attr->name, (const xmlChar *) attr_name)) {
35570af302Sopenharmony_ci			return get_text_from_children(curr_attr->children);
36570af302Sopenharmony_ci		}
37570af302Sopenharmony_ci	}
38570af302Sopenharmony_ci	return NULL;
39570af302Sopenharmony_ci}
40570af302Sopenharmony_ci
41570af302Sopenharmony_cistatic xmlNodePtr find_child_node_with_attr(const char *name, const char *attr_name, const char *attr_value, xmlNodePtr parent)
42570af302Sopenharmony_ci{
43570af302Sopenharmony_ci	if (parent == NULL) {
44570af302Sopenharmony_ci		return NULL;
45570af302Sopenharmony_ci	}
46570af302Sopenharmony_ci	for (xmlNodePtr curr_node = parent->children; curr_node != NULL; curr_node = curr_node->next) {
47570af302Sopenharmony_ci		if (curr_node->type == XML_ELEMENT_NODE && xmlStrEqual(curr_node->name, (xmlChar *) name)) {
48570af302Sopenharmony_ci			if (attr_name == NULL) {
49570af302Sopenharmony_ci				return curr_node;
50570af302Sopenharmony_ci			}
51570af302Sopenharmony_ci			if (xmlStrEqual(get_attribute(attr_name, curr_node), (const xmlChar *) attr_value)) {
52570af302Sopenharmony_ci				return curr_node;
53570af302Sopenharmony_ci			}
54570af302Sopenharmony_ci		}
55570af302Sopenharmony_ci	}
56570af302Sopenharmony_ci	return NULL;
57570af302Sopenharmony_ci}
58570af302Sopenharmony_ci
59570af302Sopenharmony_cistatic xmlNodePtr find_child_node(const char *name, xmlNodePtr parent)
60570af302Sopenharmony_ci{
61570af302Sopenharmony_ci	return find_child_node_with_attr(name, NULL, NULL, parent);
62570af302Sopenharmony_ci}
63570af302Sopenharmony_ci
64570af302Sopenharmony_cistatic const char *get_node_text(xmlNodePtr node_ptr)
65570af302Sopenharmony_ci{
66570af302Sopenharmony_ci	if (node_ptr == NULL) {
67570af302Sopenharmony_ci		return NULL;
68570af302Sopenharmony_ci	}
69570af302Sopenharmony_ci	return (const char *) get_text_from_children(node_ptr->children);
70570af302Sopenharmony_ci}
71570af302Sopenharmony_ci
72570af302Sopenharmony_cistatic void stderr_stats_cb(void)
73570af302Sopenharmony_ci{
74570af302Sopenharmony_ci	malloc_info(0, stderr);
75570af302Sopenharmony_ci}
76570af302Sopenharmony_ci
77570af302Sopenharmony_cistatic long long parse_amount(const char *s)
78570af302Sopenharmony_ci{
79570af302Sopenharmony_ci	if (s == NULL) {
80570af302Sopenharmony_ci		return -1;
81570af302Sopenharmony_ci	}
82570af302Sopenharmony_ci	char *end_ptr;
83570af302Sopenharmony_ci	long long result = strtoll(s, &end_ptr, 10);
84570af302Sopenharmony_ci	if (end_ptr != s + strlen(s)) {
85570af302Sopenharmony_ci		return -1;
86570af302Sopenharmony_ci	}
87570af302Sopenharmony_ci	if (result < 0) {
88570af302Sopenharmony_ci		return -1;
89570af302Sopenharmony_ci	}
90570af302Sopenharmony_ci	return result;
91570af302Sopenharmony_ci}
92570af302Sopenharmony_ci
93570af302Sopenharmony_cistatic xmlNodePtr find_thread_in_document(xmlDocPtr doc_ptr, const char *thread_id)
94570af302Sopenharmony_ci{
95570af302Sopenharmony_ci	xmlNodePtr root_element = xmlDocGetRootElement(doc_ptr);
96570af302Sopenharmony_ci	return find_child_node_with_attr("thread", "id", thread_id, find_child_node("threads", root_element));
97570af302Sopenharmony_ci}
98570af302Sopenharmony_ci
99570af302Sopenharmony_cistatic int populate_thread_stats(const char *output, const char *thread_id, malloc_thread_stats_t *stats)
100570af302Sopenharmony_ci{
101570af302Sopenharmony_ci	xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
102570af302Sopenharmony_ci	if (doc_ptr == NULL) {
103570af302Sopenharmony_ci		return 0;
104570af302Sopenharmony_ci	}
105570af302Sopenharmony_ci	xmlNodePtr thread_root = find_thread_in_document(doc_ptr, thread_id);
106570af302Sopenharmony_ci	long long total_allocated_memory =
107570af302Sopenharmony_ci		parse_amount(get_node_text(find_child_node("total_allocated_memory", thread_root)));
108570af302Sopenharmony_ci	long long total_mmapped_memory =
109570af302Sopenharmony_ci		parse_amount(get_node_text(find_child_node("total_mmapped_memory", thread_root)));
110570af302Sopenharmony_ci	long long mmapped_regions =
111570af302Sopenharmony_ci		parse_amount(get_node_text(find_child_node("mmapped_regions", thread_root)));
112570af302Sopenharmony_ci	xmlFreeDoc(doc_ptr);
113570af302Sopenharmony_ci
114570af302Sopenharmony_ci	if (total_allocated_memory == -1 || total_mmapped_memory == -1 || mmapped_regions == -1) {
115570af302Sopenharmony_ci		return 0;
116570af302Sopenharmony_ci	}
117570af302Sopenharmony_ci	stats->total_allocated_memory = total_allocated_memory;
118570af302Sopenharmony_ci	stats->total_mmapped_memory = total_mmapped_memory;
119570af302Sopenharmony_ci	stats->mmapped_regions = mmapped_regions;
120570af302Sopenharmony_ci	return 1;
121570af302Sopenharmony_ci}
122570af302Sopenharmony_ci
123570af302Sopenharmony_cistatic int populate_total_free_heap_space(const char *output, long long *total_free_heap_space)
124570af302Sopenharmony_ci{
125570af302Sopenharmony_ci	xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
126570af302Sopenharmony_ci	if (doc_ptr == NULL) {
127570af302Sopenharmony_ci		return 0;
128570af302Sopenharmony_ci	}
129570af302Sopenharmony_ci	xmlNodePtr heap_space_root = find_child_node("total_free_heap_space", xmlDocGetRootElement(doc_ptr));
130570af302Sopenharmony_ci	long long total_free_heap_space_parsed = parse_amount(get_node_text(heap_space_root));
131570af302Sopenharmony_ci	xmlFreeDoc(doc_ptr);
132570af302Sopenharmony_ci
133570af302Sopenharmony_ci	if (total_free_heap_space_parsed == -1) {
134570af302Sopenharmony_ci		return 0;
135570af302Sopenharmony_ci	}
136570af302Sopenharmony_ci	*total_free_heap_space = total_free_heap_space_parsed;
137570af302Sopenharmony_ci	return 1;
138570af302Sopenharmony_ci}
139570af302Sopenharmony_ci
140570af302Sopenharmony_cistatic int is_thread_in_output(const char *output, const char *thread_id)
141570af302Sopenharmony_ci{
142570af302Sopenharmony_ci	xmlDocPtr doc_ptr = xmlParseDoc((const xmlChar *) output);
143570af302Sopenharmony_ci	if (doc_ptr == NULL) {
144570af302Sopenharmony_ci		return 0;
145570af302Sopenharmony_ci	}
146570af302Sopenharmony_ci	int result = find_thread_in_document(doc_ptr, thread_id) != NULL;
147570af302Sopenharmony_ci	xmlFreeDoc(doc_ptr);
148570af302Sopenharmony_ci	return result;
149570af302Sopenharmony_ci}
150