Skip to content

Commit 4aa6152

Browse files
authored
Extend and improve unittests (#356)
* feat(test): Add propagation tests for suppression scenarios * Based on test cases in tracer_compliance_test_cases.json * feat(test): Add unit test for StanRecorder with suppressed span * fix(test): Fix docstring of tear down in test_django
1 parent b578be8 commit 4aa6152

File tree

4 files changed

+231
-2
lines changed

4 files changed

+231
-2
lines changed

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
collect_ignore_glob.append("*test_tornado*")
2626
collect_ignore_glob.append("*test_grpc*")
2727
collect_ignore_glob.append("*test_boto3*")
28+
collect_ignore_glob.append("*test_stan_recorder*")
2829

2930
if "ASYNQP_TEST" not in os.environ:
3031
# if LooseVersion(sys.version) < LooseVersion('3.5.3') or LooseVersion(sys.version) >= LooseVersion('3.8.0'):

tests/frameworks/test_django.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def setUp(self):
2323
self.http = urllib3.PoolManager()
2424

2525
def tearDown(self):
26-
""" Do nothing for now """
26+
""" Clear the INSTANA_DISABLE_W3C_TRACE_CORRELATION environment variable """
2727
os.environ["INSTANA_DISABLE_W3C_TRACE_CORRELATION"] = ""
2828

2929
def test_basic_request(self):

tests/propagators/test_http_propagator.py

Lines changed: 199 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@
55
from instana.w3c_trace_context.traceparent import Traceparent
66
from instana.span_context import SpanContext
77
from mock import patch
8+
import os
89
import unittest
910

1011

1112
class TestHTTPPropagatorTC(unittest.TestCase):
1213
def setUp(self):
1314
self.hptc = HTTPPropagator()
1415

16+
def tearDown(self):
17+
""" Clear the INSTANA_DISABLE_W3C_TRACE_CORRELATION environment variable """
18+
os.environ["INSTANA_DISABLE_W3C_TRACE_CORRELATION"] = ""
19+
1520
@patch.object(Traceparent, "get_traceparent_fields")
1621
@patch.object(Traceparent, "validate")
1722
def test_extract_carrier_dict(self, mock_validate, mock_get_traceparent_fields):
@@ -163,4 +168,197 @@ def test_extract_carrier_dict_level_header_not_splitable(self, mock_validate, mo
163168
self.assertEqual(ctx.trace_id, "1234d0e0e4736234")
164169
self.assertIsNone(ctx.trace_parent)
165170
self.assertEqual(ctx.traceparent, '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01')
166-
self.assertEqual(ctx.tracestate, 'congo=t61rcWkgMzE')
171+
self.assertEqual(ctx.tracestate, 'congo=t61rcWkgMzE')
172+
173+
174+
# 28 in the tracer_compliance_test_cases.json
175+
# "Scenario/incoming headers": "w3c off, only X-INSTANA-L=0",
176+
def test_w3c_off_only_x_instana_l_0(self):
177+
carrier = {
178+
'X-INSTANA-L': '0'
179+
}
180+
os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'yes_please'
181+
ctx = self.hptc.extract(carrier)
182+
183+
# Assert that the level is (zero) int, not str
184+
self.assertEqual(ctx.level, 0)
185+
# Assert that the suppression is on
186+
self.assertTrue(ctx.suppression)
187+
188+
# Assert that the rest of the attributes are on their default value
189+
self.assertTrue(ctx.sampled)
190+
self.assertFalse(ctx.synthetic)
191+
self.assertEqual(ctx._baggage, {})
192+
193+
self.assertTrue(
194+
all(map(lambda x: x is None,
195+
(ctx.correlation_id, ctx.trace_id, ctx.span_id,
196+
ctx.trace_parent, ctx.instana_ancestor,
197+
ctx.long_trace_id, ctx.correlation_type,
198+
ctx.correlation_id, ctx.traceparent, ctx.tracestate)
199+
)))
200+
201+
# Simulate the sideffect of starting a span,
202+
# getting a trace_id and span_id:
203+
ctx.trace_id = ctx.span_id = '4dfe94d65496a02c'
204+
205+
# Test propagation
206+
downstream_carrier = {}
207+
208+
self.hptc.inject(ctx, downstream_carrier)
209+
210+
# Assert that 'X-INSTANA-L' has been injected with the correct 0 value
211+
self.assertIn('X-INSTANA-L', downstream_carrier)
212+
self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0')
213+
214+
self.assertIn('traceparent', downstream_carrier)
215+
self.assertEqual('00-0000000000000000' + ctx.trace_id + '-' + ctx.span_id + '-00',
216+
downstream_carrier.get('traceparent'))
217+
218+
219+
# 29 in the tracer_compliance_test_cases.json
220+
# "Scenario/incoming headers": "w3c off, X-INSTANA-L=0 plus -T and -S",
221+
def test_w3c_off_x_instana_l_0_plus_t_and_s(self):
222+
os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'w3c_trace_correlation_stinks'
223+
carrier = {
224+
'X-INSTANA-T': 'fa2375d711a4ca0f',
225+
'X-INSTANA-S': '37cb2d6e9b1c078a',
226+
'X-INSTANA-L': '0'
227+
}
228+
229+
ctx = self.hptc.extract(carrier)
230+
231+
# Assert that the level is (zero) int, not str
232+
self.assertEqual(ctx.level, 0)
233+
# Assert that the suppression is on
234+
self.assertTrue(ctx.suppression)
235+
236+
# Assert that the rest of the attributes are on their default value
237+
# And even T and S are None
238+
self.assertTrue(ctx.sampled)
239+
self.assertFalse(ctx.synthetic)
240+
self.assertEqual(ctx._baggage, {})
241+
242+
self.assertTrue(
243+
all(map(lambda x: x is None,
244+
(ctx.correlation_id, ctx.trace_id, ctx.span_id,
245+
ctx.trace_parent, ctx.instana_ancestor,
246+
ctx.long_trace_id, ctx.correlation_type,
247+
ctx.correlation_id, ctx.traceparent, ctx.tracestate)
248+
)))
249+
250+
# Simulate the sideffect of starting a span,
251+
# getting a trace_id and span_id:
252+
ctx.trace_id = ctx.span_id = '4dfe94d65496a02c'
253+
254+
# Test propagation
255+
downstream_carrier = {}
256+
257+
self.hptc.inject(ctx, downstream_carrier)
258+
259+
# Assert that 'X-INSTANA-L' has been injected with the correct 0 value
260+
self.assertIn('X-INSTANA-L', downstream_carrier)
261+
self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0')
262+
263+
self.assertIn('traceparent', downstream_carrier)
264+
self.assertEqual('00-0000000000000000' + ctx.trace_id + '-' + ctx.span_id + '-00',
265+
downstream_carrier.get('traceparent'))
266+
267+
268+
269+
# 30 in the tracer_compliance_test_cases.json
270+
# "Scenario/incoming headers": "w3c off, X-INSTANA-L=0 plus traceparent",
271+
def test_w3c_off_x_instana_l_0_plus_traceparent(self):
272+
os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'w3c_trace_correlation_stinks'
273+
carrier = {
274+
'traceparent': '00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01',
275+
'X-INSTANA-L': '0'
276+
}
277+
278+
ctx = self.hptc.extract(carrier)
279+
280+
# Assert that the level is (zero) int, not str
281+
self.assertEqual(ctx.level, 0)
282+
# Assert that the suppression is on
283+
self.assertTrue(ctx.suppression)
284+
# Assert that the traceparent is not None
285+
self.assertIsNotNone(ctx.traceparent)
286+
287+
# Assert that the rest of the attributes are on their default value
288+
self.assertTrue(ctx.sampled)
289+
self.assertFalse(ctx.synthetic)
290+
self.assertEqual(ctx._baggage, {})
291+
292+
self.assertTrue(
293+
all(map(lambda x: x is None,
294+
(ctx.correlation_id, ctx.trace_id, ctx.span_id,
295+
ctx.instana_ancestor, ctx.long_trace_id, ctx.correlation_type,
296+
ctx.correlation_id, ctx.tracestate)
297+
)))
298+
299+
# Simulate the sideffect of starting a span,
300+
# getting a trace_id and span_id:
301+
ctx.trace_id = ctx.span_id = '4dfe94d65496a02c'
302+
303+
# Test propagation
304+
downstream_carrier = {}
305+
self.hptc.inject(ctx, downstream_carrier)
306+
307+
# Assert that 'X-INSTANA-L' has been injected with the correct 0 value
308+
self.assertIn('X-INSTANA-L', downstream_carrier)
309+
self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0')
310+
# Assert that the traceparent is propagated
311+
self.assertIn('traceparent', downstream_carrier)
312+
self.assertEqual('00-0af7651916cd43dd8448eb211c80319c-' + ctx.trace_id + '-00',
313+
downstream_carrier.get('traceparent'))
314+
315+
316+
# 31 in the tracer_compliance_test_cases.json
317+
# "Scenario/incoming headers": "w3c off, X-INSTANA-L=0 plus traceparent and tracestate",
318+
def test_w3c_off_x_instana_l_0_plus_traceparent_and_tracestate(self):
319+
os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'w3c_trace_correlation_stinks'
320+
carrier = {
321+
'traceparent': '00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01',
322+
'tracestate': 'congo=ucfJifl5GOE,rojo=00f067aa0ba902b7',
323+
'X-INSTANA-L': '0'
324+
}
325+
326+
ctx = self.hptc.extract(carrier)
327+
328+
# Assert that the level is (zero) int, not str
329+
self.assertEqual(ctx.level, 0)
330+
# Assert that the suppression is on
331+
self.assertTrue(ctx.suppression)
332+
# Assert that the traceparent is not None
333+
self.assertIsNotNone(ctx.traceparent)
334+
335+
# Assert that the rest of the attributes are on their default value
336+
self.assertTrue(ctx.sampled)
337+
self.assertFalse(ctx.synthetic)
338+
self.assertEqual(ctx._baggage, {})
339+
340+
self.assertTrue(
341+
all(map(lambda x: x is None,
342+
(ctx.correlation_id, ctx.trace_id, ctx.span_id,
343+
ctx.instana_ancestor, ctx.long_trace_id, ctx.correlation_type,
344+
ctx.correlation_id)
345+
)))
346+
347+
# Simulate the sideffect of starting a span,
348+
# getting a trace_id and span_id:
349+
ctx.trace_id = ctx.span_id = '4dfe94d65496a02c'
350+
351+
# Test propagation
352+
downstream_carrier = {}
353+
self.hptc.inject(ctx, downstream_carrier)
354+
355+
# Assert that 'X-INSTANA-L' has been injected with the correct 0 value
356+
self.assertIn('X-INSTANA-L', downstream_carrier)
357+
self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0')
358+
# Assert that the traceparent is propagated
359+
self.assertIn('traceparent', downstream_carrier)
360+
self.assertEqual('00-0af7651916cd43dd8448eb211c80319c-' + ctx.trace_id + '-00',
361+
downstream_carrier.get('traceparent'))
362+
# Assert that the tracestate is propagated
363+
self.assertIn('tracestate', downstream_carrier)
364+
self.assertEqual(carrier['tracestate'], downstream_carrier['tracestate'])
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from instana.recorder import StanRecorder
2+
3+
from multiprocessing import Queue
4+
from unittest import TestCase
5+
from unittest.mock import NonCallableMagicMock, PropertyMock
6+
7+
class TestStanRecorderTC(TestCase):
8+
def setUp(self):
9+
mock_agent = NonCallableMagicMock()
10+
mock_collector = NonCallableMagicMock(span_queue=Queue())
11+
mock_agent.collector = mock_collector
12+
self.recorder = StanRecorder(agent=mock_agent)
13+
self.mock_suppressed_span = NonCallableMagicMock()
14+
self.mock_suppressed_span.context = NonCallableMagicMock()
15+
self.mock_suppressed_property = PropertyMock(return_value=True)
16+
type(self.mock_suppressed_span.context).suppression = self.mock_suppressed_property
17+
18+
def test_record_span_with_suppression(self):
19+
# Ensure that the queue is empty
20+
self.assertEqual(self.recorder.queue_size(), 0)
21+
self.recorder.record_span(self.mock_suppressed_span)
22+
# Ensure that even after adding a suppressed span
23+
# the queue remains empty
24+
self.assertEqual(self.recorder.queue_size(), 0)
25+
# Ensure that the no recorded spans can be retrieved
26+
self.assertEqual(self.recorder.queued_spans(), [])
27+
28+
# Make sure that the success so far has indeed resulted after a getitem
29+
# call to the 'suppression' property of the mock span context
30+
self.mock_suppressed_property.assert_called_once_with()

0 commit comments

Comments
 (0)