Tests: add basic ust context tests for $app, vpid, vuid, vgid
[lttng-tools.git] / tests / regression / tools / context / test_ust.py
1 #!/usr/bin/env python3
2 #
3 # Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 #
5 # SPDX-License-Identifier: GPL-2.0-only
6
7 from cgi import test
8 import pathlib
9 import sys
10 import os
11 from typing import Any, Callable, Type
12
13 """
14 Test the addition of various user space contexts.
15
16 This test successively sets up a session with a certain context enabled, traces
17 a test application, and then reads the resulting trace to determine if:
18 - the context field is present in the trace
19 - the context field has the expected value.
20
21 The vpid, vuid, vgid and java application contexts are validated by this test.
22 """
23
24 # Import in-tree test utils
25 test_utils_import_path = pathlib.Path(__file__).absolute().parents[3] / "utils"
26 sys.path.append(str(test_utils_import_path))
27
28 import lttngtest
29 import bt2
30
31
32 def context_trace_field_name(context_type: Type[lttngtest.ContextType]) -> str:
33 if isinstance(context_type, lttngtest.VpidContextType):
34 return "vpid"
35 elif isinstance(context_type, lttngtest.VuidContextType):
36 return "vuid"
37 elif isinstance(context_type, lttngtest.VgidContextType):
38 return "vgid"
39 elif isinstance(context_type, lttngtest.JavaApplicationContextType):
40 # Depends on the trace format and will need to be adapted for CTF 2.
41 return "_app_{retriever}_{name}".format(
42 retriever=context_type.retriever_name, name=context_type.field_name
43 )
44 else:
45 raise NotImplementedError
46
47
48 def trace_stream_class_has_context_field_in_event_context(
49 trace_location: pathlib.Path, context_field_name: str
50 ) -> bool:
51 iterator = bt2.TraceCollectionMessageIterator(str(trace_location))
52
53 # A bt2 message sequence is guaranteed to begin with a StreamBeginningMessage.
54 # Since we only have one channel (one stream class) and one trace, it is
55 # safe to use it to determine if the stream class contains the expected
56 # context field.
57 stream_begin_msg = next(iterator)
58
59 trace_class = stream_begin_msg.stream.trace.cls
60 # Ensure the trace class has only one stream class.
61 assert len(trace_class)
62
63 stream_class_id = next(iter(trace_class))
64 stream_class = trace_class[stream_class_id]
65 event_common_context_field_class = stream_class.event_common_context_field_class
66
67 return context_field_name in event_common_context_field_class
68
69
70 def trace_events_have_context_value(
71 trace_location: pathlib.Path, context_field_name: str, value: Any
72 ) -> bool:
73 for msg in bt2.TraceCollectionMessageIterator(str(trace_location)):
74 if type(msg) is not bt2._EventMessageConst:
75 continue
76
77 if msg.event.common_context_field[context_field_name] != value:
78 print(msg.event.common_context_field[context_field_name])
79 return False
80 return True
81
82
83 def test_static_context(
84 tap: lttngtest.TapGenerator,
85 test_env: lttngtest._Environment,
86 context_type: lttngtest.ContextType,
87 context_value_retriever: Callable[[lttngtest.WaitTraceTestApplication], Any],
88 ) -> None:
89 tap.diagnostic(
90 "Test presence and expected value of context `{context_name}`".format(
91 context_name=type(context_type).__name__
92 )
93 )
94
95 session_output_location = lttngtest.LocalSessionOutputLocation(
96 test_env.create_temporary_directory("trace")
97 )
98
99 client: lttngtest.Controller = lttngtest.LTTngClient(test_env, log=tap.diagnostic)
100
101 with tap.case("Create a session") as test_case:
102 session = client.create_session(output=session_output_location)
103 tap.diagnostic("Created session `{session_name}`".format(session_name=session.name))
104
105 with tap.case(
106 "Add a channel to session `{session_name}`".format(session_name=session.name)
107 ) as test_case:
108 channel = session.add_channel(lttngtest.TracingDomain.User)
109 tap.diagnostic("Created channel `{channel_name}`".format(channel_name=channel.name))
110
111 with tap.case(
112 "Add {context_type} context to channel `{channel_name}`".format(
113 context_type=type(context_type).__name__, channel_name=channel.name
114 )
115 ) as test_case:
116 channel.add_context(context_type)
117
118 test_app = test_env.launch_wait_trace_test_application(50)
119
120 # Only track the test application
121 session.user_vpid_process_attribute_tracker.track(test_app.vpid)
122 expected_context_value = context_value_retriever(test_app)
123
124 # Enable all user space events, the default for a user tracepoint event rule.
125 channel.add_recording_rule(lttngtest.UserTracepointEventRule())
126
127 session.start()
128 test_app.trace()
129 test_app.wait_for_exit()
130 session.stop()
131 session.destroy()
132
133 tap.test(
134 trace_stream_class_has_context_field_in_event_context(
135 session_output_location.path, context_trace_field_name(context_type)
136 ),
137 "Stream class contains field `{context_field_name}`".format(
138 context_field_name=context_trace_field_name(context_type)
139 ),
140 )
141
142 tap.test(
143 trace_events_have_context_value(
144 session_output_location.path,
145 context_trace_field_name(context_type),
146 expected_context_value,
147 ),
148 "Trace's events contain the expected `{context_field_name}` value `{expected_context_value}`".format(
149 context_field_name=context_trace_field_name(context_type),
150 expected_context_value=expected_context_value,
151 ),
152 )
153
154
155 tap = lttngtest.TapGenerator(20)
156 tap.diagnostic("Test user space context tracing")
157
158 with lttngtest.test_environment(with_sessiond=True, log=tap.diagnostic) as test_env:
159 test_static_context(
160 tap, test_env, lttngtest.VpidContextType(), lambda test_app: test_app.vpid
161 )
162 test_static_context(
163 tap, test_env, lttngtest.VuidContextType(), lambda test_app: os.getuid()
164 )
165 test_static_context(
166 tap, test_env, lttngtest.VgidContextType(), lambda test_app: os.getgid()
167 )
168 test_static_context(
169 tap,
170 test_env,
171 lttngtest.JavaApplicationContextType("mayo", "ketchup"),
172 lambda test_app: {},
173 )
174
175 sys.exit(0 if tap.is_successful else 1)
This page took 0.040585 seconds and 4 git commands to generate.