3 # Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 # SPDX-License-Identifier: GPL-2.0-only
11 from typing
import Any
, Callable
, Type
14 Test the addition of various user space contexts.
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.
21 The vpid, vuid, vgid and java application contexts are validated by this test.
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
))
32 def context_trace_field_name(context_type
):
33 # type: (Type[lttngtest.ContextType]) -> str
34 if isinstance(context_type
, lttngtest
.VpidContextType
):
36 elif isinstance(context_type
, lttngtest
.VuidContextType
):
38 elif isinstance(context_type
, lttngtest
.VgidContextType
):
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
46 raise NotImplementedError
49 def trace_stream_class_has_context_field_in_event_context(
50 trace_location
, context_field_name
52 # type: (pathlib.Path, str) -> bool
53 iterator
= bt2
.TraceCollectionMessageIterator(str(trace_location
))
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
59 stream_begin_msg
= next(iterator
)
61 trace_class
= stream_begin_msg
.stream
.trace
.cls
62 # Ensure the trace class has only one stream class.
63 assert len(trace_class
)
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
69 return context_field_name
in event_common_context_field_class
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
:
78 if msg
.event
.common_context_field
[context_field_name
] != value
:
79 print(msg
.event
.common_context_field
[context_field_name
])
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
87 "Test presence and expected value of context `{context_name}`".format(
88 context_name
=type(context_type
).__name
__
92 session_output_location
= lttngtest
.LocalSessionOutputLocation(
93 test_env
.create_temporary_directory("trace")
96 client
= lttngtest
.LTTngClient(test_env
, log
=tap
.diagnostic
)
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
))
103 "Add a channel to session `{session_name}`".format(session_name
=session
.name
)
105 channel
= session
.add_channel(lttngtest
.TracingDomain
.User
)
106 tap
.diagnostic("Created channel `{channel_name}`".format(channel_name
=channel
.name
))
109 "Add {context_type} context to channel `{channel_name}`".format(
110 context_type
=type(context_type
).__name
__, channel_name
=channel
.name
113 channel
.add_context(context_type
)
115 test_app
= test_env
.launch_wait_trace_test_application(50)
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
)
121 # Enable all user space events, the default for a user tracepoint event rule.
122 channel
.add_recording_rule(lttngtest
.UserTracepointEventRule())
126 test_app
.wait_for_exit()
131 trace_stream_class_has_context_field_in_event_context(
132 session_output_location
.path
, context_trace_field_name(context_type
)
134 "Stream class contains field `{context_field_name}`".format(
135 context_field_name
=context_trace_field_name(context_type
)
140 trace_events_have_context_value(
141 session_output_location
.path
,
142 context_trace_field_name(context_type
),
143 expected_context_value
,
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
,
152 tap
= lttngtest
.TapGenerator(20)
153 tap
.diagnostic("Test user space context tracing")
155 with lttngtest
.test_environment(with_sessiond
=True, log
=tap
.diagnostic
) as test_env
:
157 tap
, test_env
, lttngtest
.VpidContextType(), lambda test_app
: test_app
.vpid
160 tap
, test_env
, lttngtest
.VuidContextType(), lambda test_app
: os
.getuid()
163 tap
, test_env
, lttngtest
.VgidContextType(), lambda test_app
: os
.getgid()
168 lttngtest
.JavaApplicationContextType("mayo", "ketchup"),
172 sys
.exit(0 if tap
.is_successful
else 1)