tests: Handle test failures for ust-constructors with heap allocation
[lttng-tools.git] / tests / regression / ust / ust-constructor / test_ust_constructor.py
CommitLineData
da1e97c9
MD
1#!/usr/bin/env python3
2#
3# Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4# Copyright (C) 2023 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5#
6# SPDX-License-Identifier: GPL-2.0-only
7
da1e97c9
MD
8import pathlib
9import sys
10import os
b8e79f3f 11import subprocess
da1e97c9
MD
12from typing import Any, Callable, Type
13
14"""
15Test instrumentation coverage of C/C++ constructors and destructors by LTTng-UST
16tracepoints.
17
18This test successively sets up a session, traces a test application, and then
19reads the resulting trace to determine if all the expected events are present.
20"""
21
22# Import in-tree test utils
23test_utils_import_path = pathlib.Path(__file__).absolute().parents[3] / "utils"
24sys.path.append(str(test_utils_import_path))
25
26import lttngtest
27import bt2
28
b8e79f3f
KS
29# Determine if LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP is set. This will
30# affect if certain events may or may not be expected when compiling with
31# C++.
32# @see https://github.com/lttng/lttng-ust/blob/47fa3e4ed7ab43e034dc61fc1480f919f4ee51d0/include/lttng/ust-compiler.h#L51
33#
34compound_literal_on_heap = False
35process = subprocess.Popen(
36 [
37 os.path.join(
38 str(test_utils_import_path),
39 "testapp",
40 "gen-ust-events-constructor",
41 "uses_heap",
42 )
43 ]
44)
45process.wait()
46if process.returncode == 0:
47 compound_literal_on_heap = True
48
da1e97c9
MD
49expected_events = [
50 {"name": "tp_so:constructor_c_provider_shared_library", "msg": None, "count": 0},
b8e79f3f
KS
51 {
52 "name": "tp_a:constructor_c_provider_static_archive",
53 "msg": None,
54 "count": 0,
55 "may_fail": compound_literal_on_heap,
56 },
da1e97c9
MD
57 {
58 "name": "tp_so:constructor_cplusplus_provider_shared_library",
59 "msg": "global - shared library define and provider",
60 "count": 0,
61 },
62 {
63 "name": "tp_a:constructor_cplusplus_provider_static_archive",
64 "msg": "global - static archive define and provider",
65 "count": 0,
b8e79f3f
KS
66 "may_fail": compound_literal_on_heap,
67 },
68 {
69 "name": "tp:constructor_c_across_units_before_define",
70 "msg": None,
71 "count": 0,
72 "may_fail": compound_literal_on_heap,
da1e97c9 73 },
da1e97c9
MD
74 {
75 "name": "tp:constructor_cplusplus",
76 "msg": "global - across units before define",
77 "count": 0,
b8e79f3f
KS
78 "may_fail": compound_literal_on_heap,
79 },
80 {
81 "name": "tp:constructor_c_same_unit_before_define",
82 "msg": None,
83 "count": 0,
84 "may_fail": compound_literal_on_heap,
85 },
86 {
87 "name": "tp:constructor_c_same_unit_after_define",
88 "msg": None,
89 "count": 0,
90 "may_fail": compound_literal_on_heap,
da1e97c9 91 },
da1e97c9
MD
92 {
93 "name": "tp:constructor_cplusplus",
94 "msg": "global - same unit before define",
95 "count": 0,
b8e79f3f 96 "may_fail": compound_literal_on_heap,
da1e97c9
MD
97 },
98 {
99 "name": "tp:constructor_cplusplus",
100 "msg": "global - same unit after define",
101 "count": 0,
b8e79f3f
KS
102 "may_fail": compound_literal_on_heap,
103 },
104 {
105 "name": "tp:constructor_c_across_units_after_define",
106 "msg": None,
107 "count": 0,
108 "may_fail": compound_literal_on_heap,
da1e97c9 109 },
da1e97c9
MD
110 {
111 "name": "tp:constructor_cplusplus",
112 "msg": "global - across units after define",
113 "count": 0,
b8e79f3f
KS
114 "may_fail": compound_literal_on_heap,
115 },
116 {
117 "name": "tp:constructor_c_same_unit_before_provider",
118 "msg": None,
119 "count": 0,
120 "may_fail": compound_literal_on_heap,
121 },
122 {
123 "name": "tp:constructor_c_same_unit_after_provider",
124 "msg": None,
125 "count": 0,
126 "may_fail": compound_literal_on_heap,
da1e97c9 127 },
da1e97c9
MD
128 {
129 "name": "tp:constructor_cplusplus",
130 "msg": "global - same unit before provider",
131 "count": 0,
b8e79f3f 132 "may_fail": compound_literal_on_heap,
da1e97c9
MD
133 },
134 {
135 "name": "tp:constructor_cplusplus",
136 "msg": "global - same unit after provider",
137 "count": 0,
138 },
139 {"name": "tp:constructor_c_across_units_after_provider", "msg": None, "count": 0},
140 {
141 "name": "tp:constructor_cplusplus",
142 "msg": "global - across units after provider",
143 "count": 0,
144 },
145 {"name": "tp:constructor_cplusplus", "msg": "main() local", "count": 0},
146 {
147 "name": "tp_so:constructor_cplusplus_provider_shared_library",
148 "msg": "main() local - shared library define and provider",
149 "count": 0,
150 },
151 {
152 "name": "tp_a:constructor_cplusplus_provider_static_archive",
153 "msg": "main() local - static archive define and provider",
154 "count": 0,
155 },
156 {"name": "tp:main", "msg": None, "count": 0},
157 {
158 "name": "tp_a:destructor_cplusplus_provider_static_archive",
159 "msg": "main() local - static archive define and provider",
160 "count": 0,
161 },
162 {
163 "name": "tp_so:destructor_cplusplus_provider_shared_library",
164 "msg": "main() local - shared library define and provider",
165 "count": 0,
166 },
167 {"name": "tp:destructor_cplusplus", "msg": "main() local", "count": 0},
168 {
169 "name": "tp:destructor_cplusplus",
170 "msg": "global - across units after provider",
171 "count": 0,
172 },
173 {
174 "name": "tp:destructor_cplusplus",
175 "msg": "global - same unit after provider",
176 "count": 0,
177 },
178 {
179 "name": "tp:destructor_cplusplus",
180 "msg": "global - same unit before provider",
181 "count": 0,
b8e79f3f 182 "may_fail": compound_literal_on_heap,
da1e97c9
MD
183 },
184 {
185 "name": "tp:destructor_cplusplus",
186 "msg": "global - across units after define",
187 "count": 0,
b8e79f3f 188 "may_fail": compound_literal_on_heap,
da1e97c9
MD
189 },
190 {
191 "name": "tp:destructor_cplusplus",
192 "msg": "global - same unit after define",
193 "count": 0,
b8e79f3f 194 "may_fail": compound_literal_on_heap,
da1e97c9
MD
195 },
196 {
197 "name": "tp:destructor_cplusplus",
198 "msg": "global - same unit before define",
199 "count": 0,
b8e79f3f 200 "may_fail": compound_literal_on_heap,
da1e97c9
MD
201 },
202 {
203 "name": "tp:destructor_cplusplus",
204 "msg": "global - across units before define",
205 "count": 0,
b8e79f3f 206 "may_fail": compound_literal_on_heap,
da1e97c9
MD
207 },
208 {
209 "name": "tp_a:destructor_cplusplus_provider_static_archive",
210 "msg": "global - static archive define and provider",
211 "count": 0,
b8e79f3f 212 "may_fail": compound_literal_on_heap,
da1e97c9
MD
213 },
214 {
215 "name": "tp_so:destructor_cplusplus_provider_shared_library",
216 "msg": "global - shared library define and provider",
217 "count": 0,
218 },
b8e79f3f
KS
219 {
220 "name": "tp:destructor_c_across_units_after_provider",
221 "msg": None,
222 "count": 0,
223 "may_fail": compound_literal_on_heap,
224 },
225 {
226 "name": "tp:destructor_c_same_unit_after_provider",
227 "msg": None,
228 "count": 0,
229 "may_fail": compound_literal_on_heap,
230 },
231 {
232 "name": "tp:destructor_c_same_unit_before_provider",
233 "msg": None,
234 "count": 0,
235 "may_fail": compound_literal_on_heap,
236 },
237 {
238 "name": "tp:destructor_c_across_units_after_define",
239 "msg": None,
240 "count": 0,
241 "may_fail": compound_literal_on_heap,
242 },
243 {
244 "name": "tp:destructor_c_same_unit_after_define",
245 "msg": None,
246 "count": 0,
247 "may_fail": compound_literal_on_heap,
248 },
249 {
250 "name": "tp:destructor_c_same_unit_before_define",
251 "msg": None,
252 "count": 0,
253 "may_fail": compound_literal_on_heap,
254 },
255 {
256 "name": "tp:destructor_c_across_units_before_define",
257 "msg": None,
258 "count": 0,
259 "may_fail": compound_literal_on_heap,
260 },
261 {
262 "name": "tp_a:destructor_c_provider_static_archive",
263 "msg": None,
264 "count": 0,
265 "may_fail": compound_literal_on_heap,
266 },
da1e97c9
MD
267 {"name": "tp_so:destructor_c_provider_shared_library", "msg": None, "count": 0},
268]
269
d096be91
MJ
270num_tests = 7 + len(expected_events)
271
da1e97c9 272
d2455527
JG
273def capture_trace(tap, test_env):
274 # type: (lttngtest.TapGenerator, lttngtest._Environment) -> lttngtest.LocalSessionOutputLocation
da1e97c9
MD
275 tap.diagnostic(
276 "Capture trace from application with instrumented C/C++ constructors/destructors"
277 )
278
279 session_output_location = lttngtest.LocalSessionOutputLocation(
280 test_env.create_temporary_directory("trace")
281 )
282
aae4cdd1 283 client = lttngtest.LTTngClient(test_env, log=tap.diagnostic)
da1e97c9
MD
284
285 with tap.case("Create a session") as test_case:
286 session = client.create_session(output=session_output_location)
287 tap.diagnostic("Created session `{session_name}`".format(session_name=session.name))
288
289 with tap.case(
290 "Add a channel to session `{session_name}`".format(session_name=session.name)
291 ) as test_case:
292 channel = session.add_channel(lttngtest.TracingDomain.User)
293 tap.diagnostic("Created channel `{channel_name}`".format(channel_name=channel.name))
294
295 # Enable all user space events, the default for a user tracepoint event rule.
296 channel.add_recording_rule(lttngtest.UserTracepointEventRule("tp*"))
297
d096be91
MJ
298 with tap.case(
299 "Start session `{session_name}`".format(session_name=session.name)
300 ) as test_case:
301 session.start()
302
da1e97c9 303 test_app = test_env.launch_trace_test_constructor_application()
d096be91
MJ
304 with tap.case("Run test app".format(session_name=session.name)) as test_case:
305 test_app.wait_for_exit()
306
307 with tap.case(
308 "Stop session `{session_name}`".format(session_name=session.name)
309 ) as test_case:
310 session.stop()
311
312 with tap.case(
313 "Destroy session `{session_name}`".format(session_name=session.name)
314 ) as test_case:
315 session.destroy()
316
da1e97c9
MD
317 return session_output_location
318
319
873d3601 320def validate_trace(trace_location, tap):
d096be91 321 # type: (pathlib.Path, lttngtest.TapGenerator)
da1e97c9
MD
322 unknown_event_count = 0
323
324 for msg in bt2.TraceCollectionMessageIterator(str(trace_location)):
325 if type(msg) is not bt2._EventMessageConst:
326 continue
327
328 found = False
329 for event in expected_events:
330 if event["name"] == msg.event.name and event["msg"] is None:
331 found = True
332 event["count"] = event["count"] + 1
333 break
334 elif (
335 event["name"] == msg.event.name
336 and event["msg"] is not None
337 and event["msg"] == msg.event["msg"]
338 ):
339 found = True
340 event["count"] = event["count"] + 1
341 break
d096be91 342
da1e97c9
MD
343 if found == False:
344 unknown_event_count = unknown_event_count + 1
345 printmsg = None
346 if "msg" in msg.event:
347 printmsg = msg.event["msg"]
348 tap.diagnostic(
349 'Unexpected event name="{}" msg="{}" encountered'.format(
350 msg.event.name, str(printmsg)
351 )
352 )
353
354 for event in expected_events:
b8e79f3f
KS
355 may_fail = "may_fail" in event.keys() and event["may_fail"]
356 if not may_fail:
357 tap.test(
358 event["count"] == 1,
359 'Found expected event name="{}" msg="{}"'.format(
360 event["name"], str(event["msg"])
361 ),
d096be91 362 ),
b8e79f3f
KS
363 else:
364 tap.skip("Event '{}' may or may not be recorded".format(event["name"]))
d096be91
MJ
365
366 tap.test(unknown_event_count == 0, "Found no unexpected events")
da1e97c9
MD
367
368
369tap = lttngtest.TapGenerator(num_tests)
370tap.diagnostic("Test user space constructor/destructor instrumentation coverage")
371
372with lttngtest.test_environment(with_sessiond=True, log=tap.diagnostic) as test_env:
373 outputlocation = capture_trace(tap, test_env)
d096be91 374 validate_trace(outputlocation.path, tap)
da1e97c9
MD
375
376sys.exit(0 if tap.is_successful else 1)
This page took 0.044098 seconds and 4 git commands to generate.