3 # Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 # SPDX-License-Identifier: GPL-2.0-only
10 from typing
import Any
, Callable
, Type
13 Test the addition of various user space contexts.
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.
20 The vpid, vuid, vgid and java application contexts are validated by this test.
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
))
31 def context_trace_field_name(context_type
):
32 # type: (Type[lttngtest.ContextType]) -> str
33 if isinstance(context_type
, lttngtest
.VpidContextType
):
35 elif isinstance(context_type
, lttngtest
.VuidContextType
):
37 elif isinstance(context_type
, lttngtest
.VgidContextType
):
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
45 raise NotImplementedError
48 def trace_stream_class_has_context_field_in_event_context(
49 trace_location
, context_field_name
51 # type: (pathlib.Path, str) -> bool
52 iterator
= bt2
.TraceCollectionMessageIterator(str(trace_location
))
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
58 stream_begin_msg
= next(iterator
)
60 trace_class
= stream_begin_msg
.stream
.trace
.cls
61 # Ensure the trace class has only one stream class.
62 assert len(trace_class
)
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
68 return context_field_name
in event_common_context_field_class
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
:
77 if msg
.event
.common_context_field
[context_field_name
] != value
:
78 print(msg
.event
.common_context_field
[context_field_name
])
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
86 "Test presence and expected value of context `{context_name}`".format(
87 context_name
=type(context_type
).__name
__
91 session_output_location
= lttngtest
.LocalSessionOutputLocation(
92 test_env
.create_temporary_directory("trace")
95 client
= lttngtest
.LTTngClient(test_env
, log
=tap
.diagnostic
)
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
))
102 "Add a channel to session `{session_name}`".format(session_name
=session
.name
)
104 channel
= session
.add_channel(lttngtest
.TracingDomain
.User
)
105 tap
.diagnostic("Created channel `{channel_name}`".format(channel_name
=channel
.name
))
108 "Add {context_type} context to channel `{channel_name}`".format(
109 context_type
=type(context_type
).__name
__, channel_name
=channel
.name
112 channel
.add_context(context_type
)
114 test_app
= test_env
.launch_wait_trace_test_application(50)
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
)
120 # Enable all user space events, the default for a user tracepoint event rule.
121 channel
.add_recording_rule(lttngtest
.UserTracepointEventRule())
125 test_app
.wait_for_exit()
130 trace_stream_class_has_context_field_in_event_context(
131 session_output_location
.path
, context_trace_field_name(context_type
)
133 "Stream class contains field `{context_field_name}`".format(
134 context_field_name
=context_trace_field_name(context_type
)
139 trace_events_have_context_value(
140 session_output_location
.path
,
141 context_trace_field_name(context_type
),
142 expected_context_value
,
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
,
151 tap
= lttngtest
.TapGenerator(20)
152 tap
.diagnostic("Test user space context tracing")
154 with lttngtest
.test_environment(with_sessiond
=True, log
=tap
.diagnostic
) as test_env
:
156 tap
, test_env
, lttngtest
.VpidContextType(), lambda test_app
: test_app
.vpid
159 tap
, test_env
, lttngtest
.VuidContextType(), lambda test_app
: os
.getuid()
162 tap
, test_env
, lttngtest
.VgidContextType(), lambda test_app
: os
.getgid()
167 lttngtest
.JavaApplicationContextType("mayo", "ketchup"),
171 sys
.exit(0 if tap
.is_successful
else 1)