1# Copyright 2020 - The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import unittest 16import gdb 17import json 18 19 20def remove_gdb_output_prefix(str): 21 """ gdb output contains a "$%d =" prefix, the function remove the prefix 22 """ 23 idx = str.find("=") 24 return str[idx + 1:] 25 26 27def check_type_and_ctype(input_json, input_type, ctype): 28 assert(input_json["type"] == input_type) 29 assert(input_json["ctype"] == ctype) 30 31 32def check_basic_value(input_json, input_type, ctype, value): 33 check_type_and_ctype(input_json, input_type, ctype) 34 assert(input_json["value"] == value) 35 36 37def gdb_extract_variable_to_json(variable_name): 38 """ extract a variable from gdb 39 40 Args: 41 variable_name: 42 a string, the name of the variable to extract 43 Returns: 44 A json Object in Python 45 """ 46 variable = gdb.execute("p {}".format(variable_name), to_string=True) 47 variable = remove_gdb_output_prefix(variable) 48 variable_json = json.loads(variable) 49 return variable_json 50 51 52def json_equal_except_address(testcase, json0, json1): 53 """ check if all content of two json are same except the address fields 54 55 The function will check the two json objects recursively to set address fields to None, 56 then convert two json objects into strings with sorted keys, and check if the two strings 57 are same. 58 """ 59 def replace_address_by_None(input_json): 60 if isinstance(input_json, dict): 61 for (k, v) in input_json.items(): 62 if k == "address": 63 input_json[k] = None 64 else: 65 replace_address_by_None(v) 66 elif isinstance(input_json, list): 67 for item in input_json: 68 replace_address_by_None(item) 69 70 replace_address_by_None(json0) 71 replace_address_by_None(json1) 72 json0 = json.dumps(json0, sort_keys=True) 73 json1 = json.dumps(json1, sort_keys=True) 74 testcase.assertEqual(json0, json1) 75 76 77def test_json_variable(testcase, testname, line, variable_name_list): 78 for variable_name in variable_name_list: 79 variable_json = gdb_extract_variable_to_json(variable_name) 80 with open("test/{}_{}_{}.json".format(testname, str(line), variable_name), "r") as f: 81 expect_variable = json.load(f) 82 json_equal_except_address(testcase, variable_json, expect_variable) 83 84 85class TestGdbJsonPrinter(unittest.TestCase): 86 87 def __init__(self, *args, **kwargs): 88 super().__init__(*args, **kwargs) 89 self.maxDiff = None 90 91 def test_basic_types(self): 92 gdb.execute("file test_examples/basic_types") 93 gdb.execute("b 42") 94 gdb.execute("r") 95 96 variable_json = gdb_extract_variable_to_json("a") 97 check_basic_value(variable_json, "int", "uint8_t", "1") 98 99 variable_json = gdb_extract_variable_to_json("a") 100 check_basic_value(variable_json, "int", "uint8_t", "1") 101 102 variable_json = gdb_extract_variable_to_json("b") 103 check_basic_value(variable_json, "int", "int8_t", "-2") 104 105 variable_json = gdb_extract_variable_to_json("c") 106 check_basic_value(variable_json, "int", "uint16_t", "3") 107 108 variable_json = gdb_extract_variable_to_json("d") 109 check_basic_value(variable_json, "int", "int16_t", "-4") 110 111 variable_json = gdb_extract_variable_to_json("e") 112 check_basic_value(variable_json, "int", "uint32_t", "5") 113 114 variable_json = gdb_extract_variable_to_json("f") 115 check_basic_value(variable_json, "int", "int32_t", "-6") 116 117 variable_json = gdb_extract_variable_to_json("g") 118 check_basic_value(variable_json, "int", "uint64_t", "7") 119 120 variable_json = gdb_extract_variable_to_json("h") 121 check_basic_value(variable_json, "int", "int64_t", "-8") 122 123 variable_json = gdb_extract_variable_to_json("i") 124 check_basic_value(variable_json, "float", "float", "9.0") 125 126 variable_json = gdb_extract_variable_to_json("j") 127 check_basic_value(variable_json, "float", "double", "-10.0") 128 129 variable_json = gdb_extract_variable_to_json("k") 130 check_type_and_ctype(variable_json, "pointer", "const char *") 131 check_basic_value( 132 variable_json["reference"], "int", "const char", "72") 133 134 variable_json = gdb_extract_variable_to_json("l") 135 check_type_and_ctype(variable_json, "pointer", "void *") 136 assert(variable_json["reference"] == "cannot extract void ptr") 137 138 variable_json = gdb_extract_variable_to_json("m") 139 check_type_and_ctype(variable_json, "pointer", "char *") 140 assert(variable_json["reference"] == "nullptr") 141 142 variable_json = gdb_extract_variable_to_json("o") 143 check_basic_value(variable_json, "enum", "Animal", "0") 144 145 gdb.execute("b 61") 146 gdb.execute("c") 147 148 variable_json = gdb_extract_variable_to_json("a") 149 check_basic_value(variable_json, "int", "const uint8_t", "1") 150 151 variable_json = gdb_extract_variable_to_json("a") 152 check_basic_value(variable_json, "int", "const uint8_t", "1") 153 154 variable_json = gdb_extract_variable_to_json("b") 155 check_basic_value(variable_json, "int", "const int8_t", "-2") 156 157 variable_json = gdb_extract_variable_to_json("c") 158 check_basic_value(variable_json, "int", "const uint16_t", "3") 159 160 variable_json = gdb_extract_variable_to_json("d") 161 check_basic_value(variable_json, "int", "const int16_t", "-4") 162 163 variable_json = gdb_extract_variable_to_json("e") 164 check_basic_value(variable_json, "int", "const uint32_t", "5") 165 166 variable_json = gdb_extract_variable_to_json("f") 167 check_basic_value(variable_json, "int", "const int32_t", "-6") 168 169 variable_json = gdb_extract_variable_to_json("g") 170 check_basic_value(variable_json, "int", "const uint64_t", "7") 171 172 variable_json = gdb_extract_variable_to_json("h") 173 check_basic_value(variable_json, "int", "const int64_t", "-8") 174 175 variable_json = gdb_extract_variable_to_json("i") 176 check_basic_value(variable_json, "float", "const float", "9.0") 177 178 variable_json = gdb_extract_variable_to_json("j") 179 check_basic_value(variable_json, "float", "const double", "-10.0") 180 181 variable_json = gdb_extract_variable_to_json("k") 182 check_type_and_ctype(variable_json, "pointer", "const char *") 183 check_basic_value( 184 variable_json["reference"], "int", "const char", "72") 185 186 variable_json = gdb_extract_variable_to_json("l") 187 check_type_and_ctype(variable_json, "pointer", "const void *") 188 assert(variable_json["reference"] == "cannot extract void ptr") 189 190 variable_json = gdb_extract_variable_to_json("m") 191 check_type_and_ctype(variable_json, "pointer", "const char *") 192 assert(variable_json["reference"] == "nullptr") 193 194 variable_json = gdb_extract_variable_to_json("o") 195 check_basic_value(variable_json, "enum", "const Animal", "1") 196 197 def test_objects(self): 198 gdb.execute("file test_examples/objects") 199 gdb.execute("b 37") 200 gdb.execute("r") 201 test_json_variable(self, "objects", 37, ["bar", "foo"]) 202 203 def test_objects1(self): 204 gdb.execute("file test_examples/objects1") 205 gdb.execute("b 41") 206 gdb.execute("r") 207 test_json_variable(self, "objects1", 41, ["bar", "foo"]) 208 209 def test_objects2(self): 210 gdb.execute("file test_examples/objects2") 211 gdb.execute("b 85") 212 gdb.execute("r") 213 test_json_variable( 214 self, 215 "objects2", 216 85, 217 ["a", "b", "c", "d", "e", "f", "w", "x", "y", "z"]) 218 219 def test_array(self): 220 gdb.execute("file test_examples/array") 221 gdb.execute("b 42") 222 gdb.execute("r") 223 test_json_variable(self, "array", 42, ["a", "b", "bar", "foo"]) 224 225 def test_reference(self): 226 gdb.execute("file test_examples/reference") 227 gdb.execute("b 41") 228 gdb.execute("r") 229 test_json_variable( 230 self, 231 "reference", 232 41, 233 ["bar", "foo", "bar_ref", "foo_ref", "bar_ptr", "foo_ptr"]) 234 235 236unittest.main() 237