Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
"""
Test some SBStructuredData API.
"""

from __future__ import print_function

import os
import re
import time

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class TestStructuredDataAPI(TestBase):

mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True

def test(self):
self.structured_data_api_test()

def setUp(self):
TestBase.setUp(self)

@add_test_categories(['pyapi'])
def structured_data_api_test(self):
error = lldb.SBError()
s = lldb.SBStream()
s.Print(
"{\"key_dict\":{\"key_string\":\"STRING\",\"key_int\":3,\"key_float\":2.99,\"key_bool\":true,\"key_array\":[\"23\",\"arr\"]}}")
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)

dict_struct = lldb.SBStructuredData()
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.int_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)

def invalid_struct_test(self, example):
invalid_struct = lldb.SBStructuredData()
invalid_struct = example.GetValueForKey("invalid_key")
if invalid_struct.IsValid():
self.fail("An invalid object should have been returned")

# Check Type API
if not 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 = lldb.SBStructuredData()
dict_struct = example.GetValueForKey("key_dict")
if not dict_struct.IsValid():
self.fail("A valid object should have been returned")

# Check Type API
if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary:
self.fail("Wrong type returned: " + str(dict_struct.GetType()))

# Check Size API for 'dictionary' type
if not dict_struct.GetSize() == 5:
self.fail("Wrong no of elements returned: " +
str(dict_struct.GetSize()))

def string_struct_test(self, dict_struct):
string_struct = lldb.SBStructuredData()
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 not 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 int_struct_test(self, dict_struct):
# Check a valid SBStructuredData containing an 'integer' by
int_struct = lldb.SBStructuredData()
int_struct = dict_struct.GetValueForKey("key_int")
if not int_struct.IsValid():
self.fail("A valid object should have been returned")

# Check Type API
if not int_struct.GetType() == lldb.eStructuredDataTypeInteger:
self.fail("Wrong type returned: " + str(int_struct.GetType()))

# Check API returning 'integer' value
output = int_struct.GetIntegerValue()
if not output == 3:
self.fail("wrong output: " + str(output))

# Calling wrong API on a SBStructuredData
# (e.g. getting a string value from an integer type structure)
output = int_struct.GetStringValue(25)
if output:
self.fail(
"Valid string " +
output +
" returned for an integer object")

def double_struct_test(self, dict_struct):
floating_point_struct = lldb.SBStructuredData()
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 not 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 not output == 2.99:
self.fail("wrong output: " + str(output))

def bool_struct_test(self, dict_struct):
bool_struct = lldb.SBStructuredData()
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 not 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 = lldb.SBStructuredData()
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 not array_struct.GetType() == lldb.eStructuredDataTypeArray:
self.fail("Wrong type returned: " + str(array_struct.GetType()))

