""" Test some SBStructuredData API. """ import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil import json class TestStructuredDataAPI(TestBase): NO_DEBUG_INFO_TESTCASE = True def test(self): self.structured_data_api_test() def structured_data_api_test(self): error = lldb.SBError() s = lldb.SBStream() dict_str = json.dumps( { "key_dict": { "key_string": "STRING", "key_uint": 0xFFFFFFFF00000000, "key_sint": -42, "key_float": 2.99, "key_bool": True, "key_array": ["23", "arr"], } } ) s.Print(dict_str) example = lldb.SBStructuredData() # Check SetFromJSON API for dictionaries, integers, floating point # values, strings and arrays error = example.SetFromJSON(s) if not error.Success(): self.fail("FAILED: " + error.GetCString()) # Tests for invalid data type self.invalid_struct_test(example) # Test that GetDescription works: s.Clear() error = example.GetDescription(s) self.assertSuccess(error, "GetDescription works") # Ensure str() doesn't raise an exception. self.assertTrue(str(example)) if not "key_float" in s.GetData(): self.fail("FAILED: could not find key_float in description output") dict_struct = example.GetValueForKey("key_dict") # Tests for dictionary data type self.dictionary_struct_test(example) # Tests for string data type self.string_struct_test(dict_struct) # Tests for integer data type self.uint_struct_test(dict_struct) # Tests for integer data type self.sint_struct_test(dict_struct) # Tests for floating point data type self.double_struct_test(dict_struct) # Tests for boolean data type self.bool_struct_test(dict_struct) # Tests for array data type self.array_struct_test(dict_struct) s.Clear() self.assertSuccess(example.GetAsJSON(s)) py_obj = json.loads(s.GetData()) self.assertTrue(py_obj) self.assertIn("key_dict", py_obj) py_dict = py_obj["key_dict"] self.assertEqual(py_dict["key_string"], "STRING") self.assertEqual(py_dict["key_uint"], 0xFFFFFFFF00000000) self.assertEqual(py_dict["key_sint"], -42) self.assertEqual(py_dict["key_float"], 2.99) self.assertEqual(py_dict["key_bool"], True) self.assertEqual(py_dict["key_array"], ["23", "arr"]) class MyRandomClass: payload = "foo" py_dict["key_generic"] = MyRandomClass() stp = lldb.SBScriptObject(py_dict, lldb.eScriptLanguagePython) self.assertEqual(stp.ptr, py_dict) sd = lldb.SBStructuredData(stp, self.dbg) self.assertTrue(sd.IsValid()) self.assertEqual(sd.GetSize(), len(py_dict)) generic_sd = sd.GetValueForKey("key_generic") self.assertTrue(generic_sd.IsValid()) self.assertEqual(generic_sd.GetType(), lldb.eStructuredDataTypeGeneric) my_random_class = generic_sd.GetGenericValue() self.assertTrue(my_random_class) self.assertEqual(my_random_class.payload, MyRandomClass.payload) example = lldb.SBStructuredData() self.assertSuccess(example.SetFromJSON("1")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeInteger) self.assertEqual(example.GetIntegerValue(), 1) self.assertEqual(int(example), 1) self.assertSuccess(example.SetFromJSON("4.19")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeFloat) self.assertEqual(example.GetFloatValue(), 4.19) self.assertEqual(float(example), 4.19) self.assertSuccess(example.SetFromJSON('"Bonjour, 123!"')) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeString) self.assertEqual(example.GetStringValue(42), "Bonjour, 123!") self.assertEqual(str(example), "Bonjour, 123!") self.assertSuccess(example.SetFromJSON("true")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeBoolean) self.assertTrue(example.GetBooleanValue()) self.assertTrue(example) self.assertSuccess(example.SetFromJSON("null")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeNull) example = lldb.SBStructuredData() example.SetUnsignedIntegerValue(1) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeInteger) self.assertEqual(example.GetIntegerValue(), 1) example.SetSignedIntegerValue(-42) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeSignedInteger) self.assertEqual(example.GetSignedIntegerValue(), -42) example.SetFloatValue(4.19) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeFloat) self.assertEqual(example.GetFloatValue(), 4.19) example.SetStringValue("Bonjour, 123!") self.assertEqual(example.GetType(), lldb.eStructuredDataTypeString) self.assertEqual(example.GetStringValue(42), "Bonjour, 123!") value = lldb.SBStructuredData() example.SetValueForKey("Hello", value) self.assertEqual(example.GetSize(), 0) nested_obj = lldb.SBStructuredData() nested_obj.SetStringValue("World") example.SetValueForKey("Hello", nested_obj) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeDictionary) nested_obj = None nested_obj = example.GetValueForKey("Hello") self.assertTrue(nested_obj.IsValid()) self.assertEqual(nested_obj.GetType(), lldb.eStructuredDataTypeString) self.assertEqual(nested_obj.GetStringValue(42), "World") example.SetBooleanValue(True) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeBoolean) self.assertTrue(example.GetBooleanValue()) rnd_obj = MyRandomClass() stp = lldb.SBScriptObject(rnd_obj, lldb.eScriptLanguagePython) self.assertEqual(stp.ptr, rnd_obj) example.SetGenericValue(stp) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeGeneric) my_random_class = example.GetGenericValue() self.assertTrue(my_random_class) self.assertEqual(my_random_class.payload, MyRandomClass.payload) example_arr = [1, 2.3, "4", {"5": False}] arr_str = json.dumps(example_arr) s.Clear() s.Print(arr_str) self.assertSuccess(example.SetFromJSON(s)) s.Clear() self.assertSuccess(example.GetAsJSON(s)) sb_data = json.loads(s.GetData()) self.assertEqual(sb_data, example_arr) def invalid_struct_test(self, example): invalid_struct = example.GetValueForKey("invalid_key") if invalid_struct.IsValid(): self.fail("An invalid object should have been returned") # Check Type API if invalid_struct.GetType() != lldb.eStructuredDataTypeInvalid: self.fail("Wrong type returned: " + str(invalid_struct.GetType())) def dictionary_struct_test(self, example): # Check API returning a valid SBStructuredData of 'dictionary' type dict_struct = example.GetValueForKey("key_dict") if not dict_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if dict_struct.GetType() != lldb.eStructuredDataTypeDictionary: self.fail("Wrong type returned: " + str(dict_struct.GetType())) # Check Size API for 'dictionary' type if dict_struct.GetSize() != 6: self.fail("Wrong no of elements returned: " + str(dict_struct.GetSize())) def string_struct_test(self, dict_struct): string_struct = dict_struct.GetValueForKey("key_string") if not string_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) # Check API returning 'string' value output = string_struct.GetStringValue(25) if not "STRING" in output: self.fail("wrong output: " + output) # Calling wrong API on a SBStructuredData # (e.g. getting an integer from a string type structure) output = string_struct.GetIntegerValue() if output: self.fail( "Valid integer value " + str(output) + " returned for a string object" ) def uint_struct_test(self, dict_struct): # Check a valid SBStructuredData containing an unsigned integer. # We intentionally make this larger than what an int64_t can hold but # still small enough to fit a uint64_t uint_struct = dict_struct.GetValueForKey("key_uint") if not uint_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if uint_struct.GetType() != lldb.eStructuredDataTypeInteger: self.fail("Wrong type returned: " + str(uint_struct.GetType())) # Check API returning unsigned integer value output = uint_struct.GetUnsignedIntegerValue() if output != 0xFFFFFFFF00000000: self.fail("wrong output: " + str(output)) # Calling wrong API on a SBStructuredData # (e.g. getting a string value from an integer type structure) output = uint_struct.GetStringValue(25) if output: self.fail("Valid string " + output + " returned for an integer object") def sint_struct_test(self, dict_struct): # Check a valid SBStructuredData containing an signed integer. # We intentionally make this smaller than what an uint64_t can hold but # still small enough to fit a int64_t sint_struct = dict_struct.GetValueForKey("key_sint") if not sint_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if sint_struct.GetType() != lldb.eStructuredDataTypeSignedInteger: self.fail("Wrong type returned: " + str(sint_struct.GetType())) # Check API returning signed integer value output = sint_struct.GetSignedIntegerValue() if output != -42: self.fail("wrong output: " + str(output)) # Calling wrong API on a SBStructuredData # (e.g. getting a string value from an integer type structure) output = sint_struct.GetStringValue(69) if output: self.fail("Valid string " + output + " returned for an integer object") def double_struct_test(self, dict_struct): floating_point_struct = dict_struct.GetValueForKey("key_float") if not floating_point_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if floating_point_struct.GetType() != lldb.eStructuredDataTypeFloat: self.fail("Wrong type returned: " + str(floating_point_struct.GetType())) # Check API returning 'double' value output = floating_point_struct.GetFloatValue() if output != 2.99: self.fail("wrong output: " + str(output)) def bool_struct_test(self, dict_struct): bool_struct = dict_struct.GetValueForKey("key_bool") if not bool_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if bool_struct.GetType() != lldb.eStructuredDataTypeBoolean: self.fail("Wrong type returned: " + str(bool_struct.GetType())) # Check API returning 'bool' value output = bool_struct.GetBooleanValue() if not output: self.fail("wrong output: " + str(output)) def array_struct_test(self, dict_struct): # Check API returning a valid SBStructuredData of 'array' type array_struct = dict_struct.GetValueForKey("key_array") if not array_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API if array_struct.GetType() != lldb.eStructuredDataTypeArray: self.fail("Wrong type returned: " + str(array_struct.GetType())) # Check Size API for 'array' type if array_struct.GetSize() != 2: self.fail("Wrong no of elements returned: " + str(array_struct.GetSize())) # Check API returning a valid SBStructuredData for different 'array' # indices string_struct = array_struct.GetItemAtIndex(0) if not string_struct.IsValid(): self.fail("A valid object should have been returned") if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) if output != "23": self.fail("wrong output: " + str(output)) string_struct = array_struct.GetItemAtIndex(1) if not string_struct.IsValid(): self.fail("A valid object should have been returned") if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) if output != "arr": self.fail("wrong output: " + str(output)) def test_round_trip_scalars(self): for original in (0, 11, -1, 0.0, 4.5, -0.25): constructor = type(original) data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(original)) round_tripped = constructor(data) self.assertEqual(round_tripped, original) def test_dynamic(self): for original in (0, 11, -1, 0.0, 4.5, -0.25, "", "dirk", True, False): data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(original)) self.assertEqual(data.dynamic, original) def test_round_trip_int(self): for original in (0, 11, -1): data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(original)) self.assertEqual(int(data), int(original)) def test_round_trip_float(self): for original in (0, 11, -1, 0.0, 4.5, -0.25): data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(original)) self.assertEqual(float(data), float(original)) def test_iterate_array(self): array = [0, 1, 2] data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(array)) for value in data: self.assertEqual(value, array.pop(0)) def test_iterate_dictionary(self): dictionary = {"0": 0, "1": 1, "2": 2} keys = set(dictionary.keys()) data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(dictionary)) for key in data: self.assertIn(key, keys) keys.remove(key) def test_getitem_array(self): array = [1, 2, 3] data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(array)) for i in range(len(array)): self.assertEqual(data[i], array[i]) def test_getitem_dictionary(self): dictionary = {"one": 1, "two": 2, "three": 3} data = lldb.SBStructuredData() data.SetFromJSON(json.dumps(dictionary)) for key in dictionary: self.assertEqual(data[key], dictionary[key])