Commit | Line | Data |
---|---|---|
c3e68e71 JR |
1 | /* |
2 | * test_map.c | |
3 | * | |
4 | * Unit tests for the map API. | |
5 | * | |
6 | * Copyright (C) 2021 Francis Deslauriers <francis.deslauriers@efficios.com> | |
7 | * | |
8 | * SPDX-License-Identifier: GPL-2.0-only | |
9 | * | |
10 | */ | |
11 | ||
12 | #include "lttng/domain.h" | |
13 | #include "lttng/map/map.h" | |
14 | #include <assert.h> | |
15 | #include <inttypes.h> | |
16 | #include <stdio.h> | |
17 | #include <string.h> | |
18 | #include <unistd.h> | |
19 | ||
20 | #include <tap/tap.h> | |
21 | ||
22 | #include <lttng/map/map-internal.h> | |
23 | ||
24 | #include <common/dynamic-buffer.h> | |
25 | #include <common/buffer-view.h> | |
26 | #include <common/payload.h> | |
27 | ||
28 | #define NUM_TESTS 70 | |
29 | ||
30 | static | |
31 | void test_map_key_value_pair_serialize_deserialize(void) | |
32 | { | |
33 | struct lttng_map_key_value_pair *kv; | |
34 | struct lttng_map_key_value_pair *kv_from_payload; | |
35 | struct lttng_payload buffer; | |
36 | enum lttng_map_status map_status; | |
37 | const char *kv_from_payload_key, *key = "ma_clé"; | |
38 | int64_t kv_from_payload_value, value = 133121; | |
39 | int ret; | |
40 | ||
41 | diag("Simple lttng_map_key_value_pair tests"); | |
42 | ||
43 | lttng_payload_init(&buffer); | |
44 | ||
45 | kv = lttng_map_key_value_pair_create(key, value); | |
46 | ok(kv, "Key-value pair created"); | |
47 | ||
48 | /* Test incr value action serialization */ | |
49 | ret = lttng_map_key_value_pair_serialize(kv, &buffer); | |
50 | ok(ret == 0, "Key-value pair serialized"); | |
51 | ||
52 | { | |
53 | struct lttng_payload_view view = | |
54 | lttng_payload_view_from_payload(&buffer, 0, -1); | |
55 | ||
56 | (void) lttng_map_key_value_pair_create_from_payload( | |
57 | &view, &kv_from_payload); | |
58 | } | |
59 | ok(kv_from_payload, "Key-value pair created from payload is non-null"); | |
60 | ||
61 | map_status = lttng_map_key_value_pair_get_key(kv_from_payload, | |
62 | &kv_from_payload_key); | |
63 | ok(map_status == LTTNG_MAP_STATUS_OK, "Key-value pair 1 key"); | |
64 | ok(strcmp(kv_from_payload_key, key) == 0, "Key-value pair from payload has correct key"); | |
65 | ||
66 | map_status = lttng_map_key_value_pair_get_value(kv_from_payload, | |
67 | &kv_from_payload_value); | |
68 | ok(map_status == LTTNG_MAP_STATUS_OK, "Key-value pair 1 value"); | |
69 | ok(kv_from_payload_value == value, "Key-value pair from payload has correct value"); | |
70 | ||
71 | lttng_payload_reset(&buffer); | |
72 | lttng_map_key_value_pair_destroy(kv); | |
73 | lttng_map_key_value_pair_destroy(kv_from_payload); | |
74 | } | |
75 | ||
76 | static | |
77 | void test_map_key_value_pair_list_serialize_deserialize(void) | |
78 | { | |
79 | struct lttng_map_key_value_pair *kv; | |
80 | const struct lttng_map_key_value_pair *kv_from_payload = NULL; | |
81 | ||
82 | struct lttng_map_key_value_pair_list *kv_pair_list; | |
83 | struct lttng_map_key_value_pair_list *kv_pair_list_from_payload; | |
84 | ||
85 | struct lttng_payload buffer; | |
86 | enum lttng_map_status map_status; | |
87 | const char *kv_from_payload_key, *key1 = "ma_clé", *key2 = "autre_clé"; | |
88 | int64_t kv_from_payload_value, value1 = 123456, value2 = 98765; | |
89 | enum lttng_map_key_value_pair_list_type list_type = | |
90 | LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID; | |
91 | uint64_t identifier = 3192112; | |
92 | bool summed_all_cpus = true; | |
93 | unsigned int kv_count; | |
94 | int ret; | |
95 | ||
96 | diag("Simple lttng_map_key_value_pair_list tests"); | |
97 | ||
98 | lttng_payload_init(&buffer); | |
99 | ||
100 | kv_pair_list = lttng_map_key_value_pair_list_create(list_type, | |
101 | summed_all_cpus); | |
102 | ok(kv_pair_list, "Key-value pair_list list created"); | |
103 | ||
104 | map_status = lttng_map_key_value_pair_list_set_identifier(kv_pair_list, | |
105 | identifier); | |
106 | ok(kv_pair_list, "Key-value set identifier"); | |
107 | ||
108 | kv = lttng_map_key_value_pair_create(key1, value1); | |
109 | ok(kv, "Key-value pair 1 created"); | |
110 | ||
111 | map_status = lttng_map_key_value_pair_list_append_key_value(kv_pair_list, kv); | |
112 | ok(map_status == LTTNG_MAP_STATUS_OK, "Key value 1 appended to list"); | |
113 | ||
114 | kv = lttng_map_key_value_pair_create(key2, value2); | |
115 | ok(kv, "Key-value pair 2 created"); | |
116 | ||
117 | map_status = lttng_map_key_value_pair_list_append_key_value(kv_pair_list, kv); | |
118 | ok(map_status == LTTNG_MAP_STATUS_OK, "Key value 2 appended to list"); | |
119 | ||
120 | /* Test incr value action serialization */ | |
121 | ret = lttng_map_key_value_pair_list_serialize(kv_pair_list, &buffer); | |
122 | ok(ret == 0, "Key-value pair_list list serialized"); | |
123 | ||
124 | { | |
125 | struct lttng_payload_view view = | |
126 | lttng_payload_view_from_payload(&buffer, 0, -1); | |
127 | ||
128 | (void) lttng_map_key_value_pair_list_create_from_payload( | |
129 | &view, &kv_pair_list_from_payload); | |
130 | } | |
131 | ok(kv_pair_list_from_payload, "Key-value pair list created from payload is non-null"); | |
132 | ||
133 | ok(lttng_map_key_value_pair_list_get_summed_all_cpu(kv_pair_list_from_payload) == summed_all_cpus, | |
134 | "Got the expected summed all cpu state"); | |
135 | ||
136 | ok(lttng_map_key_value_pair_list_get_type(kv_pair_list_from_payload) == list_type, | |
137 | "Got the expected list type"); | |
138 | ok(lttng_map_key_value_pair_list_get_identifer(kv_pair_list_from_payload) == identifier, | |
139 | "Got the expected list identifier"); | |
140 | ||
141 | map_status = lttng_map_key_value_pair_list_get_count( | |
142 | kv_pair_list_from_payload, &kv_count); | |
143 | ok(map_status == LTTNG_MAP_STATUS_OK, "Got key value pair count"); | |
144 | ok(kv_count == 2, "Got the right key value pair count"); | |
145 | ||
146 | kv_from_payload = lttng_map_key_value_pair_list_get_at_index( | |
147 | kv_pair_list_from_payload, 0); | |
148 | ok(kv_from_payload, "Key-value pair 1 created from payload"); | |
149 | ||
150 | map_status = lttng_map_key_value_pair_get_key(kv_from_payload, | |
151 | &kv_from_payload_key); | |
152 | ok(strcmp(kv_from_payload_key, key1) == 0, "Key-value pair 1 from payload has correct key"); | |
153 | ||
154 | map_status = lttng_map_key_value_pair_get_value(kv_from_payload, | |
155 | &kv_from_payload_value); | |
156 | ok(kv_from_payload_value == value1, "Key-value pair 1 from payload has correct value"); | |
157 | ||
158 | kv_from_payload = lttng_map_key_value_pair_list_get_at_index( | |
159 | kv_pair_list_from_payload, 1); | |
160 | ok(kv_from_payload, "Key-value pair 2 created from payload"); | |
161 | ||
162 | map_status = lttng_map_key_value_pair_get_key(kv_from_payload, | |
163 | &kv_from_payload_key); | |
164 | ok(strcmp(kv_from_payload_key, key2) == 0, "Key-value pair 2 from payload has correct key"); | |
165 | ||
166 | map_status = lttng_map_key_value_pair_get_value(kv_from_payload, | |
167 | &kv_from_payload_value); | |
168 | ok(kv_from_payload_value == value2, "Key-value pair 2 from payload has correct value"); | |
169 | ||
170 | lttng_payload_reset(&buffer); | |
171 | lttng_map_key_value_pair_list_destroy(kv_pair_list); | |
172 | lttng_map_key_value_pair_list_destroy(kv_pair_list_from_payload); | |
173 | } | |
174 | ||
175 | static | |
176 | void test_map_content_serialize_deserialize(void) | |
177 | { | |
178 | struct lttng_map_content *map_content, *map_content_from_payload; | |
179 | enum lttng_map_status map_status; | |
180 | struct lttng_payload buffer; | |
181 | struct lttng_map_key_value_pair *kv1, *kv2; | |
182 | const char *key1 = "ma_clé", *key2 = "autre_clé"; | |
183 | uint64_t value1 = 123456, value2 = 98765; | |
184 | enum lttng_map_key_value_pair_list_type list_type1 = | |
185 | LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID; | |
186 | enum lttng_map_key_value_pair_list_type list_type2 = | |
187 | LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID; | |
188 | enum lttng_map_key_value_pair_list_type list_type3 = | |
189 | LTTNG_MAP_KEY_VALUE_PAIR_LIST_TYPE_UST_PER_PID_AGGREGATED; | |
190 | uint64_t id1 = 958323, id2 = 121942; | |
191 | struct lttng_map_key_value_pair_list *kv_pair_list1, *kv_pair_list2, *kv_pair_list3; | |
192 | const struct lttng_map_key_value_pair_list *kv_pair_list1_from_payload; | |
193 | const struct lttng_map_key_value_pair_list *kv_pair_list2_from_payload; | |
194 | const struct lttng_map_key_value_pair_list *kv_pair_list3_from_payload; | |
195 | unsigned int list_count; | |
196 | enum lttng_buffer_type buffer_type = LTTNG_BUFFER_PER_UID; | |
197 | int ret; | |
198 | ||
199 | diag("Simple lttng_map_content tests"); | |
200 | ||
201 | lttng_payload_init(&buffer); | |
202 | ||
203 | kv_pair_list1 = lttng_map_key_value_pair_list_create(list_type1, true); | |
204 | map_status = lttng_map_key_value_pair_list_set_identifier(kv_pair_list1, id1); | |
205 | ||
206 | kv_pair_list2 = lttng_map_key_value_pair_list_create(list_type2, false); | |
207 | map_status = lttng_map_key_value_pair_list_set_identifier(kv_pair_list2, id2); | |
208 | ||
209 | kv_pair_list3 = lttng_map_key_value_pair_list_create(list_type3, true); | |
210 | ||
211 | kv1 = lttng_map_key_value_pair_create(key1, value1); | |
212 | map_status = lttng_map_key_value_pair_list_append_key_value(kv_pair_list1, kv1); | |
213 | ||
214 | kv2 = lttng_map_key_value_pair_create(key2, value2); | |
215 | map_status = lttng_map_key_value_pair_list_append_key_value(kv_pair_list2, kv2); | |
216 | ||
217 | map_content = lttng_map_content_create(buffer_type); | |
218 | ||
219 | map_status = lttng_map_content_append_key_value_list(map_content, kv_pair_list1); | |
220 | ok(map_status == LTTNG_MAP_STATUS_OK, "Key value list 1 appended to map_content"); | |
221 | ||
222 | map_status = lttng_map_content_append_key_value_list(map_content, kv_pair_list2); | |
223 | ok(map_status == LTTNG_MAP_STATUS_OK, "Key value list 2 appended to map_content"); | |
224 | ||
225 | map_status = lttng_map_content_append_key_value_list(map_content, kv_pair_list3); | |
226 | ok(map_status == LTTNG_MAP_STATUS_OK, "Key value list 3 appended to map_content"); | |
227 | ||
228 | ret = lttng_map_content_serialize(map_content, &buffer); | |
229 | ok(ret == 0, "Map list serialized"); | |
230 | { | |
231 | struct lttng_payload_view view = | |
232 | lttng_payload_view_from_payload(&buffer, 0, -1); | |
233 | (void) lttng_map_content_create_from_payload( | |
234 | &view, &map_content_from_payload); | |
235 | } | |
236 | ||
237 | ok(map_content, "map content created from payload is non-null"); | |
238 | map_status = lttng_map_content_get_count(map_content_from_payload, &list_count); | |
239 | ok(map_status == LTTNG_MAP_STATUS_OK, "Got key value pair count"); | |
240 | ok(list_count == 3, "Got the expected key-value list count"); | |
241 | ||
242 | ok(lttng_map_content_get_buffer_type(map_content_from_payload) == buffer_type, | |
243 | "Got the expected buffer type"); | |
244 | ||
245 | kv_pair_list1_from_payload = lttng_map_content_get_at_index(map_content_from_payload, 0); | |
246 | ok(kv_pair_list1_from_payload, "Key-value pair list created from payload is non-null"); | |
247 | ||
248 | ok(lttng_map_key_value_pair_list_get_type(kv_pair_list1_from_payload) == list_type1, | |
249 | "Got the expected list type"); | |
250 | ||
251 | ok(lttng_map_key_value_pair_list_get_identifer(kv_pair_list1_from_payload) == id1, | |
252 | "Got the expected list identifier"); | |
253 | ||
254 | kv_pair_list2_from_payload = lttng_map_content_get_at_index(map_content_from_payload, 1); | |
255 | ok(kv_pair_list2_from_payload, "Key-value pair list created from payload is non-null"); | |
256 | ||
257 | ok(lttng_map_key_value_pair_list_get_type(kv_pair_list2_from_payload) == list_type2, | |
258 | "Got the expected list type"); | |
259 | ||
260 | ok(lttng_map_key_value_pair_list_get_identifer(kv_pair_list2_from_payload) == id2, | |
261 | "Got the expected list identifier"); | |
262 | ||
263 | kv_pair_list3_from_payload = lttng_map_content_get_at_index(map_content_from_payload, 2); | |
264 | ok(kv_pair_list3_from_payload, "Key-value pair list created from payload is non-null"); | |
265 | ||
266 | ok(lttng_map_key_value_pair_list_get_type(kv_pair_list3_from_payload) == list_type3, | |
267 | "Got the expected list type"); | |
268 | ||
269 | lttng_payload_reset(&buffer); | |
270 | lttng_map_content_destroy(map_content); | |
271 | lttng_map_content_destroy(map_content_from_payload); | |
272 | } | |
273 | ||
274 | static | |
275 | void test_map(void) | |
276 | { | |
277 | int ret; | |
278 | struct lttng_payload buffer; | |
279 | struct lttng_map *map, *map_from_payload = NULL; | |
280 | enum lttng_map_status map_status; | |
281 | const char *map_name = "map_name", *map_name_from_payload; | |
282 | unsigned int dimension_count = 1; | |
283 | uint64_t first_dim_size = 423; | |
284 | uint64_t dimension_sizes[1] = {first_dim_size}; | |
285 | enum lttng_domain_type domain = LTTNG_DOMAIN_UST; | |
286 | enum lttng_buffer_type buffer_type = LTTNG_BUFFER_PER_UID; | |
287 | enum lttng_map_bitness bitness = LTTNG_MAP_BITNESS_32BITS; | |
288 | enum lttng_map_boundary_policy boundary_policy = LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW; | |
289 | bool coalesce_hits = true; | |
290 | ||
291 | ||
292 | diag("Simple lttng_map tests"); | |
293 | lttng_payload_init(&buffer); | |
294 | ||
295 | map_status = lttng_map_create(map_name, dimension_count, | |
296 | dimension_sizes, domain, buffer_type, bitness, | |
297 | boundary_policy, coalesce_hits, &map); | |
298 | ok(map_status == LTTNG_MAP_STATUS_OK, "Created map"); | |
299 | ||
300 | lttng_map_set_is_enabled(map, true); | |
301 | ||
302 | ret = lttng_map_serialize(map, &buffer); | |
303 | ok(ret == 0, "Map serialized"); | |
304 | ||
305 | { | |
306 | struct lttng_payload_view view = | |
307 | lttng_payload_view_from_payload(&buffer, 0, -1); | |
308 | (void) lttng_map_create_from_payload( | |
309 | &view, &map_from_payload); | |
310 | } | |
311 | ok(map_from_payload, "Map created from payload"); | |
312 | ||
313 | ok(lttng_map_get_dimension_count(map_from_payload) == dimension_count, | |
314 | "Got the expected dimension count from payload"); | |
315 | ||
316 | ok(lttng_map_get_is_enabled(map_from_payload) == 1, | |
317 | "Got the expected enabled state from payload"); | |
318 | ||
319 | ok(lttng_map_get_bitness(map_from_payload) == bitness, | |
320 | "Got the expected bitness from payload"); | |
321 | ||
322 | ok(lttng_map_get_domain(map_from_payload) == domain, | |
323 | "Got the expected domain from payload"); | |
324 | ||
325 | ok(lttng_map_get_buffer_type(map_from_payload) == buffer_type, | |
326 | "Got the expected buffer type from payload"); | |
327 | ||
328 | ok(lttng_map_get_boundary_policy(map_from_payload) == boundary_policy, | |
329 | "Got the expected boundary policy from payload"); | |
330 | ||
331 | ok(lttng_map_get_coalesce_hits(map_from_payload) == coalesce_hits, | |
332 | "Got the expected coalesce hits value from payload"); | |
333 | ||
334 | map_status = lttng_map_get_name(map_from_payload, &map_name_from_payload); | |
335 | ok(map_status == LTTNG_MAP_STATUS_OK, "Got map name from payload"); | |
336 | ok(strcmp(map_name_from_payload, map_name) == 0, | |
337 | "Got the expected map name from payload"); | |
338 | ||
339 | lttng_map_destroy(map); | |
340 | lttng_map_destroy(map_from_payload); | |
341 | lttng_payload_reset(&buffer); | |
342 | } | |
343 | ||
344 | static | |
345 | void test_map_list(void) | |
346 | { | |
347 | int ret; | |
348 | struct lttng_payload buffer; | |
349 | enum lttng_map_status map_status; | |
350 | struct lttng_map *map1, *map2; | |
351 | const struct lttng_map *map1_from_payload = NULL, *map2_from_payload = NULL; | |
352 | struct lttng_map_list *map_list, *map_list_from_payload = NULL; | |
353 | const char *map1_name = "map_name_1", *map1_name_from_payload; | |
354 | const char *map2_name = "map_name_2", *map2_name_from_payload; | |
355 | unsigned int dimension_count = 1, map_count = 0; | |
356 | uint64_t first_dim_size = 423; | |
357 | uint64_t dimension_sizes[1] = {first_dim_size}; | |
358 | enum lttng_domain_type domain = LTTNG_DOMAIN_KERNEL; | |
359 | enum lttng_buffer_type buffer_type1 = LTTNG_BUFFER_PER_PID, buffer_type2 = LTTNG_BUFFER_PER_UID; | |
360 | enum lttng_map_bitness bitness = LTTNG_MAP_BITNESS_64BITS; | |
361 | enum lttng_map_boundary_policy boundary_policy = LTTNG_MAP_BOUNDARY_POLICY_OVERFLOW; | |
362 | bool coalesce_hits = false; | |
363 | ||
364 | diag("Simple lttng_map_list tests"); | |
365 | ||
366 | lttng_payload_init(&buffer); | |
367 | ||
368 | map_status = lttng_map_create(map1_name, dimension_count, | |
369 | dimension_sizes, domain, buffer_type1, bitness, | |
370 | boundary_policy, coalesce_hits, &map1); | |
371 | ok(map_status == LTTNG_MAP_STATUS_OK, "Created map 1"); | |
372 | lttng_map_set_is_enabled(map1, true); | |
373 | ||
374 | map_status = lttng_map_create(map2_name, dimension_count, | |
375 | dimension_sizes, domain, buffer_type2, bitness, | |
376 | boundary_policy, coalesce_hits, &map2); | |
377 | ok(map_status == LTTNG_MAP_STATUS_OK, "Created map 2"); | |
378 | lttng_map_set_is_enabled(map2, true); | |
379 | ||
380 | map_list = lttng_map_list_create(); | |
381 | ok(map_list, "Map list created"); | |
382 | ||
383 | map_status = lttng_map_list_add(map_list, map1); | |
384 | ok(map_status == LTTNG_MAP_STATUS_OK, "Map 1 added to map list"); | |
385 | ||
386 | map_status = lttng_map_list_add(map_list, map2); | |
387 | ok(map_status == LTTNG_MAP_STATUS_OK, "Map 1 added to map list"); | |
388 | ||
389 | ret = lttng_map_list_serialize(map_list, &buffer); | |
390 | ok(ret == 0, "Map list serialized"); | |
391 | ||
392 | { | |
393 | struct lttng_payload_view view = | |
394 | lttng_payload_view_from_payload(&buffer, 0, -1); | |
395 | (void) lttng_map_list_create_from_payload( | |
396 | &view, &map_list_from_payload); | |
397 | } | |
398 | ||
399 | map_status = lttng_map_list_get_count(map_list, &map_count); | |
400 | ok(map_status == LTTNG_MAP_STATUS_OK, "Got map count from payload"); | |
401 | ok(map_count == 2, "Got the right map count from payload"); | |
402 | ||
403 | map1_from_payload = lttng_map_list_get_at_index(map_list, 0); | |
404 | ok(map1_from_payload, "Got first map from payload"); | |
405 | map_status = lttng_map_get_name(map1_from_payload, &map1_name_from_payload); | |
406 | ok(map_status == LTTNG_MAP_STATUS_OK, "Got map 1 name from payload"); | |
407 | ok(strcmp(map1_name_from_payload, map1_name) == 0, | |
408 | "Got right map 1 name from payload"); | |
409 | ok(lttng_map_get_is_enabled(map1_from_payload) == 1, | |
410 | "Got right map 1 enabled state from payload"); | |
411 | ||
412 | map2_from_payload = lttng_map_list_get_at_index(map_list, 1); | |
413 | ok(map2_from_payload, "Got first map from payload"); | |
414 | map_status = lttng_map_get_name(map2_from_payload, &map2_name_from_payload); | |
415 | ok(map_status == LTTNG_MAP_STATUS_OK, "Got map 2 name from payload"); | |
416 | ok(strcmp(map2_name_from_payload, map2_name) == 0, | |
417 | "Got right map 2 name from payload"); | |
418 | ok(lttng_map_get_is_enabled(map2_from_payload) == 1, | |
419 | "Got right map 2 enabled state from payload"); | |
420 | ||
421 | lttng_map_destroy(map1); | |
422 | lttng_map_destroy(map2); | |
423 | lttng_map_list_destroy(map_list); | |
424 | lttng_map_list_destroy(map_list_from_payload); | |
425 | lttng_payload_reset(&buffer); | |
426 | } | |
427 | ||
428 | int main(int argc, const char *argv[]) | |
429 | { | |
430 | plan_tests(NUM_TESTS); | |
431 | ||
432 | test_map(); | |
433 | test_map_list(); | |
434 | test_map_key_value_pair_serialize_deserialize(); | |
435 | test_map_key_value_pair_list_serialize_deserialize(); | |
436 | test_map_content_serialize_deserialize(); | |
437 | ||
438 | return exit_status(); | |
439 | } |