mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-09 21:24:14 +00:00
tbv2: support capture-thrift-isset
Support the capture-thrift-isset feature with TreeBuilder-v2. Fairly minor changes here except the type of the Enum in a template parameter now matters. We follow the previous behaviour of capturing a value for each field in a struct that has an `isset_bitset`. This value is a VarInt captured before the C++ contents of the member. It has 3 values: 0 (not set), 1 (set), and 2 (unavailable). These are handled by the processor and represented in the output as `false`, `true`, and `std::nullopt_t` respectively. Changes: - Add a simple Thrift isset processor before any fields that have Thrift isset. - Store the fully qualified names of enum types in DrgnParser - it already worked out this information anyway for naming the values and this is consistent with classes. - Forward all enum template parameters under their input name under the assumption that they will all be policy type things like `IssetBitsetOption`. This could turn out to be wrong. Test plan: - CI (doesn't test thrift changes but covers other regressions) - Updated Thrift enum tests for new format. - `FILTER='OilIntegration.*' make test` - Thrift tests failed before, succeed after.
This commit is contained in:
parent
1e7e8ffee6
commit
4c2e24c9bd
@ -158,7 +158,7 @@ inline void Json::printFields(const result::Element& el,
|
|||||||
printUnsignedField("capacity", el.container_stats->capacity, indent);
|
printUnsignedField("capacity", el.container_stats->capacity, indent);
|
||||||
}
|
}
|
||||||
if (el.is_set_stats.has_value())
|
if (el.is_set_stats.has_value())
|
||||||
printUnsignedField("is_set", el.is_set_stats->is_set, indent);
|
printBoolField("is_set", el.is_set_stats->is_set, indent);
|
||||||
printBoolField("is_primitive", el.is_primitive, indent);
|
printBoolField("is_primitive", el.is_primitive, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,7 +687,9 @@ void CodeGen::genClassTraversalFunction(const Class& c, std::string& code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (thriftIssetMember != nullptr && thriftIssetMember != &member) {
|
if (thriftIssetMember != nullptr && thriftIssetMember != &member) {
|
||||||
code += "\n .write(getThriftIsset(t, " + std::to_string(i) + "))";
|
code += "\n .write(getThriftIsset(t, ";
|
||||||
|
code += std::to_string(i);
|
||||||
|
code += "))";
|
||||||
}
|
}
|
||||||
|
|
||||||
code += "\n .";
|
code += "\n .";
|
||||||
@ -765,6 +767,12 @@ void CodeGen::genClassStaticType(const Class& c, std::string& code) {
|
|||||||
|
|
||||||
void CodeGen::genClassTreeBuilderInstructions(const Class& c,
|
void CodeGen::genClassTreeBuilderInstructions(const Class& c,
|
||||||
std::string& code) {
|
std::string& code) {
|
||||||
|
const Member* thriftIssetMember = nullptr;
|
||||||
|
if (const auto it = thriftIssetMembers_.find(&c);
|
||||||
|
it != thriftIssetMembers_.end()) {
|
||||||
|
thriftIssetMember = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
code += " private:\n";
|
code += " private:\n";
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (const auto& m : c.members) {
|
for (const auto& m : c.members) {
|
||||||
@ -799,12 +807,32 @@ void CodeGen::genClassTreeBuilderInstructions(const Class& c,
|
|||||||
continue;
|
continue;
|
||||||
std::string fullName = c.name() + "::" + m.name;
|
std::string fullName = c.name() + "::" + m.name;
|
||||||
bool isPrimitive = dynamic_cast<const Primitive*>(&m.type());
|
bool isPrimitive = dynamic_cast<const Primitive*>(&m.type());
|
||||||
code += " inst::Field{sizeof(" + fullName + "), " +
|
code += " inst::Field{sizeof(";
|
||||||
std::to_string(calculateExclusiveSize(m.type())) + ",\"" +
|
code += fullName;
|
||||||
m.inputName + "\", member_" + std::to_string(index) +
|
code += "), ";
|
||||||
"_type_names, TypeHandler<Ctx, decltype(" + fullName +
|
code += std::to_string(calculateExclusiveSize(m.type()));
|
||||||
")>::fields, TypeHandler<Ctx, decltype(" + fullName +
|
code += ",\"";
|
||||||
")>::processors, ";
|
code += m.inputName;
|
||||||
|
code += "\", member_";
|
||||||
|
code += std::to_string(index);
|
||||||
|
code += "_type_names, TypeHandler<Ctx, decltype(";
|
||||||
|
code += fullName;
|
||||||
|
code += ")>::fields, ";
|
||||||
|
|
||||||
|
if (thriftIssetMember != nullptr && thriftIssetMember != &m) {
|
||||||
|
code += "ThriftIssetHandler<";
|
||||||
|
// code += "member_";
|
||||||
|
// code += std::to_string(index);
|
||||||
|
// code += "_processors";
|
||||||
|
}
|
||||||
|
code += "TypeHandler<Ctx, decltype(";
|
||||||
|
code += fullName;
|
||||||
|
code += ")>";
|
||||||
|
if (thriftIssetMember != nullptr && thriftIssetMember != &m) {
|
||||||
|
code += '>';
|
||||||
|
}
|
||||||
|
code += "::processors, ";
|
||||||
|
|
||||||
code += isPrimitive ? "true" : "false";
|
code += isPrimitive ? "true" : "false";
|
||||||
code += "},\n";
|
code += "},\n";
|
||||||
}
|
}
|
||||||
@ -825,10 +853,10 @@ void CodeGen::genClassTypeHandler(const Class& c, std::string& code) {
|
|||||||
static int getThriftIsset(const %1%& t, size_t i) {
|
static int getThriftIsset(const %1%& t, size_t i) {
|
||||||
using thrift_data = apache::thrift::TStructDataStorage<%2%>;
|
using thrift_data = apache::thrift::TStructDataStorage<%2%>;
|
||||||
|
|
||||||
if (&thrift_data::isset_indexes == nullptr) return -1;
|
if (&thrift_data::isset_indexes == nullptr) return 2;
|
||||||
|
|
||||||
auto idx = thrift_data::isset_indexes[i];
|
auto idx = thrift_data::isset_indexes[i];
|
||||||
if (idx == -1) return -1;
|
if (idx == -1) return 2;
|
||||||
|
|
||||||
return t.%3%.get(idx);
|
return t.%3%.get(idx);
|
||||||
}
|
}
|
||||||
@ -900,7 +928,15 @@ void genContainerTypeHandler(std::unordered_set<const ContainerInfo*>& used,
|
|||||||
for (const auto& p : templateParams) {
|
for (const auto& p : templateParams) {
|
||||||
if (p.value) {
|
if (p.value) {
|
||||||
code += ", ";
|
code += ", ";
|
||||||
code += p.type().name();
|
|
||||||
|
// HACK: forward all enums directly. this might turn out to be a problem
|
||||||
|
// if there are enums we should be regenerating/use in the body.
|
||||||
|
if (const auto* e = dynamic_cast<const Enum*>(&p.type())) {
|
||||||
|
code += e->inputName();
|
||||||
|
} else {
|
||||||
|
code += p.type().name();
|
||||||
|
}
|
||||||
|
|
||||||
code += " N" + std::to_string(values++);
|
code += " N" + std::to_string(values++);
|
||||||
} else {
|
} else {
|
||||||
code += ", typename T" + std::to_string(types++);
|
code += ", typename T" + std::to_string(types++);
|
||||||
@ -1048,11 +1084,32 @@ void addCaptureKeySupport(std::string& code) {
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addThriftIssetSupport(std::string& code) {
|
||||||
|
code += R"(
|
||||||
|
void processThriftIsset(result::Element& el, std::function<void(inst::Inst)> stack_ins, ParsedData d) {
|
||||||
|
auto v = std::get<ParsedData::VarInt>(d.val).value;
|
||||||
|
if (v <= 1) {
|
||||||
|
el.is_set_stats.emplace(result::Element::IsSetStats { v == 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static constexpr exporters::inst::ProcessorInst thriftIssetProcessor{
|
||||||
|
types::st::VarInt<int>::describe,
|
||||||
|
&processThriftIsset,
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
struct ThriftIssetHandler {
|
||||||
|
static constexpr auto processors = arrayPrepend(Handler::processors, thriftIssetProcessor);
|
||||||
|
};
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
void addStandardTypeHandlers(TypeGraph& typeGraph,
|
void addStandardTypeHandlers(TypeGraph& typeGraph,
|
||||||
FeatureSet features,
|
FeatureSet features,
|
||||||
std::string& code) {
|
std::string& code) {
|
||||||
if (features[Feature::TreeBuilderV2])
|
addCaptureKeySupport(code);
|
||||||
addCaptureKeySupport(code);
|
if (features[Feature::CaptureThriftIsset])
|
||||||
|
addThriftIssetSupport(code);
|
||||||
|
|
||||||
// Provide a wrapper function, getSizeType, to infer T instead of having to
|
// Provide a wrapper function, getSizeType, to infer T instead of having to
|
||||||
// explicitly specify it with TypeHandler<Ctx, T>::getSizeType every time.
|
// explicitly specify it with TypeHandler<Ctx, T>::getSizeType every time.
|
||||||
|
@ -40,6 +40,11 @@ constexpr int oidMagicId = 0x01DE8;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
constexpr std::array<T, N + 1> arrayPrepend(std::array<T, N> a, T t);
|
||||||
|
template <typename T, size_t N, size_t... I>
|
||||||
|
constexpr std::array<T, N+1> arrayPrependHelper(std::array<T, N> a, T t, std::index_sequence<I...>);
|
||||||
|
|
||||||
template <size_t Size = (1 << 20) / sizeof(uintptr_t)>
|
template <size_t Size = (1 << 20) / sizeof(uintptr_t)>
|
||||||
class PointerHashSet {
|
class PointerHashSet {
|
||||||
private:
|
private:
|
||||||
@ -182,6 +187,20 @@ bool isStorageInline(const auto& c) {
|
|||||||
(uintptr_t)std::data(c) >= (uintptr_t)&c;
|
(uintptr_t)std::data(c) >= (uintptr_t)&c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <typename T, size_t N, size_t... I>
|
||||||
|
constexpr std::array<T, N+1> arrayPrependHelper(std::array<T, N> a, T t, std::index_sequence<I...>) {
|
||||||
|
return {t, a[I]...};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
constexpr std::array<T, N + 1> arrayPrepend(std::array<T, N> a, T t) {
|
||||||
|
return arrayPrependHelper(a, t, std::make_index_sequence<N>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace OIInternal {
|
namespace OIInternal {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -137,6 +137,8 @@ Typedef& ClangTypeParser::enumerateTypedef(const clang::TypedefType& ty) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Enum& ClangTypeParser::enumerateEnum(const clang::EnumType& ty) {
|
Enum& ClangTypeParser::enumerateEnum(const clang::EnumType& ty) {
|
||||||
|
std::string fqName = clang::TypeName::getFullyQualifiedName(
|
||||||
|
clang::QualType(&ty, 0), *ast, {ast->getLangOpts()});
|
||||||
std::string name = ty.getDecl()->getNameAsString();
|
std::string name = ty.getDecl()->getNameAsString();
|
||||||
auto size = ast->getTypeSize(clang::QualType(&ty, 0)) / 8;
|
auto size = ast->getTypeSize(clang::QualType(&ty, 0)) / 8;
|
||||||
|
|
||||||
@ -148,7 +150,8 @@ Enum& ClangTypeParser::enumerateEnum(const clang::EnumType& ty) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeType<Enum>(ty, std::move(name), size, std::move(enumeratorMap));
|
return makeType<Enum>(
|
||||||
|
ty, std::move(name), std::move(fqName), size, std::move(enumeratorMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
Array& ClangTypeParser::enumerateArray(const clang::ConstantArrayType& ty) {
|
Array& ClangTypeParser::enumerateArray(const clang::ConstantArrayType& ty) {
|
||||||
|
@ -73,6 +73,8 @@ void warnForDrgnError(struct drgn_type* type,
|
|||||||
const std::string& msg,
|
const std::string& msg,
|
||||||
struct drgn_error* err);
|
struct drgn_error* err);
|
||||||
|
|
||||||
|
std::string getDrgnFullyQualifiedName(struct drgn_type* type);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Type& DrgnParser::parse(struct drgn_type* root) {
|
Type& DrgnParser::parse(struct drgn_type* root) {
|
||||||
@ -150,6 +152,8 @@ Class& DrgnParser::enumerateClass(struct drgn_type* type) {
|
|||||||
std::string fqName;
|
std::string fqName;
|
||||||
char* nameStr = nullptr;
|
char* nameStr = nullptr;
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
|
// HACK: Leak this error. Freeing it causes a SEGV which suggests our
|
||||||
|
// underlying implementation is bad.
|
||||||
auto* err = drgn_type_fully_qualified_name(type, &nameStr, &length);
|
auto* err = drgn_type_fully_qualified_name(type, &nameStr, &length);
|
||||||
if (err == nullptr && nameStr != nullptr) {
|
if (err == nullptr && nameStr != nullptr) {
|
||||||
fqName = nameStr;
|
fqName = nameStr;
|
||||||
@ -307,14 +311,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
|
|||||||
// This template parameter is a value
|
// This template parameter is a value
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
if (drgn_type_kind(obj->type) == DRGN_TYPE_ENUM) {
|
if (dynamic_cast<const Enum*>(&ttype)) {
|
||||||
char* nameStr = nullptr;
|
|
||||||
size_t length = 0;
|
|
||||||
err = drgn_type_fully_qualified_name(obj->type, &nameStr, &length);
|
|
||||||
if (err != nullptr || nameStr == nullptr) {
|
|
||||||
throw DrgnParserError{"Failed to get enum's fully qualified name", err};
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t enumVal;
|
uint64_t enumVal;
|
||||||
switch (obj->encoding) {
|
switch (obj->encoding) {
|
||||||
case DRGN_OBJECT_ENCODING_SIGNED:
|
case DRGN_OBJECT_ENCODING_SIGNED:
|
||||||
@ -333,7 +330,9 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
|
|||||||
size_t numEnumerators = drgn_type_num_enumerators(obj->type);
|
size_t numEnumerators = drgn_type_num_enumerators(obj->type);
|
||||||
for (size_t j = 0; j < numEnumerators; j++) {
|
for (size_t j = 0; j < numEnumerators; j++) {
|
||||||
if (enumerators[j].uvalue == enumVal) {
|
if (enumerators[j].uvalue == enumVal) {
|
||||||
value = std::string{nameStr} + "::" + enumerators[j].name;
|
value = ttype.inputName();
|
||||||
|
value += "::";
|
||||||
|
value += enumerators[j].name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -416,6 +415,8 @@ void DrgnParser::enumerateClassFunctions(struct drgn_type* type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Enum& DrgnParser::enumerateEnum(struct drgn_type* type) {
|
Enum& DrgnParser::enumerateEnum(struct drgn_type* type) {
|
||||||
|
std::string fqName = getDrgnFullyQualifiedName(type);
|
||||||
|
|
||||||
const char* typeTag = drgn_type_tag(type);
|
const char* typeTag = drgn_type_tag(type);
|
||||||
std::string name = typeTag ? typeTag : "";
|
std::string name = typeTag ? typeTag : "";
|
||||||
uint64_t size = get_drgn_type_size(type);
|
uint64_t size = get_drgn_type_size(type);
|
||||||
@ -432,7 +433,8 @@ Enum& DrgnParser::enumerateEnum(struct drgn_type* type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeType<Enum>(type, name, size, std::move(enumeratorMap));
|
return makeType<Enum>(
|
||||||
|
type, std::move(name), std::move(fqName), size, std::move(enumeratorMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
Typedef& DrgnParser::enumerateTypedef(struct drgn_type* type) {
|
Typedef& DrgnParser::enumerateTypedef(struct drgn_type* type) {
|
||||||
@ -528,6 +530,18 @@ void warnForDrgnError(struct drgn_type* type,
|
|||||||
<< ": " << err->code << " " << err->message;
|
<< ": " << err->code << " " << err->message;
|
||||||
drgn_error_destroy(err);
|
drgn_error_destroy(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getDrgnFullyQualifiedName(drgn_type* type) {
|
||||||
|
char* nameStr = nullptr;
|
||||||
|
size_t length = 0;
|
||||||
|
auto* err = drgn_type_fully_qualified_name(type, &nameStr, &length);
|
||||||
|
if (err != nullptr)
|
||||||
|
throw DrgnParserError("failed to get fully qualified name!", err);
|
||||||
|
if (nameStr != nullptr)
|
||||||
|
return nameStr;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
} // namespace oi::detail::type_graph
|
} // namespace oi::detail::type_graph
|
||||||
|
@ -477,14 +477,20 @@ class Container : public Type {
|
|||||||
class Enum : public Type {
|
class Enum : public Type {
|
||||||
public:
|
public:
|
||||||
explicit Enum(std::string name,
|
explicit Enum(std::string name,
|
||||||
|
std::string inputName,
|
||||||
size_t size,
|
size_t size,
|
||||||
std::map<int64_t, std::string> enumerators = {})
|
std::map<int64_t, std::string> enumerators = {})
|
||||||
: name_(name),
|
: name_(std::move(name)),
|
||||||
inputName_(std::move(name)),
|
inputName_(std::move(inputName)),
|
||||||
size_(size),
|
size_(size),
|
||||||
enumerators_(std::move(enumerators)) {
|
enumerators_(std::move(enumerators)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit Enum(std::string name,
|
||||||
|
size_t size,
|
||||||
|
std::map<int64_t, std::string> enumerators = {})
|
||||||
|
: Enum{name, std::move(name), size, std::move(enumerators)} {};
|
||||||
|
|
||||||
static inline constexpr bool has_node_id = false;
|
static inline constexpr bool has_node_id = false;
|
||||||
|
|
||||||
DECLARE_ACCEPT
|
DECLARE_ACCEPT
|
||||||
|
@ -36,12 +36,12 @@ definitions = '''
|
|||||||
param_types = ["ScopedEnum"]
|
param_types = ["ScopedEnum"]
|
||||||
setup = "return {};"
|
setup = "return {};"
|
||||||
expect_json = '[{"staticSize":4, "dynamicSize":0}]'
|
expect_json = '[{"staticSize":4, "dynamicSize":0}]'
|
||||||
expect_json_v2 = '[{"typeNames": ["ScopedEnum"], "staticSize":4, "exclusiveSize":4, "size":4}]'
|
expect_json_v2 = '[{"typeNames": ["ns_enums::ScopedEnum"], "staticSize":4, "exclusiveSize":4, "size":4}]'
|
||||||
[cases.scoped_uint8]
|
[cases.scoped_uint8]
|
||||||
param_types = ["ScopedEnumUint8"]
|
param_types = ["ScopedEnumUint8"]
|
||||||
setup = "return {};"
|
setup = "return {};"
|
||||||
expect_json = '[{"staticSize":1, "dynamicSize":0}]'
|
expect_json = '[{"staticSize":1, "dynamicSize":0}]'
|
||||||
expect_json_v2 = '[{"typeNames": ["ScopedEnumUint8"], "staticSize":1, "exclusiveSize":1, "size":1}]'
|
expect_json_v2 = '[{"typeNames": ["ns_enums::ScopedEnumUint8"], "staticSize":1, "exclusiveSize":1, "size":1}]'
|
||||||
[cases.unscoped]
|
[cases.unscoped]
|
||||||
param_types = ["UNSCOPED_ENUM"]
|
param_types = ["UNSCOPED_ENUM"]
|
||||||
setup = "return {};"
|
setup = "return {};"
|
||||||
@ -60,7 +60,7 @@ definitions = '''
|
|||||||
expect_json = '[{"staticSize":2, "dynamicSize":0}]'
|
expect_json = '[{"staticSize":2, "dynamicSize":0}]'
|
||||||
expect_json_v2 = '''[
|
expect_json_v2 = '''[
|
||||||
{"staticSize": 2, "exclusiveSize": 0, "size":2, "members": [
|
{"staticSize": 2, "exclusiveSize": 0, "size":2, "members": [
|
||||||
{"typeNames": ["ScopedEnumUint8"], "staticSize":1, "exclusiveSize":1, "size":1},
|
{"typeNames": ["ns_enums::ScopedEnumUint8"], "staticSize":1, "exclusiveSize":1, "size":1},
|
||||||
{"typeNames": ["uint8_t"], "staticSize":1, "exclusiveSize":1, "size":1}
|
{"typeNames": ["uint8_t"], "staticSize":1, "exclusiveSize":1, "size":1}
|
||||||
]}
|
]}
|
||||||
]'''
|
]'''
|
||||||
|
@ -77,7 +77,6 @@ namespace cpp2 {
|
|||||||
|
|
||||||
[cases]
|
[cases]
|
||||||
[cases.unpacked]
|
[cases.unpacked]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const cpp2::MyThriftStructUnpacked&"]
|
param_types = ["const cpp2::MyThriftStructUnpacked&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
cpp2::MyThriftStructUnpacked ret;
|
cpp2::MyThriftStructUnpacked ret;
|
||||||
@ -95,9 +94,19 @@ namespace cpp2 {
|
|||||||
{"name":"__fbthrift_field_c", "staticSize":4, "isset":true},
|
{"name":"__fbthrift_field_c", "staticSize":4, "isset":true},
|
||||||
{"name":"__isset", "staticSize":3}
|
{"name":"__isset", "staticSize":3}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":16,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":16,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]
|
||||||
|
}]'''
|
||||||
|
|
||||||
[cases.packed]
|
[cases.packed]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const cpp2::MyThriftStructPacked&"]
|
param_types = ["const cpp2::MyThriftStructPacked&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
cpp2::MyThriftStructPacked ret;
|
cpp2::MyThriftStructPacked ret;
|
||||||
@ -126,9 +135,25 @@ namespace cpp2 {
|
|||||||
{"name":"__fbthrift_field_j", "staticSize":4, "isset":true},
|
{"name":"__fbthrift_field_j", "staticSize":4, "isset":true},
|
||||||
{"name":"__isset", "staticSize":2}
|
{"name":"__isset", "staticSize":2}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":44,
|
||||||
|
"exclusiveSize":2,
|
||||||
|
"size":44,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_d", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_e", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_f", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_g", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_h", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_i", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_j", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__isset", "staticSize":2, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
|
|
||||||
[cases.packed_non_atomic]
|
[cases.packed_non_atomic]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const cpp2::MyThriftStructPackedNonAtomic&"]
|
param_types = ["const cpp2::MyThriftStructPackedNonAtomic&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
cpp2::MyThriftStructPackedNonAtomic ret;
|
cpp2::MyThriftStructPackedNonAtomic ret;
|
||||||
@ -147,9 +172,19 @@ namespace cpp2 {
|
|||||||
{"name":"__fbthrift_field_d", "staticSize":4, "isset":false},
|
{"name":"__fbthrift_field_d", "staticSize":4, "isset":false},
|
||||||
{"name":"__isset", "staticSize":1}
|
{"name":"__isset", "staticSize":1}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":20,
|
||||||
|
"exclusiveSize":3,
|
||||||
|
"size":20,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_d", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__isset", "staticSize":1, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
|
|
||||||
[cases.out_of_order]
|
[cases.out_of_order]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const cpp2::MyThriftStructOutOfOrder&"]
|
param_types = ["const cpp2::MyThriftStructOutOfOrder&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
cpp2::MyThriftStructOutOfOrder ret;
|
cpp2::MyThriftStructOutOfOrder ret;
|
||||||
@ -166,9 +201,18 @@ namespace cpp2 {
|
|||||||
{"name":"__fbthrift_field_c", "staticSize":4, "isset":false},
|
{"name":"__fbthrift_field_c", "staticSize":4, "isset":false},
|
||||||
{"name":"__isset", "staticSize":3}
|
{"name":"__isset", "staticSize":3}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":16,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":16,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
|
|
||||||
[cases.required]
|
[cases.required]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const cpp2::MyThriftStructRequired&"]
|
param_types = ["const cpp2::MyThriftStructRequired&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
cpp2::MyThriftStructRequired ret;
|
cpp2::MyThriftStructRequired ret;
|
||||||
@ -189,9 +233,21 @@ namespace cpp2 {
|
|||||||
{"name":"__fbthrift_field_f", "staticSize":4, "isset":true},
|
{"name":"__fbthrift_field_f", "staticSize":4, "isset":true},
|
||||||
{"name":"__isset", "staticSize":3}
|
{"name":"__isset", "staticSize":3}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":28,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":28,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_d", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_e", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_f", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
|
|
||||||
[cases.box]
|
[cases.box]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const cpp2::MyThriftStructBoxed&"]
|
param_types = ["const cpp2::MyThriftStructBoxed&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
cpp2::MyThriftStructBoxed ret;
|
cpp2::MyThriftStructBoxed ret;
|
||||||
@ -211,6 +267,18 @@ namespace cpp2 {
|
|||||||
{"name":"__fbthrift_field_e", "staticSize":4, "isset":true},
|
{"name":"__fbthrift_field_e", "staticSize":4, "isset":true},
|
||||||
{"name":"__isset", "staticSize":3}
|
{"name":"__isset", "staticSize":3}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":32,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":32,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":8, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":8, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_d", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_e", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
|
|
||||||
[cases.no_capture]
|
[cases.no_capture]
|
||||||
param_types = ["const cpp2::MyThriftStructBoxed&"]
|
param_types = ["const cpp2::MyThriftStructBoxed&"]
|
||||||
@ -231,3 +299,15 @@ namespace cpp2 {
|
|||||||
{"name":"__fbthrift_field_e", "staticSize":4, "NOT":"isset"},
|
{"name":"__fbthrift_field_e", "staticSize":4, "NOT":"isset"},
|
||||||
{"name":"__isset", "staticSize":3}
|
{"name":"__isset", "staticSize":3}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":32,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":32,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":8, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":8, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_d", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_e", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
|
@ -58,7 +58,6 @@ raw_definitions = '''
|
|||||||
'''
|
'''
|
||||||
[cases]
|
[cases]
|
||||||
[cases.present]
|
[cases.present]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const FakeThriftWithData&"]
|
param_types = ["const FakeThriftWithData&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
FakeThriftWithData ret;
|
FakeThriftWithData ret;
|
||||||
@ -78,8 +77,17 @@ raw_definitions = '''
|
|||||||
{"name":"__fbthrift_field_c", "staticSize":4, "isset":true},
|
{"name":"__fbthrift_field_c", "staticSize":4, "isset":true},
|
||||||
{"name":"__isset", "staticSize":3}
|
{"name":"__isset", "staticSize":3}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":16,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":16,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
[cases.missing]
|
[cases.missing]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const FakeThriftWithoutData&"]
|
param_types = ["const FakeThriftWithoutData&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
FakeThriftWithoutData ret;
|
FakeThriftWithoutData ret;
|
||||||
@ -99,8 +107,17 @@ raw_definitions = '''
|
|||||||
{"name":"__fbthrift_field_c", "staticSize":4, "NOT":"isset"},
|
{"name":"__fbthrift_field_c", "staticSize":4, "NOT":"isset"},
|
||||||
{"name":"__isset", "staticSize":3}
|
{"name":"__isset", "staticSize":3}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":16,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":16,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]}]'''
|
||||||
[cases.mixed]
|
[cases.mixed]
|
||||||
oil_skip = 'oil does not support thrift isset yet' # https://github.com/facebookexperimental/object-introspection/issues/296
|
|
||||||
param_types = ["const Mixed&"]
|
param_types = ["const Mixed&"]
|
||||||
setup = '''
|
setup = '''
|
||||||
Mixed ret;
|
Mixed ret;
|
||||||
@ -143,3 +160,31 @@ raw_definitions = '''
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]}]'''
|
]}]'''
|
||||||
|
expect_json_v2 = '''[{
|
||||||
|
"staticSize":32,
|
||||||
|
"exclusiveSize":0,
|
||||||
|
"size":32,
|
||||||
|
"members":[
|
||||||
|
{
|
||||||
|
"staticSize":16,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":16,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "is_set":false},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "is_set":true},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"staticSize":16,
|
||||||
|
"exclusiveSize":1,
|
||||||
|
"size":16,
|
||||||
|
"members":[
|
||||||
|
{"name":"__fbthrift_field_a", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_b", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__fbthrift_field_c", "staticSize":4, "NOT":"is_set"},
|
||||||
|
{"name":"__isset", "staticSize":3, "NOT":"is_set"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]}]'''
|
||||||
|
Loading…
Reference in New Issue
Block a user