xref: /llvm-project/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py (revision 57bd882343f8e4cca598b6ad47da93476cffb987)
1"""
2Test some SBStructuredData API.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11import json
12
13
14class TestStructuredDataAPI(TestBase):
15    NO_DEBUG_INFO_TESTCASE = True
16
17    def test(self):
18        self.structured_data_api_test()
19
20    def structured_data_api_test(self):
21        error = lldb.SBError()
22        s = lldb.SBStream()
23
24        dict_str = json.dumps(
25            {
26                "key_dict": {
27                    "key_string": "STRING",
28                    "key_uint": 0xFFFFFFFF00000000,
29                    "key_sint": -42,
30                    "key_float": 2.99,
31                    "key_bool": True,
32                    "key_array": ["23", "arr"],
33                }
34            }
35        )
36        s.Print(dict_str)
37        example = lldb.SBStructuredData()
38
39        # Check SetFromJSON API for dictionaries, integers, floating point
40        # values, strings and arrays
41        error = example.SetFromJSON(s)
42        if not error.Success():
43            self.fail("FAILED:   " + error.GetCString())
44
45        # Tests for invalid data type
46        self.invalid_struct_test(example)
47
48        # Test that GetDescription works:
49        s.Clear()
50        error = example.GetDescription(s)
51        self.assertSuccess(error, "GetDescription works")
52        if not "key_float" in s.GetData():
53            self.fail("FAILED: could not find key_float in description output")
54
55        dict_struct = lldb.SBStructuredData()
56        dict_struct = example.GetValueForKey("key_dict")
57
58        # Tests for dictionary data type
59        self.dictionary_struct_test(example)
60
61        # Tests for string data type
62        self.string_struct_test(dict_struct)
63
64        # Tests for integer data type
65        self.uint_struct_test(dict_struct)
66
67        # Tests for integer data type
68        self.sint_struct_test(dict_struct)
69
70        # Tests for floating point data type
71        self.double_struct_test(dict_struct)
72
73        # Tests for boolean data type
74        self.bool_struct_test(dict_struct)
75
76        # Tests for array data type
77        self.array_struct_test(dict_struct)
78
79        s.Clear()
80        self.assertSuccess(example.GetAsJSON(s))
81        py_obj = json.loads(s.GetData())
82        self.assertTrue(py_obj)
83        self.assertIn("key_dict", py_obj)
84
85        py_dict = py_obj["key_dict"]
86        self.assertEqual(py_dict["key_string"], "STRING")
87        self.assertEqual(py_dict["key_uint"], 0xFFFFFFFF00000000)
88        self.assertEqual(py_dict["key_sint"], -42)
89        self.assertEqual(py_dict["key_float"], 2.99)
90        self.assertEqual(py_dict["key_bool"], True)
91        self.assertEqual(py_dict["key_array"], ["23", "arr"])
92
93        class MyRandomClass:
94            payload = "foo"
95
96        py_dict["key_generic"] = MyRandomClass()
97
98        stp = lldb.SBScriptObject(py_dict, lldb.eScriptLanguagePython)
99        self.assertEqual(stp.ptr, py_dict)
100
101        sd = lldb.SBStructuredData(stp, self.dbg)
102        self.assertTrue(sd.IsValid())
103        self.assertEqual(sd.GetSize(), len(py_dict))
104
105        generic_sd = sd.GetValueForKey("key_generic")
106        self.assertTrue(generic_sd.IsValid())
107        self.assertEqual(generic_sd.GetType(), lldb.eStructuredDataTypeGeneric)
108
109        my_random_class = generic_sd.GetGenericValue()
110        self.assertTrue(my_random_class)
111        self.assertEqual(my_random_class.payload, MyRandomClass.payload)
112
113    def invalid_struct_test(self, example):
114        invalid_struct = lldb.SBStructuredData()
115        invalid_struct = example.GetValueForKey("invalid_key")
116        if invalid_struct.IsValid():
117            self.fail("An invalid object should have been returned")
118
119        # Check Type API
120        if not invalid_struct.GetType() == lldb.eStructuredDataTypeInvalid:
121            self.fail("Wrong type returned: " + str(invalid_struct.GetType()))
122
123    def dictionary_struct_test(self, example):
124        # Check API returning a valid SBStructuredData of 'dictionary' type
125        dict_struct = lldb.SBStructuredData()
126        dict_struct = example.GetValueForKey("key_dict")
127        if not dict_struct.IsValid():
128            self.fail("A valid object should have been returned")
129
130        # Check Type API
131        if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary:
132            self.fail("Wrong type returned: " + str(dict_struct.GetType()))
133
134        # Check Size API for 'dictionary' type
135        if not dict_struct.GetSize() == 6:
136            self.fail("Wrong no of elements returned: " + str(dict_struct.GetSize()))
137
138    def string_struct_test(self, dict_struct):
139        string_struct = lldb.SBStructuredData()
140        string_struct = dict_struct.GetValueForKey("key_string")
141        if not string_struct.IsValid():
142            self.fail("A valid object should have been returned")
143
144        # Check Type API
145        if not string_struct.GetType() == lldb.eStructuredDataTypeString:
146            self.fail("Wrong type returned: " + str(string_struct.GetType()))
147
148        # Check API returning 'string' value
149        output = string_struct.GetStringValue(25)
150        if not "STRING" in output:
151            self.fail("wrong output: " + output)
152
153        # Calling wrong API on a SBStructuredData
154        # (e.g. getting an integer from a string type structure)
155        output = string_struct.GetIntegerValue()
156        if output:
157            self.fail(
158                "Valid integer value " + str(output) + " returned for a string object"
159            )
160
161    def uint_struct_test(self, dict_struct):
162        # Check a valid SBStructuredData containing an unsigned integer.
163        # We intentionally make this larger than what an int64_t can hold but
164        # still small enough to fit a uint64_t
165        uint_struct = lldb.SBStructuredData()
166        uint_struct = dict_struct.GetValueForKey("key_uint")
167        if not uint_struct.IsValid():
168            self.fail("A valid object should have been returned")
169
170        # Check Type API
171        if not uint_struct.GetType() == lldb.eStructuredDataTypeInteger:
172            self.fail("Wrong type returned: " + str(uint_struct.GetType()))
173
174        # Check API returning unsigned integer value
175        output = uint_struct.GetUnsignedIntegerValue()
176        if not output == 0xFFFFFFFF00000000:
177            self.fail("wrong output: " + str(output))
178
179        # Calling wrong API on a SBStructuredData
180        # (e.g. getting a string value from an integer type structure)
181        output = uint_struct.GetStringValue(25)
182        if output:
183            self.fail("Valid string " + output + " returned for an integer object")
184
185    def sint_struct_test(self, dict_struct):
186        # Check a valid SBStructuredData containing an signed integer.
187        # We intentionally make this smaller than what an uint64_t can hold but
188        # still small enough to fit a int64_t
189        sint_struct = lldb.SBStructuredData()
190        sint_struct = dict_struct.GetValueForKey("key_sint")
191        if not sint_struct.IsValid():
192            self.fail("A valid object should have been returned")
193
194        # Check Type API
195        if not sint_struct.GetType() == lldb.eStructuredDataTypeSignedInteger:
196            self.fail("Wrong type returned: " + str(sint_struct.GetType()))
197
198        # Check API returning signed integer value
199        output = sint_struct.GetSignedIntegerValue()
200        if not output == -42:
201            self.fail("wrong output: " + str(output))
202
203        # Calling wrong API on a SBStructuredData
204        # (e.g. getting a string value from an integer type structure)
205        output = sint_struct.GetStringValue(69)
206        if output:
207            self.fail("Valid string " + output + " returned for an integer object")
208
209    def double_struct_test(self, dict_struct):
210        floating_point_struct = lldb.SBStructuredData()
211        floating_point_struct = dict_struct.GetValueForKey("key_float")
212        if not floating_point_struct.IsValid():
213            self.fail("A valid object should have been returned")
214
215        # Check Type API
216        if not floating_point_struct.GetType() == lldb.eStructuredDataTypeFloat:
217            self.fail("Wrong type returned: " + str(floating_point_struct.GetType()))
218
219        # Check API returning 'double' value
220        output = floating_point_struct.GetFloatValue()
221        if not output == 2.99:
222            self.fail("wrong output: " + str(output))
223
224    def bool_struct_test(self, dict_struct):
225        bool_struct = lldb.SBStructuredData()
226        bool_struct = dict_struct.GetValueForKey("key_bool")
227        if not bool_struct.IsValid():
228            self.fail("A valid object should have been returned")
229
230        # Check Type API
231        if not bool_struct.GetType() == lldb.eStructuredDataTypeBoolean:
232            self.fail("Wrong type returned: " + str(bool_struct.GetType()))
233
234        # Check API returning 'bool' value
235        output = bool_struct.GetBooleanValue()
236        if not output:
237            self.fail("wrong output: " + str(output))
238
239    def array_struct_test(self, dict_struct):
240        # Check API returning a valid SBStructuredData of 'array' type
241        array_struct = lldb.SBStructuredData()
242        array_struct = dict_struct.GetValueForKey("key_array")
243        if not array_struct.IsValid():
244            self.fail("A valid object should have been returned")
245
246        # Check Type API
247        if not array_struct.GetType() == lldb.eStructuredDataTypeArray:
248            self.fail("Wrong type returned: " + str(array_struct.GetType()))
249
250        # Check Size API for 'array' type
251        if not array_struct.GetSize() == 2:
252            self.fail("Wrong no of elements returned: " + str(array_struct.GetSize()))
253
254        # Check API returning a valid SBStructuredData for different 'array'
255        # indices
256        string_struct = array_struct.GetItemAtIndex(0)
257        if not string_struct.IsValid():
258            self.fail("A valid object should have been returned")
259        if not string_struct.GetType() == lldb.eStructuredDataTypeString:
260            self.fail("Wrong type returned: " + str(string_struct.GetType()))
261        output = string_struct.GetStringValue(5)
262        if not output == "23":
263            self.fail("wrong output: " + str(output))
264
265        string_struct = array_struct.GetItemAtIndex(1)
266        if not string_struct.IsValid():
267            self.fail("A valid object should have been returned")
268        if not string_struct.GetType() == lldb.eStructuredDataTypeString:
269            self.fail("Wrong type returned: " + str(string_struct.GetType()))
270        output = string_struct.GetStringValue(5)
271        if not output == "arr":
272            self.fail("wrong output: " + str(output))
273