Integration tests: Add tests for unrestricted unions

i.e. unions with non-POD members

We can't examine untagged unions, but we should be able to support
looking inside tagged unions at some point in the future.
This commit is contained in:
Alastair Robertson 2023-07-13 07:23:02 -07:00 committed by Alastair Robertson
parent 30cd23fa53
commit c3fec2624b
4 changed files with 146 additions and 4 deletions

View File

@ -20,21 +20,21 @@ workflows:
- build-gcc
oid_test_args: "-ftype-graph"
tests_regex: "OidIntegration\\..*"
exclude_regex: ".*inheritance_polymorphic.*|.*pointers_incomplete_containing_struct|.*arrays_member_int0"
exclude_regex: ".*inheritance_polymorphic.*|.*pointers_incomplete_containing_struct|.*arrays_member_int0|OidIntegration.unions.*|.*thrift_unions_dynamic_.*"
- test:
name: test-typed-data-segment-gcc
requires:
- build-gcc
oid_test_args: "-ftyped-data-segment"
tests_regex: "OidIntegration\\..*"
exclude_regex: ".*inheritance_polymorphic.*|.*pointers.*|.*arrays_member_int0|.*cycles_.*"
exclude_regex: ".*inheritance_polymorphic.*|.*pointers.*|.*arrays_member_int0|.*cycles_.*|OidIntegration.unions.*|.*thrift_unions_dynamic_.*"
- test:
name: test-tree-builder-type-checking-gcc
requires:
- build-gcc
oid_test_args: "-ftree-builder-type-checking"
tests_regex: "OidIntegration\\..*"
exclude_regex: ".*inheritance_polymorphic.*|.*pointers.*|.*arrays_member_int0|.*cycles_.*"
exclude_regex: ".*inheritance_polymorphic.*|.*pointers.*|.*arrays_member_int0|.*cycles_.*|OidIntegration.unions.*|.*thrift_unions_dynamic_.*"
- coverage:
name: coverage
requires:
@ -68,7 +68,7 @@ workflows:
oid_test_args: "-ftype-graph"
tests_regex: "OidIntegration\\..*"
# Tests disabled due to bad DWARF generated by the old clang compiler in CI
exclude_regex: ".*inheritance_polymorphic.*|.*pointers_incomplete_containing_struct|.*arrays_member_int0|.*fbstring.*|.*std_string_*|.*multi_arg_tb_.*|.*ignored_a"
exclude_regex: ".*inheritance_polymorphic.*|.*pointers_incomplete_containing_struct|.*arrays_member_int0|.*fbstring.*|.*std_string_*|.*multi_arg_tb_.*|.*ignored_a|OidIntegration.unions.*|.*thrift_unions_dynamic_.*"
executors:
ubuntu-docker:

View File

@ -8,6 +8,7 @@ set(THRIFT_TEST_CONFIGS
thrift_isset.toml
thrift_isset_missing.toml
thrift_namespaces.toml
thrift_unions.toml
)
find_package(Thrift)

View File

