Tests: python: use quoted annotations to support python <= 3.6
[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):
33 # type: (Type[lttngtest.ContextType]) -> str
34 if isinstance(context_type, lttngtest.VpidContextType):
35 return "vpid"
36 elif isinstance(context_type, lttngtest.VuidContextType):
37 return "vuid"
38 elif isinstance(context_type, lttngtest.VgidContextType):
39 return "vgid"
40 elif isinstance(context_type, lttngtest.JavaApplicationContextType):
41 # Depends on the trace format and will need to be adapted for CTF 2.
42 return "_app_{retriever}_{name}".format(
43 retriever=context_type.retriever_name, name=context_type.field_name
44 )
45 else:
46 raise NotImplementedError
47
48
49 def trace_stream_class_has_context_field_in_event_context(
50 trace_location, context_field_name
51 ):
52 # type: (pathlib.Path, str) -> bool
53 iterator = bt2.TraceCollectionMessageIterator(str(trace_location))
54
55 # A bt2 message sequence is guaranteed to begin with a StreamBeginningMessage.
56 # Since we only have one channel (one stream class) and one trace, it is
57 # safe to use it to determine if the stream class contains the expected
58 # context field.
59 stream_begin_msg = next(iterator)
60
61 trace_class = stream_begin_msg.stream.trace.cls
62 # Ensure the trace class has only one stream class.
63 assert len(trace_class)
64
65 stream_class_id = next(iter(trace_class))
66 stream_class = trace_class[stream_class_id]
67 event_common_context_field_class = stream_class.event_common_context_field_class
68
69 return context_field_name in event_common_context_field_class
70
71
72 def trace_events_have_context_value(trace_location, context_field_name, value):
73 # type: (pathlib.Path, str, Any) -> bool
74 for msg in bt2.TraceCollectionMessageIterator(str(trace_location)):
75 if type(msg) is not bt2._EventMessageConst:
76 continue
77
78 if msg.event.common_context_field[context_field_name] != value:
79 print(msg.event.common_context_field[context_field_name])
80 return False
81 return True
82
83
84 def test_static_context(tap, test_env, context_type, context_value_retriever):
85 # type: (lttngtest.TapGenerator, lttngtest._Environment, lttngtest.ContextType, Callable[[lttngtest.WaitTraceTestApplication], Any]) -> None
86 tap.diagnostic(
87 "Test presence and expected value of context `{context_name}`".format(
88 context_name=type(context_type).__name__
89 )
90 )
91
92 session_output_location = lttngtest.LocalSessionOutputLocation(
93 test_env.create_temporary_directory("trace")
94 )
95
96 client = lttngtest.LTTngClient(test_env, log=tap.diagnostic)
97
98 with tap.case("Create a session") as test_case:
99 session = client.create_session(output=session_output_location)
100 tap.diagnostic("Created session `{session_name}`".format(session_name=session.name))
101
102 with tap.case(
103 "Add a channel to session `{session_name}`".format(session_name=session.name)
104 ) as test_case:
105 channel = session.add_channel(lttngtest.TracingDomain.User)
106 tap.diagnostic("Created channel `{channel_name}`".format(channel_name=channel.name))
107
108 with tap.case(
109 "Add {context_type} context to channel `{channel_name}`".format(
110 context_type=type(context_type).__name__, channel_name=channel.name
111 )
112 ) as test_case:
113 channel.add_context(context_type)
114
115 test_app = test_env.launch_wait_trace_test_application(50)
116
117 # Only track the test application
118 session.user_vpid_process_attribute_tracker.track(test_app.vpid)
119 expected_context_value = context_value_retriever(test_app)
120
121 # Enable all user space events, the default for a user tracepoint event rule.
122 channel.add_recording_rule(lttngtest.UserTracepointEventRule())
123
124 session.start()
125 test_app.trace()
126 test_app.wait_for_exit()
127 session.stop()
128 session.destroy()
129
130 tap.test(
131 trace_stream_class_has_context_field_in_event_context(
132 session_output_location.path, context_trace_field_name(context_type)
133 ),
134 "Stream class contains field `{context_field_name}`".format(
135 context_field_name=context_trace_field_name(context_type)
136 ),
137 )
138
139 tap.test(
140 trace_events_have_context_value(
141 session_output_location.path,
142 context_trace_field_name(context_type),
143 expected_context_value,
144 ),
145 "Trace's events contain the expected `{context_field_name}` value `{expected_context_value}`".format(
146 context_field_name=context_trace_field_name(context_type),
147 expected_context_value=expected_context_value,
148 ),
149 )
150
151
152 tap = lttngtest.TapGenerator(20)
153 tap.diagnostic("Test user space context tracing")
154
155 with lttngtest.test_environment(with_sessiond=True, log=tap.diagnostic) as test_env:
156 test_static_context(
157 tap, test_env, lttngtest.VpidContextType(), lambda test_app: test_app.vpid
158 )
159 test_static_context(
160 tap, test_env, lttngtest.VuidContextType(), lambda test_app: os.getuid()
161 )
162 test_static_context(
163 tap, test_env, lttngtest.VgidContextType(), lambda test_app: os.getgid()
164 )
165 test_static_context(
166 tap,
167 test_env,
168 lttngtest.JavaApplicationContextType("mayo", "ketchup"),
169 lambda test_app: {},
170 )
171
172 sys.exit(0 if tap.is_successful else 1)
This page took 0.033068 seconds and 4 git commands to generate.