2023-09-22 14:53:13 +01:00
|
|
|
# This file contains tests for core key-capture features at the top, followed
|
|
|
|
# by basic tests for each container type which supports key capture.
|
|
|
|
|
2023-09-29 03:12:16 +01:00
|
|
|
includes = ["map","sys/mman.h"]
|
2023-09-22 14:53:13 +01:00
|
|
|
definitions = '''
|
|
|
|
struct MapHolder {
|
|
|
|
std::map<int, int> captureMyKeys;
|
|
|
|
std::map<int, int> dontCaptureKeysHere;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class MyEnum {
|
|
|
|
One = 1,
|
|
|
|
Two = 2,
|
|
|
|
Three = 3,
|
|
|
|
};
|
2023-09-29 03:12:16 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
2023-09-22 14:53:13 +01:00
|
|
|
'''
|
|
|
|
[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": [
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[1]",
|
|
|
|
"typePath": ["a0","[1]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 1,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[1]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[1]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[3]",
|
|
|
|
"typePath": ["a0","[3]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 3,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[3]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[3]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}]'''
|
|
|
|
|
|
|
|
[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": [
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[abc]",
|
|
|
|
"typePath": ["a0","[abc]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": "abc",
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[abc]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[abc]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[hohoho]",
|
|
|
|
"typePath": ["a0","[hohoho]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": "hohoho",
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[hohoho]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[hohoho]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}]'''
|
|
|
|
|
|
|
|
[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": [
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[1]",
|
|
|
|
"typePath": ["a0","[1]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 1,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[1]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[1]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[3]",
|
|
|
|
"typePath": ["a0","[3]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 3,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[3]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[3]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}]'''
|
|
|
|
|
2023-09-29 03:12:16 +01:00
|
|
|
[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": [
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[0x300020]",
|
|
|
|
"typePath": ["a0","[0x300020]"],
|
2023-09-29 03:12:16 +01:00
|
|
|
"data": "0x300020",
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[0x300020]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[0x300020]","value"]}
|
2023-09-29 03:12:16 +01:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[0x301020]",
|
|
|
|
"typePath": ["a0","[0x301020]"],
|
2023-09-29 03:12:16 +01:00
|
|
|
"data": "0x301020",
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[0x301020]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[0x301020]","value"]}
|
2023-09-29 03:12:16 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}]'''
|
|
|
|
|
2023-09-22 14:53:13 +01:00
|
|
|
[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": [
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[123]",
|
|
|
|
"typePath": ["a0","[123]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 123,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[123]","key"]},
|
2023-09-22 14:53:13 +01:00
|
|
|
{
|
|
|
|
"name": "value",
|
2023-10-09 21:39:33 +01:00
|
|
|
"typePath": ["a0","[123]","value"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"members": [
|
|
|
|
{
|
|
|
|
"name": "[]",
|
2023-10-09 21:39:33 +01:00
|
|
|
"typePath": ["a0","[123]","value","[]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"NOT":"data",
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[123]","value","[]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[123]","value","[]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[456]",
|
|
|
|
"typePath": ["a0","[456]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 456,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[456]","key"]},
|
2023-09-22 14:53:13 +01:00
|
|
|
{
|
|
|
|
"name": "value",
|
2023-10-09 21:39:33 +01:00
|
|
|
"typePath": ["a0","[456]","value"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"members": [
|
|
|
|
{
|
|
|
|
"name": "[]",
|
2023-10-09 21:39:33 +01:00
|
|
|
"typePath": ["a0","[456]","value","[]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"NOT":"data",
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[456]","value","[]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[456]","value","[]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"name": "[]",
|
2023-10-09 21:39:33 +01:00
|
|
|
"typePath": ["a0","[456]","value","[]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"NOT":"data",
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","[456]","value","[]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","[456]","value","[]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}]'''
|
|
|
|
|
|
|
|
[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": [
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[1]",
|
|
|
|
"typePath": ["a0","captureMyKeys","[1]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 1,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","captureMyKeys","[1]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","captureMyKeys","[1]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2023-10-09 21:39:33 +01:00
|
|
|
"name": "[3]",
|
|
|
|
"typePath": ["a0","captureMyKeys","[3]"],
|
2023-09-22 14:53:13 +01:00
|
|
|
"data": 3,
|
|
|
|
"members": [
|
2023-10-09 21:39:33 +01:00
|
|
|
{"name": "key", "typePath": ["a0","captureMyKeys","[3]","key"]},
|
|
|
|
{"name": "value", "typePath": ["a0","captureMyKeys","[3]","value"]}
|
2023-09-22 14:53:13 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"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.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}]}]'
|
2023-09-27 21:46:19 +01:00
|
|
|
[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}]}]'
|