Tests: Fix: Use '.logfile' instead of '.log' for test app output
[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 import pathlib
8 import sys
9 import os
10 from typing import Any, Callable, Type
11
12 """
13 Test the addition of various user space contexts.
14
15 This test successively sets up a session with a certain context enabled, traces
16 a test application, and then reads the resulting trace to determine if:
17 - the context field is present in the trace
18 - the context field has the expected value.
19
20 The vpid, vuid, vgid and java application contexts are validated by this test.
21 """
22
23 # Import in-tree test utils
24 test_utils_import_path = pathlib.Path(__file__).absolute().parents[3] / "utils"
25 sys.path.append(str(test_utils_import_path))
26
27 import lttngtest
28 import bt2
29
30
31 def context_trace_field_name(context_type):
32 # 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, context_field_name
50 ):
51 # type: (pathlib.Path, str) -> bool
52 iterator = bt2.TraceCollectionMessageIterator(str(trace_location))
53
54 # A bt2 message sequence is guaranteed to begin with a StreamBeginningMessage.
55 # Since we only have one channel (one stream class) and one trace, it is
56 # safe to use it to determine if the stream class contains the expected
57 # context field.
58 stream_begin_msg = next(iterator)
59
60 trace_class = stream_begin_msg.stream.trace.cls
61 # Ensure the trace class has only one stream class.
62 assert len(trace_class)
63
64 stream_class_id = next(iter(trace_class))
65 stream_class = trace_class[stream_class_id]
66 event_common_context_field_class = stream_class.event_common_context_field_class
67
68 return context_field_name in event_common_context_field_class
69
70
71 def trace_events_have_context_value(trace_location, context_field_name, value):
72 # type: (pathlib.Path, str, Any) -> 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(tap, test_env, context_type, context_value_retriever):
84 # type: (lttngtest.TapGenerator, lttngtest._Environment, lttngtest.ContextType, Callable[[lttngtest.WaitTraceTestApplication], Any]) -> None
85 tap.diagnostic(
86 "Test presence and expected value of context `{context_name}`".format(
87 context_name=type(context_type).__name__
88 )
89 )
90
91 session_output_location = lttngtest.LocalSessionOutputLocation(
92 test_env.create_temporary_directory("trace")
93 )
94
95 client = lttngtest.LTTngClient(test_env, log=tap.diagnostic)
96
97 with tap.case("Create a session") as test_case:
98 session = client.create_session(output=session_output_location)
99 tap.diagnostic("Created session `{session_name}`".format(session_name=session.name))
100
101 with tap.case(
102 "Add a channel to session `{session_name}`".format(session_name=session.name)
103 ) as test_case:
104 channel = session.add_channel(lttngtest.TracingDomain.User)
105 tap.diagnostic("Created channel `{channel_name}`".format(channel_name=channel.name))
106
107 with tap.case(
108 "Add {context_type} context to channel `{channel_name}`".format(
109 context_type=type(context_type).__name__, channel_name=channel.name
110 )
111 ) as test_case:
112 channel.add_context(context_type)
113
114 test_app = test_env.launch_wait_trace_test_application(50)
115
116 # Only track the test application
117 session.user_vpid_process_attribute_tracker.track(test_app.vpid)
118 expected_context_value = context_value_retriever(test_app)
119
120 # Enable all user space events, the default for a user tracepoint event rule.
121 channel.add_recording_rule(lttngtest.UserTracepointEventRule())
122
123 session.start()
124 test_app.trace()
125 test_app.wait_for_exit()
126 session.stop()
127 session.destroy()
128
129 tap.test(
130 trace_stream_class_has_context_field_in_event_context(
131 session_output_location.path, context_trace_field_name(context_type)
132 ),
133 "Stream class contains field `{context_field_name}`".format(
134 context_field_name=context_trace_field_name(context_type)
135 ),
136 )
137
138 tap.test(
139 trace_events_have_context_value(
140 session_output_location.path,
141 context_trace_field_name(context_type),
142 expected_context_value,
143 ),
144 "Trace's events contain the expected `{context_field_name}` value `{expected_context_value}`".format(
145 context_field_name=context_trace_field_name(context_type),
146 expected_context_value=expected_context_value,
147 ),
148 )
149
150
151 tap = lttngtest.TapGenerator(20)
152 tap.diagnostic("Test user space context tracing")
153
154 with lttngtest.test_environment(with_sessiond=True, log=tap.diagnostic) as test_env:
155 test_static_context(
156 tap, test_env, lttngtest.VpidContextType(), lambda test_app: test_app.vpid
157 )
158 test_static_context(
159 tap, test_env, lttngtest.VuidContextType(), lambda test_app: os.getuid()
160 )
161 test_static_context(
162 tap, test_env, lttngtest.VgidContextType(), lambda test_app: os.getgid()
163 )
164 test_static_context(
165 tap,
166 test_env,
167 lttngtest.JavaApplicationContextType("mayo", "ketchup"),
168 lambda test_app: {},
169 )
170
171 sys.exit(0 if tap.is_successful else 1)
This page took 0.065684 seconds and 5 git commands to generate.