1 # SPDX-License-Identifier: GPL-2.0-only
3 # Copyright (C) 2019 EfficiOS Inc.
10 # Run callable `func` in the context of a component's __init__ method. The
11 # callable is passed the Component being instantiated.
13 # The value returned by the callable is returned by run_in_component_init.
14 def run_in_component_init(func
):
15 class MySink(bt2
._UserSinkComponent
):
16 def __init__(self
, config
, params
, obj
):
18 res_bound
= func(self
)
20 def _user_consume(self
):
25 g
.add_component(MySink
, 'comp')
27 # We deliberately use a different variable for returning the result than
28 # the variable bound to the MySink.__init__ context and delete res_bound.
29 # The MySink.__init__ context stays alive until the end of the program, so
30 # if res_bound were to still point to our result, it would contribute an
31 # unexpected reference to the refcount of the result, from the point of view
32 # of the user of this function. It would then affect destruction tests,
33 # for example, which want to test what happens when the refcount of a Python
41 # Create an empty trace class with default values.
42 def get_default_trace_class():
44 return comp_self
._create
_trace
_class
()
46 return run_in_component_init(f
)
49 # Create a pair of list, one containing non-const messages and the other
50 # containing const messages
51 def _get_all_message_types(with_packet
=True):
54 class MyIter(bt2
._UserMessageIterator
):
55 def __init__(self
, config
, self_output_port
):
60 self
._create
_stream
_beginning
_message
(
61 self_output_port
.user_data
['stream']
66 assert self_output_port
.user_data
['packet']
68 self
._create
_packet
_beginning
_message
(
69 self_output_port
.user_data
['packet']
73 default_clock_snapshot
= 789
76 assert self_output_port
.user_data
['packet']
77 ev_parent
= self_output_port
.user_data
['packet']
79 assert self_output_port
.user_data
['stream']
80 ev_parent
= self_output_port
.user_data
['stream']
82 msg
= self
._create
_event
_message
(
83 self_output_port
.user_data
['event_class'],
85 default_clock_snapshot
,
88 msg
.event
.payload_field
['giraffe'] = 1
89 msg
.event
.specific_context_field
['ant'] = -1
90 msg
.event
.common_context_field
['cpu_id'] = 1
91 self
._msgs
.append(msg
)
95 self
._create
_packet
_end
_message
(
96 self_output_port
.user_data
['packet']
101 self
._create
_stream
_end
_message
(self_output_port
.user_data
['stream'])
107 if self
._at
== len(self
._msgs
):
110 msg
= self
._msgs
[self
._at
]
114 class MySrc(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
115 def __init__(self
, config
, params
, obj
):
116 tc
= self
._create
_trace
_class
()
117 clock_class
= self
._create
_clock
_class
(frequency
=1000)
119 # event common context (stream-class-defined)
120 cc
= tc
.create_structure_field_class()
121 cc
+= [('cpu_id', tc
.create_signed_integer_field_class(8))]
123 # packet context (stream-class-defined)
127 pc
= tc
.create_structure_field_class()
128 pc
+= [('something', tc
.create_unsigned_integer_field_class(8))]
130 stream_class
= tc
.create_stream_class(
131 default_clock_class
=clock_class
,
132 event_common_context_field_class
=cc
,
133 packet_context_field_class
=pc
,
134 supports_packets
=with_packet
,
137 # specific context (event-class-defined)
138 sc
= tc
.create_structure_field_class()
139 sc
+= [('ant', tc
.create_signed_integer_field_class(16))]
142 ep
= tc
.create_structure_field_class()
143 ep
+= [('giraffe', tc
.create_signed_integer_field_class(32))]
145 event_class
= stream_class
.create_event_class(
146 name
='garou', specific_context_field_class
=sc
, payload_field_class
=ep
149 trace
= tc(environment
={'patate': 12})
150 stream
= trace
.create_stream(stream_class
, user_attributes
={'salut': 23})
153 packet
= stream
.create_packet()
154 packet
.context_field
['something'] = 154
158 self
._add
_output
_port
(
163 'event_class': event_class
,
170 _src_comp
= _graph
.add_component(MySrc
, 'my_source')
171 _msg_iter
= TestOutputPortMessageIterator(_graph
, _src_comp
.output_ports
['out'])
173 const_msgs
= list(_msg_iter
)
175 return _msgs
, const_msgs
178 def get_stream_beginning_message():
179 msgs
, _
= _get_all_message_types()
181 if type(m
) is bt2
._StreamBeginningMessage
:
185 def get_const_stream_beginning_message():
186 _
, const_msgs
= _get_all_message_types()
188 if type(m
) is bt2
._StreamBeginningMessageConst
:
192 def get_stream_end_message():
193 msgs
, _
= _get_all_message_types()
195 if type(m
) is bt2
._StreamEndMessage
:
199 def get_packet_beginning_message():
200 msgs
, _
= _get_all_message_types(with_packet
=True)
202 if type(m
) is bt2
._PacketBeginningMessage
:
206 def get_const_packet_beginning_message():
207 _
, const_msgs
= _get_all_message_types(with_packet
=True)
209 if type(m
) is bt2
._PacketBeginningMessageConst
:
213 def get_packet_end_message():
214 msgs
, _
= _get_all_message_types(with_packet
=True)
216 if type(m
) is bt2
._PacketEndMessage
:
220 def get_event_message():
221 msgs
, _
= _get_all_message_types()
223 if type(m
) is bt2
._EventMessage
:
227 def get_const_event_message():
228 _
, const_msgs
= _get_all_message_types()
230 if type(m
) is bt2
._EventMessageConst
:
234 # Proxy sink component class.
236 # This sink accepts a list of a single item as its initialization
237 # object. This sink creates a single input port `in`. When it consumes
238 # from this port, it puts the returned message in the initialization
239 # list as the first item.
240 class TestProxySink(bt2
._UserSinkComponent
):
241 def __init__(self
, config
, params
, msg_list
):
242 assert msg_list
is not None
243 self
._msg
_list
= msg_list
244 self
._add
_input
_port
('in')
246 def _user_graph_is_configured(self
):
247 self
._msg
_iter
= self
._create
_message
_iterator
(self
._input
_ports
['in'])
249 def _user_consume(self
):
250 assert self
._msg
_list
[0] is None
251 self
._msg
_list
[0] = next(self
._msg
_iter
)
254 # This is a helper message iterator for tests.
256 # The constructor accepts a graph and an output port.
258 # Internally, it adds a proxy sink to the graph and connects the
259 # received output port to the proxy sink's input port. Its __next__()
260 # method then uses the proxy sink to transfer the consumed message to
261 # the output port message iterator's user.
263 # This message iterator cannot seek.
264 class TestOutputPortMessageIterator(collections
.abc
.Iterator
):
265 def __init__(self
, graph
, output_port
):
267 self
._msg
_list
= [None]
268 sink
= graph
.add_component(TestProxySink
, 'test-proxy-sink', obj
=self
._msg
_list
)
269 graph
.connect_ports(output_port
, sink
.input_ports
['in'])
272 assert self
._msg
_list
[0] is None
273 self
._graph
.run_once()
274 msg
= self
._msg
_list
[0]
275 assert msg
is not None
276 self
._msg
_list
[0] = None
280 # Create a const field of the given field class.
282 # The field is part of a dummy stream, itself part of a dummy trace created
283 # from trace class `tc`.
284 def create_const_field(tc
, field_class
, field_value_setter_fn
):
285 field_name
= 'const field'
287 class MyIter(bt2
._UserMessageIterator
):
288 def __init__(self
, config
, self_port_output
):
290 nonlocal field_value_setter_fn
292 packet_context_fc
= tc
.create_structure_field_class()
293 packet_context_fc
.append_member(field_name
, field_class
)
294 sc
= tc
.create_stream_class(
295 packet_context_field_class
=packet_context_fc
, supports_packets
=True
297 stream
= trace
.create_stream(sc
)
298 packet
= stream
.create_packet()
300 field_value_setter_fn(packet
.context_field
[field_name
])
303 self
._create
_stream
_beginning
_message
(stream
),
304 self
._create
_packet
_beginning
_message
(packet
),
308 if len(self
._msgs
) == 0:
311 return self
._msgs
.pop(0)
313 class MySrc(bt2
._UserSourceComponent
, message_iterator_class
=MyIter
):
314 def __init__(self
, config
, params
, obj
):
315 self
._add
_output
_port
('out', params
)
318 src_comp
= graph
.add_component(MySrc
, 'my_source', None)
319 msg_iter
= TestOutputPortMessageIterator(graph
, src_comp
.output_ports
['out'])
321 # Ignore first message, stream beginning
323 packet_beg_msg
= next(msg_iter
)
325 return packet_beg_msg
.packet
.context_field
[field_name
]