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