20
20
from unittest import TestCase
21
21
from unittest .mock import Mock , patch
22
22
23
+ from opentelemetry import trace
23
24
from opentelemetry .baggage .propagation import W3CBaggagePropagator
25
+ from opentelemetry .context .context import Context
24
26
from opentelemetry .environment_variables import OTEL_PROPAGATORS
25
27
from opentelemetry .trace .propagation .tracecontext import (
26
28
TraceContextTextMapPropagator ,
@@ -44,6 +46,7 @@ def test_propagators(propagators):
44
46
** {"side_effect" : test_propagators }
45
47
)
46
48
49
+ # pylint: disable=import-outside-toplevel
47
50
import opentelemetry .propagate
48
51
49
52
reload (opentelemetry .propagate )
@@ -79,6 +82,7 @@ def test_propagators(propagators):
79
82
** {"side_effect" : test_propagators }
80
83
)
81
84
85
+ # pylint: disable=import-outside-toplevel
82
86
import opentelemetry .propagate
83
87
84
88
reload (opentelemetry .propagate )
@@ -88,6 +92,7 @@ def test_propagators(propagators):
88
92
)
89
93
def test_composite_propagators_error (self ):
90
94
95
+ # pylint: disable=import-outside-toplevel
91
96
import opentelemetry .propagate
92
97
93
98
with self .assertRaises (Exception ):
@@ -97,3 +102,145 @@ def test_composite_propagators_error(self):
97
102
"Failed to load configured propagator `unknown`" ,
98
103
err .output [0 ],
99
104
)
105
+
106
+
107
+ class TestTraceContextTextMapPropagator (TestCase ):
108
+ def setUp (self ):
109
+ self .propagator = TraceContextTextMapPropagator ()
110
+
111
+ def traceparent_helper (
112
+ self ,
113
+ carrier ,
114
+ ):
115
+ # We purposefully start with an empty context so we can test later if anything is added to it.
116
+ initial_context = Context ()
117
+
118
+ context = self .propagator .extract (carrier , context = initial_context )
119
+ self .assertIsNotNone (context )
120
+ self .assertIsInstance (context , Context )
121
+
122
+ return context
123
+
124
+ def traceparent_helper_generator (
125
+ self ,
126
+ version = 0x00 ,
127
+ trace_id = 0x00000000000000000000000000000001 ,
128
+ span_id = 0x0000000000000001 ,
129
+ trace_flags = 0x00 ,
130
+ suffix = "" ,
131
+ ):
132
+ traceparent = f"{ version :02x} -{ trace_id :032x} -{ span_id :016x} -{ trace_flags :02x} { suffix } "
133
+ carrier = {"traceparent" : traceparent }
134
+ return self .traceparent_helper (carrier )
135
+
136
+ def valid_traceparent_helper (
137
+ self ,
138
+ version = 0x00 ,
139
+ trace_id = 0x00000000000000000000000000000001 ,
140
+ span_id = 0x0000000000000001 ,
141
+ trace_flags = 0x00 ,
142
+ suffix = "" ,
143
+ assert_context_msg = "A valid traceparent was provided, so the context should be non-empty." ,
144
+ ):
145
+ context = self .traceparent_helper_generator (
146
+ version = version ,
147
+ trace_id = trace_id ,
148
+ span_id = span_id ,
149
+ trace_flags = trace_flags ,
150
+ suffix = suffix ,
151
+ )
152
+
153
+ self .assertNotEqual (
154
+ context ,
155
+ Context (),
156
+ assert_context_msg ,
157
+ )
158
+
159
+ span = trace .get_current_span (context )
160
+ self .assertIsNotNone (span )
161
+ self .assertIsInstance (span , trace .span .Span )
162
+
163
+ span_context = span .get_span_context ()
164
+ self .assertIsNotNone (span_context )
165
+ self .assertIsInstance (span_context , trace .span .SpanContext )
166
+
167
+ # Note: No version in SpanContext, it is only used locally in TraceContextTextMapPropagator
168
+ self .assertEqual (span_context .trace_id , trace_id )
169
+ self .assertEqual (span_context .span_id , span_id )
170
+ self .assertEqual (span_context .trace_flags , trace_flags )
171
+
172
+ self .assertIsInstance (span_context .trace_state , trace .TraceState )
173
+ self .assertCountEqual (span_context .trace_state , [])
174
+ self .assertEqual (span_context .is_remote , True )
175
+
176
+ return context , span , span_context
177
+
178
+ def invalid_traceparent_helper (
179
+ self ,
180
+ version = 0x00 ,
181
+ trace_id = 0x00000000000000000000000000000001 ,
182
+ span_id = 0x0000000000000001 ,
183
+ trace_flags = 0x00 ,
184
+ suffix = "" ,
185
+ assert_context_msg = "An invalid traceparent was provided, so the context should still be empty." ,
186
+ ):
187
+ context = self .traceparent_helper_generator (
188
+ version = version ,
189
+ trace_id = trace_id ,
190
+ span_id = span_id ,
191
+ trace_flags = trace_flags ,
192
+ suffix = suffix ,
193
+ )
194
+
195
+ self .assertEqual (
196
+ context ,
197
+ Context (),
198
+ assert_context_msg ,
199
+ )
200
+
201
+ return context
202
+
203
+ def test_extract_nothing (self ):
204
+ context = self .traceparent_helper (carrier = {})
205
+ self .assertEqual (
206
+ context ,
207
+ {},
208
+ "We didn't provide a valid traceparent, so we should still have an empty Context." ,
209
+ )
210
+
211
+ def test_extract_simple_traceparent (self ):
212
+ self .valid_traceparent_helper ()
213
+
214
+ # https://www.w3.org/TR/trace-context/#version
215
+ def test_extract_version_forbidden_ff (self ):
216
+ self .invalid_traceparent_helper (
217
+ version = 0xFF ,
218
+ assert_context_msg = "We provided ann invalid traceparent with a forbidden version=0xff, so the context should still be empty." ,
219
+ )
220
+
221
+ # https://www.w3.org/TR/trace-context/#version-format
222
+ def test_extract_version_00_with_unsupported_suffix (self ):
223
+ self .invalid_traceparent_helper (
224
+ suffix = "-f00" ,
225
+ assert_context_msg = "We provided an invalid traceparent with version=0x00 and suffix information which is not supported in this version, so the context should still be empty." ,
226
+ )
227
+
228
+ # https://www.w3.org/TR/trace-context/#versioning-of-traceparent
229
+ # See the parsing of the sampled bit of flags.
230
+ def test_extract_future_version_with_future_suffix_data (self ):
231
+ self .valid_traceparent_helper (
232
+ version = 0x99 ,
233
+ suffix = "-f00" ,
234
+ assert_context_msg = "We provided a traceparent that is possibly valid in the future with version=0x99 and suffix information, so the context be non-empty." ,
235
+ )
236
+
237
+ # https://www.w3.org/TR/trace-context/#trace-id
238
+ def test_extract_trace_id_invalid_all_zeros (self ):
239
+ self .invalid_traceparent_helper (trace_id = 0 )
240
+
241
+ # https://www.w3.org/TR/trace-context/#parent-id
242
+ def test_extract_span_id_invalid_all_zeros (self ):
243
+ self .invalid_traceparent_helper (span_id = 0 )
244
+
245
+ def test_extract_non_decimal_trace_flags (self ):
246
+ self .valid_traceparent_helper (trace_flags = 0xA0 )
0 commit comments