@ -0,0 +1,63 @@
# TODO: The dynamic union tests should be updated when tagged union support is in:
# https://github.com/facebookexperimental/object-introspection/issues/234
thrift_definitions = '''
union StaticUnion {
1: i32 a;
2: i32 b;
3: i32 c;
}
union DynamicUnion {
1: i32 n;
2: list<i32> vec;
}
'''
raw_definitions = '''
namespace cpp2 {
void StaticUnion::__fbthrift_clear() {}
void DynamicUnion::__fbthrift_clear() {}
}
'''
[cases]
[cases.static]
param_types = ["const cpp2::StaticUnion&"]
setup = '''
cpp2::StaticUnion ret;
return ret;
'''
expect_json = '''[{
"staticSize":8,
"dynamicSize":0,
"members":[
{"typeName":"storage_type", "name":"value_", "staticSize":4},
{"typeName":"underlying_type_t<cpp2::StaticUnion::Type>", "name":"type_", "staticSize":4}
]}]'''
[cases.dynamic_int]
param_types = ["const cpp2::DynamicUnion&"]
setup = '''
cpp2::DynamicUnion ret;
ret.set_n(123);
return ret;
'''
expect_json = '''[{
"staticSize":32,
"dynamicSize":0,
"members":[
{"typeName":"storage_type", "name":"value_", "staticSize":24},
{"typeName":"underlying_type_t<cpp2::DynamicUnion::Type>", "name":"type_", "staticSize":4}
]}]'''
[cases.dynamic_vec]
param_types = ["const cpp2::DynamicUnion&"]
setup = '''
cpp2::DynamicUnion ret;
ret.set_vec({1,2,3});
return ret;
'''
expect_json = '''[{
"staticSize":32,
"dynamicSize":0,
"members":[
{"typeName":"storage_type", "name":"value_", "staticSize":24},
{"typeName":"underlying_type_t<cpp2::DynamicUnion::Type>", "name":"type_", "staticSize":4}
]}]'''

View File

@ -0,0 +1,78 @@
# TODO: The tagged union tests should be updated when tagged union support is in:
# https://github.com/facebookexperimental/object-introspection/issues/234
includes = ["string", "unordered_map", "vector"]
definitions = '''
union MyUnion {
int n;
std::vector<int> vec;
std::unordered_map<std::string, std::string> map;
MyUnion(int n_) : n(n_) {}
MyUnion(const std::vector<int>& vec_) : vec(vec_) {}
MyUnion(const std::unordered_map<std::string, std::string>& map_) : map(map_) {}
~MyUnion() {}
};
struct TaggedUnion {
MyUnion storage;
uint8_t tag;
TaggedUnion(const MyUnion& storage_, uint8_t tag_) : storage(0), tag(tag_) {
copyStorage(storage_);
}
TaggedUnion(const TaggedUnion& other) : storage(0), tag(other.tag) {
copyStorage(other.storage);
}
void copyStorage(const MyUnion& other) {
if (tag == 0) {
storage.n = other.n;
} else if (tag == 1) {
new (&storage.vec) decltype(MyUnion::vec){other.vec};
} else if (tag == 2) {
new (&storage.map) decltype(MyUnion::map){other.map};
} else {
assert(false);
}
}
};
'''
[cases]
[cases.int]
param_types = ["const MyUnion&"]
setup = "return 123;"
expect_json = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"}]'
[cases.vector]
param_types = ["const MyUnion&"]
setup = "return std::vector{1,2,3};"
expect_json = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"}]'
[cases.unordered_map]
param_types = ["const MyUnion&"]
setup = 'return std::unordered_map<std::string, std::string>{{"a", "b"}, {"c","d"}};'
expect_json = '[{"staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"}]'
[cases.tagged_int]
param_types = ["const TaggedUnion&"]
setup = "return TaggedUnion{MyUnion{123}, 0};"
expect_json = '''[
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "members":[
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"},
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "NOT":"members"}
]}]'''
[cases.tagged_vector]
param_types = ["const TaggedUnion&"]
setup = "return TaggedUnion{MyUnion{std::vector{1,2,3}}, 1};"
expect_json = '''[
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "members":[
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"},
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "NOT":"members"}
]}]'''
[cases.tagged_unordered_map]
param_types = ["const TaggedUnion&"]
setup = 'return TaggedUnion{MyUnion{std::unordered_map<std::string, std::string>{{"a", "b"}, {"c","d"}}}, 2};'
expect_json = '''[
{"staticSize":64, "dynamicSize":0, "exclusiveSize":7, "members":[
{"name":"storage", "staticSize":56, "dynamicSize":0, "exclusiveSize":56, "NOT":"members"},
{"name":"tag", "staticSize":1, "dynamicSize":0, "exclusiveSize":1, "NOT":"members"}
]}]'''