object-introspection/test/integration/capture_keys.toml

388 lines
11 KiB
TOML

# This file contains tests for core key-capture features at the top, followed
# by basic tests for each container type which supports key capture.
includes = ["map","sys/mman.h"]
definitions = '''
struct MapHolder {
std::map<int, int> captureMyKeys;
std::map<int, int> dontCaptureKeysHere;
};
using MyIntMap = std::map<int,int>;
struct MyTypedefIntMapHolder {
MyIntMap captureMyKeys;
};
enum class MyEnum {
One = 1,
Two = 2,
Three = 3,
};
struct KeyObj {
int n;
auto operator<=>(const KeyObj &) const = default;
};
template <typename T>
class FixedAllocator {
public:
using value_type = T;
T* allocate(std::size_t n) {
uintptr_t loc = base_ + num_*0x1000;
num_++;
return (T*)mmap((void*)loc,
n,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,
-1,
0);
}
void deallocate(T*, std::size_t) noexcept {
// cba
}
private:
uintptr_t base_ = 0x300000;
size_t num_ = 0;
};
'''
[cases]
[cases.int]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<int, int>&"]
setup = "return {{{1,2},{3,4}}};"
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[1]",
"typePath": ["a0","[1]"],
"data": 1,
"members": [
{"name": "key", "typePath": ["a0","[1]","key"]},
{"name": "value", "typePath": ["a0","[1]","value"]}
]
},
{
"name": "[3]",
"typePath": ["a0","[3]"],
"data": 3,
"members": [
{"name": "key", "typePath": ["a0","[3]","key"]},
{"name": "value", "typePath": ["a0","[3]","value"]}
]
}
]
}]'''
[cases.string]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<std::string, int>&"]
setup = '''return
{{
{"abc", 1},
{"hohoho", 2}
}};'''
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[abc]",
"typePath": ["a0","[abc]"],
"data": "abc",
"members": [
{"name": "key", "typePath": ["a0","[abc]","key"]},
{"name": "value", "typePath": ["a0","[abc]","value"]}
]
},
{
"name": "[hohoho]",
"typePath": ["a0","[hohoho]"],
"data": "hohoho",
"members": [
{"name": "key", "typePath": ["a0","[hohoho]","key"]},
{"name": "value", "typePath": ["a0","[hohoho]","value"]}
]
}
]
}]'''
[cases.enum]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<MyEnum, int>&"]
setup = "return {{{MyEnum::One,2},{MyEnum::Three,4}}};"
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[1]",
"typePath": ["a0","[1]"],
"data": 1,
"members": [
{"name": "key", "typePath": ["a0","[1]","key"]},
{"name": "value", "typePath": ["a0","[1]","value"]}
]
},
{
"name": "[3]",
"typePath": ["a0","[3]"],
"data": 3,
"members": [
{"name": "key", "typePath": ["a0","[3]","key"]},
{"name": "value", "typePath": ["a0","[3]","value"]}
]
}
]
}]'''
[cases.object]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<KeyObj, int, std::less<KeyObj>, FixedAllocator<std::pair<const KeyObj, int>>>&"]
# We're going to record the addresses of these objects, so we use a custom
# allocator based on mmap to get them at a known location in memory
setup = '''
std::map<KeyObj, int, std::less<KeyObj>, FixedAllocator<std::pair<const KeyObj, int>>> m;
m.insert({KeyObj{1}, 1});
m.insert({KeyObj{2}, 2});
return m;
'''
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[0x300020]",
"typePath": ["a0","[0x300020]"],
"data": "0x300020",
"members": [
{"name": "key", "typePath": ["a0","[0x300020]","key"]},
{"name": "value", "typePath": ["a0","[0x300020]","value"]}
]
},
{
"name": "[0x301020]",
"typePath": ["a0","[0x301020]"],
"data": "0x301020",
"members": [
{"name": "key", "typePath": ["a0","[0x301020]","key"]},
{"name": "value", "typePath": ["a0","[0x301020]","value"]}
]
}
]
}]'''
[cases.multi_level]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::map<int, std::map<std::string, std::vector<int>>>&"]
setup = '''return
{{
{123, {
{"haha", {1,2}}
}},
{456, {
{"uh oh", {3}},
{"spaghettio", {4,5,6}}
}}
}};'''
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '''[{
"name": "a0",
"typePath": ["a0"],
"members": [
{
"name": "[123]",
"typePath": ["a0","[123]"],
"data": 123,
"members": [
{"name": "key", "typePath": ["a0","[123]","key"]},
{
"name": "value",
"typePath": ["a0","[123]","value"],
"members": [
{
"name": "[]",
"typePath": ["a0","[123]","value","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","[123]","value","[]","key"]},
{"name": "value", "typePath": ["a0","[123]","value","[]","value"]}
]
}
]
}
]
},
{
"name": "[456]",
"typePath": ["a0","[456]"],
"data": 456,
"members": [
{"name": "key", "typePath": ["a0","[456]","key"]},
{
"name": "value",
"typePath": ["a0","[456]","value"],
"members": [
{
"name": "[]",
"typePath": ["a0","[456]","value","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","[456]","value","[]","key"]},
{"name": "value", "typePath": ["a0","[456]","value","[]","value"]}
]
},
{
"name": "[]",
"typePath": ["a0","[456]","value","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","[456]","value","[]","key"]},
{"name": "value", "typePath": ["a0","[456]","value","[]","value"]}
]
}
]
}
]
}
]
}]'''
[cases.config]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const MapHolder&"]
setup = '''return {MapHolder{
.captureMyKeys{ {1,2},{3,4} },
.dontCaptureKeysHere{ {5,6} },
}};'''
config_suffix = '''
[[codegen.capture_keys]]
type = "MapHolder"
members = ["captureMyKeys"]
'''
expect_json_v2 = '''[{
"members": [
{
"name": "captureMyKeys",
"typePath": ["a0","captureMyKeys"],
"members": [
{
"name": "[1]",
"typePath": ["a0","captureMyKeys","[1]"],
"data": 1,
"members": [
{"name": "key", "typePath": ["a0","captureMyKeys","[1]","key"]},
{"name": "value", "typePath": ["a0","captureMyKeys","[1]","value"]}
]
},
{
"name": "[3]",
"typePath": ["a0","captureMyKeys","[3]"],
"data": 3,
"members": [
{"name": "key", "typePath": ["a0","captureMyKeys","[3]","key"]},
{"name": "value", "typePath": ["a0","captureMyKeys","[3]","value"]}
]
}
]
},
{
"name": "dontCaptureKeysHere",
"typePath": ["a0","dontCaptureKeysHere"],
"members": [
{
"name": "[]",
"typePath": ["a0","dontCaptureKeysHere","[]"],
"NOT":"data",
"members": [
{"name": "key", "typePath": ["a0","dontCaptureKeysHere","[]","key"]},
{"name": "value", "typePath": ["a0","dontCaptureKeysHere","[]","value"]}
]
}
]
}
]
}]'''
[cases.typedef]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const MyTypedefIntMapHolder&"]
setup = '''return {MyTypedefIntMapHolder{
.captureMyKeys{ {1,2},{3,4} },
}};'''
config_suffix = '''
[[codegen.capture_keys]]
type = "MyTypedefIntMapHolder"
members = ["captureMyKeys"]
'''
expect_json_v2 = '''[{
"members": [
{
"name": "captureMyKeys",
"typePath": ["a0","captureMyKeys"],
"typeNames": ["MyIntMap", "std::map<int32_t, int32_t, less<int>, std::allocator<std::pair<int32_t const, int32_t>>>"],
"members": [
{
"name": "[1]",
"typePath": ["a0","captureMyKeys","[1]"],
"data": 1,
"members": [
{"name": "key", "typePath": ["a0","captureMyKeys","[1]","key"]},
{"name": "value", "typePath": ["a0","captureMyKeys","[1]","value"]}
]
},
{
"name": "[3]",
"typePath": ["a0","captureMyKeys","[3]"],
"data": 3,
"members": [
{"name": "key", "typePath": ["a0","captureMyKeys","[3]","key"]},
{"name": "value", "typePath": ["a0","captureMyKeys","[3]","value"]}
]
}
]
}
]
}]'''
[cases.std_unordered_map]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const std::unordered_map<int, int>&"]
setup = "return {{{1,2}}};"
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '[{"members": [{"data": 1}]}]'
[cases.folly_sorted_vector_map]
oid_skip = "Requires TreeBuilderV2"
param_types = ["const folly::sorted_vector_map<int, int>&"]
setup = "return {{{1,2}}};"
config_suffix = '''
[[codegen.capture_keys]]
top_level = true
'''
expect_json_v2 = '[{"members": [{"data": 1}]}]'