# Check Size API for 'array' type
if not 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 not string_struct.GetType() == lldb.eStructuredDataTypeString:
self.fail("Wrong type returned: " + str(string_struct.GetType()))
output = string_struct.GetStringValue(5)
if not 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 not string_struct.GetType() == lldb.eStructuredDataTypeString:
self.fail("Wrong type returned: " + str(string_struct.GetType()))
output = string_struct.GetStringValue(5)
if not output == "arr":
self.fail("wrong output: " + str(output))
25 changes: 21 additions & 4 deletions lldb/scripts/interface/SBStructuredData.i
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,38 @@ namespace lldb {
class SBStructuredData
{
public:

SBStructuredData();

SBStructuredData(const lldb::SBStructuredData &rhs);

SBStructuredData(const lldb::EventSP &event_sp);

~SBStructuredData();

bool
IsValid() const;

void
Clear();

lldb::SBStructuredData &operator=(const lldb::SBStructuredData &rhs);

lldb::StructuredDataType GetType() const;

size_t GetSize() const;

lldb::SBStructuredData GetValueForKey(const char *key) const;

lldb::SBStructuredData GetItemAtIndex(size_t idx) const;

uint64_t GetIntegerValue(uint64_t fail_value = 0) const;

double GetFloatValue(double fail_value = 0.0) const;

bool GetBooleanValue(bool fail_value = false) const;

size_t GetStringValue(char *dst, size_t dst_len) const;

lldb::SBError
GetAsJSON(lldb::SBStream &stream) const;

Expand Down
44 changes: 43 additions & 1 deletion lldb/source/API/SBStructuredData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ lldb::SBError SBStructuredData::SetFromJSON(lldb::SBStream &stream) {
StructuredData::ObjectSP json_obj = StructuredData::ParseJSON(json_str);
m_impl_up->SetObjectSP(json_obj);

if (!json_obj || json_obj->GetType() != StructuredData::Type::eTypeDictionary)
if (!json_obj || json_obj->GetType() != eStructuredDataTypeDictionary)
error.SetErrorString("Invalid Syntax");
return error;
}
Expand All @@ -67,3 +67,45 @@ lldb::SBError SBStructuredData::GetDescription(lldb::SBStream &stream) const {
sb_error.SetError(error);
return sb_error;
}

StructuredDataType SBStructuredData::GetType() const {
return (m_impl_up ? m_impl_up->GetType() : eStructuredDataTypeInvalid);
}

size_t SBStructuredData::GetSize() const {
return (m_impl_up ? m_impl_up->GetSize() : 0);
}

lldb::SBStructuredData SBStructuredData::GetValueForKey(const char *key) const {
if (!m_impl_up)
return SBStructuredData();

SBStructuredData result;
result.m_impl_up->SetObjectSP(m_impl_up->GetValueForKey(key));
return result;
}

lldb::SBStructuredData SBStructuredData::GetItemAtIndex(size_t idx) const {
if (!m_impl_up)
return SBStructuredData();

SBStructuredData result;
result.m_impl_up->SetObjectSP(m_impl_up->GetItemAtIndex(idx));
return result;
}

uint64_t SBStructuredData::GetIntegerValue(uint64_t fail_value) const {
return (m_impl_up ? m_impl_up->GetIntegerValue(fail_value) : fail_value);
}

double SBStructuredData::GetFloatValue(double fail_value) const {
return (m_impl_up ? m_impl_up->GetFloatValue(fail_value) : fail_value);
}

bool SBStructuredData::GetBooleanValue(bool fail_value) const {
return (m_impl_up ? m_impl_up->GetBooleanValue(fail_value) : fail_value);
}

size_t SBStructuredData::GetStringValue(char *dst, size_t dst_len) const {
return (m_impl_up ? m_impl_up->GetStringValue(dst, dst_len) : 0);
}
11 changes: 6 additions & 5 deletions lldb/source/API/SBThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBValue.h"
#include "lldb/lldb-enumerations.h"

using namespace lldb;
using namespace lldb_private;
Expand Down Expand Up @@ -561,26 +562,26 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
StructuredData::ObjectSP node =
info_root_sp->GetObjectForDotSeparatedPath(path);
if (node) {
if (node->GetType() == StructuredData::Type::eTypeString) {
if (node->GetType() == eStructuredDataTypeString) {
strm.Printf("%s", node->GetAsString()->GetValue().str().c_str());
success = true;
}
if (node->GetType() == StructuredData::Type::eTypeInteger) {
if (node->GetType() == eStructuredDataTypeInteger) {
strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue());
success = true;
}
if (node->GetType() == StructuredData::Type::eTypeFloat) {
if (node->GetType() == eStructuredDataTypeFloat) {
strm.Printf("0x%f", node->GetAsFloat()->GetValue());
success = true;
}
if (node->GetType() == StructuredData::Type::eTypeBoolean) {
if (node->GetType() == eStructuredDataTypeBoolean) {
if (node->GetAsBoolean()->GetValue() == true)
strm.Printf("true");
else
strm.Printf("false");
success = true;
}
if (node->GetType() == StructuredData::Type::eTypeNull) {
if (node->GetType() == eStructuredDataTypeNull) {
strm.Printf("null");
success = true;
}
Expand Down
12 changes: 6 additions & 6 deletions lldb/source/Core/FormatEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,24 +1040,24 @@ static bool FormatThreadExtendedInfoRecurse(
thread_info_dictionary->GetObjectForDotSeparatedPath(path);

if (value) {
if (value->GetType() == StructuredData::Type::eTypeInteger) {
if (value->GetType() == eStructuredDataTypeInteger) {
const char *token_format = "0x%4.4" PRIx64;
if (!entry.printf_format.empty())
token_format = entry.printf_format.c_str();
s.Printf(token_format, value->GetAsInteger()->GetValue());
return true;
} else if (value->GetType() == StructuredData::Type::eTypeFloat) {
} else if (value->GetType() == eStructuredDataTypeFloat) {
s.Printf("%f", value->GetAsFloat()->GetValue());
return true;
} else if (value->GetType() == StructuredData::Type::eTypeString) {
} else if (value->GetType() == eStructuredDataTypeString) {
s.Format("{0}", value->GetAsString()->GetValue());
return true;
} else if (value->GetType() == StructuredData::Type::eTypeArray) {
} else if (value->GetType() == eStructuredDataTypeArray) {
if (value->GetAsArray()->GetSize() > 0) {
s.Printf("%zu", value->GetAsArray()->GetSize());
return true;
}
} else if (value->GetType() == StructuredData::Type::eTypeDictionary) {
} else if (value->GetType() == eStructuredDataTypeDictionary) {
s.Printf("%zu",
value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
return true;
Expand Down Expand Up @@ -1346,7 +1346,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
if (thread) {
StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
if (object_sp &&
object_sp->GetType() == StructuredData::Type::eTypeDictionary) {
object_sp->GetType() == eStructuredDataTypeDictionary) {
if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Core/StructuredData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) {

StructuredData::ObjectSP
StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
if (this->GetType() == Type::eTypeDictionary) {
if (this->GetType() == lldb::eStructuredDataTypeDictionary) {
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
std::string key = match.first.str();
ObjectSP value = this->GetAsDictionary()->GetValueForKey(key);
Expand All @@ -200,7 +200,7 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
return ObjectSP();
}

if (this->GetType() == Type::eTypeArray) {
if (this->GetType() == lldb::eStructuredDataTypeArray) {
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
if (match.second.size() == 0) {
return this->shared_from_this();
Expand Down
24 changes: 11 additions & 13 deletions lldb/source/Target/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-enumerations.h"

using namespace lldb;
using namespace lldb_private;
Expand Down Expand Up @@ -397,7 +398,7 @@ lldb::StopInfoSP Thread::GetStopInfo() {
bool plan_overrides_trace =
have_valid_stop_info && have_valid_completed_plan
&& (m_stop_info_sp->GetStopReason() == eStopReasonTrace);

if (have_valid_stop_info && !plan_overrides_trace) {
return m_stop_info_sp;
} else if (have_valid_completed_plan) {
Expand Down Expand Up @@ -541,7 +542,7 @@ bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) {
saved_state.orig_stop_id = process_sp->GetStopID();
saved_state.current_inlined_depth = GetCurrentInlinedDepth();
saved_state.m_completed_plan_stack = m_completed_plan_stack;

return true;
}

Expand Down Expand Up @@ -1994,36 +1995,34 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
thread_info->GetObjectForDotSeparatedPath("trace_messages");

bool printed_activity = false;
if (activity &&
activity->GetType() == StructuredData::Type::eTypeDictionary) {
if (activity && activity->GetType() == eStructuredDataTypeDictionary) {
StructuredData::Dictionary *activity_dict = activity->GetAsDictionary();
StructuredData::ObjectSP id = activity_dict->GetValueForKey("id");
StructuredData::ObjectSP name = activity_dict->GetValueForKey("name");
if (name && name->GetType() == StructuredData::Type::eTypeString && id &&
id->GetType() == StructuredData::Type::eTypeInteger) {
if (name && name->GetType() == eStructuredDataTypeString && id &&
id->GetType() == eStructuredDataTypeInteger) {
strm.Format(" Activity '{0}', {1:x}\n",
name->GetAsString()->GetValue(),
id->GetAsInteger()->GetValue());
}
printed_activity = true;
}
bool printed_breadcrumb = false;
if (breadcrumb &&
breadcrumb->GetType() == StructuredData::Type::eTypeDictionary) {
if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) {
if (printed_activity)
strm.Printf("\n");
StructuredData::Dictionary *breadcrumb_dict =
breadcrumb->GetAsDictionary();
StructuredData::ObjectSP breadcrumb_text =
breadcrumb_dict->GetValueForKey("name");
if (breadcrumb_text &&
breadcrumb_text->GetType() == StructuredData::Type::eTypeString) {
breadcrumb_text->GetType() == eStructuredDataTypeString) {
strm.Format(" Current Breadcrumb: {0}\n",
breadcrumb_text->GetAsString()->GetValue());
}
printed_breadcrumb = true;
}
if (messages && messages->GetType() == StructuredData::Type::eTypeArray) {
if (messages && messages->GetType() == eStructuredDataTypeArray) {
if (printed_breadcrumb)
strm.Printf("\n");
StructuredData::Array *messages_array = messages->GetAsArray();
Expand All @@ -2032,14 +2031,13 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
strm.Printf(" %zu trace messages:\n", msg_count);
for (size_t i = 0; i < msg_count; i++) {
StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i);
if (message &&
message->GetType() == StructuredData::Type::eTypeDictionary) {
if (message && message->GetType() == eStructuredDataTypeDictionary) {
StructuredData::Dictionary *message_dict =
message->GetAsDictionary();
StructuredData::ObjectSP message_text =
message_dict->GetValueForKey("message");
if (message_text &&
message_text->GetType() == StructuredData::Type::eTypeString) {
message_text->GetType() == eStructuredDataTypeString) {
strm.Format(" {0}\n", message_text->GetAsString()->GetValue());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/lldb-enumerations.h"

#include "PythonTestSuite.h"

Expand Down Expand Up @@ -355,9 +356,9 @@ TEST_F(PythonDataObjectsTest, TestPythonListToStructuredList) {
list.AppendItem(PythonString(string_value1));

auto array_sp = list.CreateStructuredArray();
EXPECT_EQ(StructuredData::Type::eTypeInteger,
EXPECT_EQ(lldb::eStructuredDataTypeInteger,
array_sp->GetItemAtIndex(0)->GetType());
EXPECT_EQ(StructuredData::Type::eTypeString,
EXPECT_EQ(lldb::eStructuredDataTypeString,
array_sp->GetItemAtIndex(1)->GetType());

auto int_sp = array_sp->GetItemAtIndex(0)->GetAsInteger();
Expand Down Expand Up @@ -424,9 +425,9 @@ TEST_F(PythonDataObjectsTest, TestPythonTupleToStructuredList) {

auto array_sp = tuple.CreateStructuredArray();
EXPECT_EQ(tuple.GetSize(), array_sp->GetSize());
EXPECT_EQ(StructuredData::Type::eTypeInteger,
EXPECT_EQ(lldb::eStructuredDataTypeInteger,
array_sp->GetItemAtIndex(0)->GetType());
EXPECT_EQ(StructuredData::Type::eTypeString,
EXPECT_EQ(lldb::eStructuredDataTypeString,
array_sp->GetItemAtIndex(1)->GetType());
}

Expand Down