xref: /llvm-project/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py (revision 585523750e2bbe374d1cb3bf4ff9d53de29b9593)
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        example = lldb.SBStructuredData()
114        self.assertSuccess(example.SetFromJSON("1"))
115        self.assertEqual(example.GetType(), lldb.eStructuredDataTypeInteger)
116        self.assertEqual(example.GetIntegerValue(), 1)
117
118        self.assertSuccess(example.SetFromJSON("4.19"))
119        self.assertEqual(example.GetType(), lldb.eStructuredDataTypeFloat)
120        self.assertEqual(example.GetFloatValue(), 4.19)
121
122        self.assertSuccess(example.SetFromJSON('"Bonjour, 123!"'))
123        self.assertEqual(example.GetType(), lldb.eStructuredDataTypeString)
124        self.assertEqual(example.GetStringValue(42), "Bonjour, 123!")
125
126        self.assertSuccess(example.SetFromJSON("true"))
127        self.assertEqual(example.GetType(), lldb.eStructuredDataTypeBoolean)
128        self.assertTrue(example.GetBooleanValue())
129
130        self.assertSuccess(example.SetFromJSON("null"))
131        self.assertEqual(example.GetType(), lldb.eStructuredDataTypeNull)
132
133        example_arr = [1, 2.3, "4", {"5": False}]
134        arr_str = json.dumps(example_arr)
135        s.Clear()
136        s.Print(arr_str)
137        self.assertSuccess(example.SetFromJSON(s))
138
139        s.Clear()
140        self.assertSuccess(example.GetAsJSON(s))
141        sb_data = json.loads(s.GetData())
142        self.assertEqual(sb_data, example_arr)
143
144    def invalid_struct_test(self, example):
145        invalid_struct = lldb.SBStructuredData()
146        invalid_struct = example.GetValueForKey("invalid_key")
147        if invalid_struct.IsValid():
148            self.fail("An invalid object should have been returned")
149
150        # Check Type API
151        if not invalid_struct.GetType() == lldb.eStructuredDataTypeInvalid:
152            self.fail("Wrong type returned: " + str(invalid_struct.GetType()))
153
154    def dictionary_struct_test(self, example):
155        # Check API returning a valid SBStructuredData of 'dictionary' type
156        dict_struct = lldb.SBStructuredData()
157        dict_struct = example.GetValueForKey("key_dict")
158        if not dict_struct.IsValid():
159            self.fail("A valid object should have been returned")
160
161        # Check Type API
162        if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary:
163            self.fail("Wrong type returned: " + str(dict_struct.GetType()))
164
165        # Check Size API for 'dictionary' type
166        if not dict_struct.GetSize() == 6:
167            self.fail("Wrong no of elements returned: " + str(dict_struct.GetSize()))
168
169    def string_struct_test(self, dict_struct):
170        string_struct = lldb.SBStructuredData()
171        string_struct = dict_struct.GetValueForKey("key_string")
172        if not string_struct.IsValid():
173            self.fail("A valid object should have been returned")
174
175        # Check Type API
176        if not string_struct.GetType() == lldb.eStructuredDataTypeString:
177            self.fail("Wrong type returned: " + str(string_struct.GetType()))
178
179        # Check API returning 'string' value
180        output = string_struct.GetStringValue(25)
181        if not "STRING" in output:
182            self.fail("wrong output: " + output)
183
184        # Calling wrong API on a SBStructuredData
185        # (e.g. getting an integer from a string type structure)
186        output = string_struct.GetIntegerValue()
187        if output:
188            self.fail(
189                "Valid integer value " + str(output) + " returned for a string object"
190            )
191
192    def uint_struct_test(self, dict_struct):
193        # Check a valid SBStructuredData containing an unsigned integer.
194        # We intentionally make this larger than what an int64_t can hold but
195        # still small enough to fit a uint64_t
196        uint_struct = lldb.SBStructuredData()
197        uint_struct = dict_struct.GetValueForKey("key_uint")
198        if not uint_struct.IsValid():
199            self.fail("A valid object should have been returned")
200
201        # Check Type API
202        if not uint_struct.GetType() == lldb.eStructuredDataTypeInteger:
203            self.fail("Wrong type returned: " + str(uint_struct.GetType()))
204
205        # Check API returning unsigned integer value
206        output = uint_struct.GetUnsignedIntegerValue()
207        if not output == 0xFFFFFFFF00000000:
208            self.fail("wrong output: " + str(output))
209
210        # Calling wrong API on a SBStructuredData
211        # (e.g. getting a string value from an integer type structure)
212        output = uint_struct.GetStringValue(25)
213        if output:
214            self.fail("Valid string " + output + " returned for an integer object")
215
216    def sint_struct_test(self, dict_struct):
217        # Check a valid SBStructuredData containing an signed integer.
218        # We intentionally make this smaller than what an uint64_t can hold but
219        # still small enough to fit a int64_t
220        sint_struct = lldb.SBStructuredData()
221        sint_struct = dict_struct.GetValueForKey("key_sint")
222        if not sint_struct.IsValid():
223            self.fail("A valid object should have been returned")
224
225        # Check Type API
226        if not sint_struct.GetType() == lldb.eStructuredDataTypeSignedInteger:
227            self.fail("Wrong type returned: " + str(sint_struct.GetType()))
228
229        # Check API returning signed integer value
230        output = sint_struct.GetSignedIntegerValue()
231        if not output == -42:
232            self.fail("wrong output: " + str(output))
233
234        # Calling wrong API on a SBStructuredData
235        # (e.g. getting a string value from an integer type structure)
236        output = sint_struct.GetStringValue(69)
237        if output:
238            self.fail("Valid string " + output + " returned for an integer object")
239
240    def double_struct_test(self, dict_struct):
241        floating_point_struct = lldb.SBStructuredData()
242        floating_point_struct = dict_struct.GetValueForKey("key_float")
243        if not floating_point_struct.IsValid():
244            self.fail("A valid object should have been returned")
245
246        # Check Type API
247        if not floating_point_struct.GetType() == lldb.eStructuredDataTypeFloat:
248            self.fail("Wrong type returned: " + str(floating_point_struct.GetType()))
249
250        # Check API returning 'double' value
251        output = floating_point_struct.GetFloatValue()
252        if not output == 2.99:
253            self.fail("wrong output: " + str(output))
254
255    def bool_struct_test(self, dict_struct):
256        bool_struct = lldb.SBStructuredData()
257        bool_struct = dict_struct.GetValueForKey("key_bool")
258        if not bool_struct.IsValid():
259            self.fail("A valid object should have been returned")
260
261        # Check Type API
262        if not bool_struct.GetType() == lldb.eStructuredDataTypeBoolean:
263            self.fail("Wrong type returned: " + str(bool_struct.GetType()))
264
265        # Check API returning 'bool' value
266        output = bool_struct.GetBooleanValue()
267        if not output:
268            self.fail("wrong output: " + str(output))
269
270    def array_struct_test(self, dict_struct):
271        # Check API returning a valid SBStructuredData of 'array' type
272        array_struct = lldb.SBStructuredData()
273        array_struct = dict_struct.GetValueForKey("key_array")
274        if not array_struct.IsValid():
275            self.fail("A valid object should have been returned")
276
277        # Check Type API
278        if not array_struct.GetType() == lldb.eStructuredDataTypeArray:
279            self.fail("Wrong type returned: " + str(array_struct.GetType()))
280
281        # Check Size API for 'array' type
282        if not array_struct.GetSize() == 2:
283            self.fail("Wrong no of elements returned: " + str(array_struct.GetSize()))
284
285        # Check API returning a valid SBStructuredData for different 'array'
286        # indices
287        string_struct = array_struct.GetItemAtIndex(0)
288        if not string_struct.IsValid():
289            self.fail("A valid object should have been returned")
290        if not string_struct.GetType() == lldb.eStructuredDataTypeString:
291            self.fail("Wrong type returned: " + str(string_struct.GetType()))
292        output = string_struct.GetStringValue(5)
293        if not output == "23":
294            self.fail("wrong output: " + str(output))
295
296        string_struct = array_struct.GetItemAtIndex(1)
297        if not string_struct.IsValid():
298            self.fail("A valid object should have been returned")
299        if not string_struct.GetType() == lldb.eStructuredDataTypeString:
300            self.fail("Wrong type returned: " + str(string_struct.GetType()))
301        output = string_struct.GetStringValue(5)
302        if not output == "arr":
303            self.fail("wrong output: " + str(output))
304