diff --git a/tests/conftest.py b/tests/conftest.py index 6f76293e..48b66f38 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,6 +25,7 @@ collect_ignore_glob.append("*test_tornado*") collect_ignore_glob.append("*test_grpc*") collect_ignore_glob.append("*test_boto3*") + collect_ignore_glob.append("*test_stan_recorder*") if "ASYNQP_TEST" not in os.environ: # if LooseVersion(sys.version) < LooseVersion('3.5.3') or LooseVersion(sys.version) >= LooseVersion('3.8.0'): diff --git a/tests/frameworks/test_django.py b/tests/frameworks/test_django.py index b4011304..00a4a796 100644 --- a/tests/frameworks/test_django.py +++ b/tests/frameworks/test_django.py @@ -23,7 +23,7 @@ def setUp(self): self.http = urllib3.PoolManager() def tearDown(self): - """ Do nothing for now """ + """ Clear the INSTANA_DISABLE_W3C_TRACE_CORRELATION environment variable """ os.environ["INSTANA_DISABLE_W3C_TRACE_CORRELATION"] = "" def test_basic_request(self): diff --git a/tests/propagators/test_http_propagator.py b/tests/propagators/test_http_propagator.py index 159c971a..e93041ae 100644 --- a/tests/propagators/test_http_propagator.py +++ b/tests/propagators/test_http_propagator.py @@ -5,6 +5,7 @@ from instana.w3c_trace_context.traceparent import Traceparent from instana.span_context import SpanContext from mock import patch +import os import unittest @@ -12,6 +13,10 @@ class TestHTTPPropagatorTC(unittest.TestCase): def setUp(self): self.hptc = HTTPPropagator() + def tearDown(self): + """ Clear the INSTANA_DISABLE_W3C_TRACE_CORRELATION environment variable """ + os.environ["INSTANA_DISABLE_W3C_TRACE_CORRELATION"] = "" + @patch.object(Traceparent, "get_traceparent_fields") @patch.object(Traceparent, "validate") 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 self.assertEqual(ctx.trace_id, "1234d0e0e4736234") self.assertIsNone(ctx.trace_parent) self.assertEqual(ctx.traceparent, '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01') - self.assertEqual(ctx.tracestate, 'congo=t61rcWkgMzE') \ No newline at end of file + self.assertEqual(ctx.tracestate, 'congo=t61rcWkgMzE') + + + # 28 in the tracer_compliance_test_cases.json + # "Scenario/incoming headers": "w3c off, only X-INSTANA-L=0", + def test_w3c_off_only_x_instana_l_0(self): + carrier = { + 'X-INSTANA-L': '0' + } + os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'yes_please' + ctx = self.hptc.extract(carrier) + + # Assert that the level is (zero) int, not str + self.assertEqual(ctx.level, 0) + # Assert that the suppression is on + self.assertTrue(ctx.suppression) + + # Assert that the rest of the attributes are on their default value + self.assertTrue(ctx.sampled) + self.assertFalse(ctx.synthetic) + self.assertEqual(ctx._baggage, {}) + + self.assertTrue( + all(map(lambda x: x is None, + (ctx.correlation_id, ctx.trace_id, ctx.span_id, + ctx.trace_parent, ctx.instana_ancestor, + ctx.long_trace_id, ctx.correlation_type, + ctx.correlation_id, ctx.traceparent, ctx.tracestate) + ))) + + # Simulate the sideffect of starting a span, + # getting a trace_id and span_id: + ctx.trace_id = ctx.span_id = '4dfe94d65496a02c' + + # Test propagation + downstream_carrier = {} + + self.hptc.inject(ctx, downstream_carrier) + + # Assert that 'X-INSTANA-L' has been injected with the correct 0 value + self.assertIn('X-INSTANA-L', downstream_carrier) + self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0') + + self.assertIn('traceparent', downstream_carrier) + self.assertEqual('00-0000000000000000' + ctx.trace_id + '-' + ctx.span_id + '-00', + downstream_carrier.get('traceparent')) + + + # 29 in the tracer_compliance_test_cases.json + # "Scenario/incoming headers": "w3c off, X-INSTANA-L=0 plus -T and -S", + def test_w3c_off_x_instana_l_0_plus_t_and_s(self): + os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'w3c_trace_correlation_stinks' + carrier = { + 'X-INSTANA-T': 'fa2375d711a4ca0f', + 'X-INSTANA-S': '37cb2d6e9b1c078a', + 'X-INSTANA-L': '0' + } + + ctx = self.hptc.extract(carrier) + + # Assert that the level is (zero) int, not str + self.assertEqual(ctx.level, 0) + # Assert that the suppression is on + self.assertTrue(ctx.suppression) + + # Assert that the rest of the attributes are on their default value + # And even T and S are None + self.assertTrue(ctx.sampled) + self.assertFalse(ctx.synthetic) + self.assertEqual(ctx._baggage, {}) + + self.assertTrue( + all(map(lambda x: x is None, + (ctx.correlation_id, ctx.trace_id, ctx.span_id, + ctx.trace_parent, ctx.instana_ancestor, + ctx.long_trace_id, ctx.correlation_type, + ctx.correlation_id, ctx.traceparent, ctx.tracestate) + ))) + + # Simulate the sideffect of starting a span, + # getting a trace_id and span_id: + ctx.trace_id = ctx.span_id = '4dfe94d65496a02c' + + # Test propagation + downstream_carrier = {} + + self.hptc.inject(ctx, downstream_carrier) + + # Assert that 'X-INSTANA-L' has been injected with the correct 0 value + self.assertIn('X-INSTANA-L', downstream_carrier) + self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0') + + self.assertIn('traceparent', downstream_carrier) + self.assertEqual('00-0000000000000000' + ctx.trace_id + '-' + ctx.span_id + '-00', + downstream_carrier.get('traceparent')) + + + + # 30 in the tracer_compliance_test_cases.json + # "Scenario/incoming headers": "w3c off, X-INSTANA-L=0 plus traceparent", + def test_w3c_off_x_instana_l_0_plus_traceparent(self): + os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'w3c_trace_correlation_stinks' + carrier = { + 'traceparent': '00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01', + 'X-INSTANA-L': '0' + } + + ctx = self.hptc.extract(carrier) + + # Assert that the level is (zero) int, not str + self.assertEqual(ctx.level, 0) + # Assert that the suppression is on + self.assertTrue(ctx.suppression) + # Assert that the traceparent is not None + self.assertIsNotNone(ctx.traceparent) + + # Assert that the rest of the attributes are on their default value + self.assertTrue(ctx.sampled) + self.assertFalse(ctx.synthetic) + self.assertEqual(ctx._baggage, {}) + + self.assertTrue( + all(map(lambda x: x is None, + (ctx.correlation_id, ctx.trace_id, ctx.span_id, + ctx.instana_ancestor, ctx.long_trace_id, ctx.correlation_type, + ctx.correlation_id, ctx.tracestate) + ))) + + # Simulate the sideffect of starting a span, + # getting a trace_id and span_id: + ctx.trace_id = ctx.span_id = '4dfe94d65496a02c' + + # Test propagation + downstream_carrier = {} + self.hptc.inject(ctx, downstream_carrier) + + # Assert that 'X-INSTANA-L' has been injected with the correct 0 value + self.assertIn('X-INSTANA-L', downstream_carrier) + self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0') + # Assert that the traceparent is propagated + self.assertIn('traceparent', downstream_carrier) + self.assertEqual('00-0af7651916cd43dd8448eb211c80319c-' + ctx.trace_id + '-00', + downstream_carrier.get('traceparent')) + + + # 31 in the tracer_compliance_test_cases.json + # "Scenario/incoming headers": "w3c off, X-INSTANA-L=0 plus traceparent and tracestate", + def test_w3c_off_x_instana_l_0_plus_traceparent_and_tracestate(self): + os.environ['INSTANA_DISABLE_W3C_TRACE_CORRELATION'] = 'w3c_trace_correlation_stinks' + carrier = { + 'traceparent': '00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01', + 'tracestate': 'congo=ucfJifl5GOE,rojo=00f067aa0ba902b7', + 'X-INSTANA-L': '0' + } + + ctx = self.hptc.extract(carrier) + + # Assert that the level is (zero) int, not str + self.assertEqual(ctx.level, 0) + # Assert that the suppression is on + self.assertTrue(ctx.suppression) + # Assert that the traceparent is not None + self.assertIsNotNone(ctx.traceparent) + + # Assert that the rest of the attributes are on their default value + self.assertTrue(ctx.sampled) + self.assertFalse(ctx.synthetic) + self.assertEqual(ctx._baggage, {}) + + self.assertTrue( + all(map(lambda x: x is None, + (ctx.correlation_id, ctx.trace_id, ctx.span_id, + ctx.instana_ancestor, ctx.long_trace_id, ctx.correlation_type, + ctx.correlation_id) + ))) + + # Simulate the sideffect of starting a span, + # getting a trace_id and span_id: + ctx.trace_id = ctx.span_id = '4dfe94d65496a02c' + + # Test propagation + downstream_carrier = {} + self.hptc.inject(ctx, downstream_carrier) + + # Assert that 'X-INSTANA-L' has been injected with the correct 0 value + self.assertIn('X-INSTANA-L', downstream_carrier) + self.assertEqual(downstream_carrier.get('X-INSTANA-L'), '0') + # Assert that the traceparent is propagated + self.assertIn('traceparent', downstream_carrier) + self.assertEqual('00-0af7651916cd43dd8448eb211c80319c-' + ctx.trace_id + '-00', + downstream_carrier.get('traceparent')) + # Assert that the tracestate is propagated + self.assertIn('tracestate', downstream_carrier) + self.assertEqual(carrier['tracestate'], downstream_carrier['tracestate']) diff --git a/tests/recorder/test_stan_recorder.py b/tests/recorder/test_stan_recorder.py new file mode 100644 index 00000000..adb08e78 --- /dev/null +++ b/tests/recorder/test_stan_recorder.py @@ -0,0 +1,30 @@ +from instana.recorder import StanRecorder + +from multiprocessing import Queue +from unittest import TestCase +from unittest.mock import NonCallableMagicMock, PropertyMock + +class TestStanRecorderTC(TestCase): + def setUp(self): + mock_agent = NonCallableMagicMock() + mock_collector = NonCallableMagicMock(span_queue=Queue()) + mock_agent.collector = mock_collector + self.recorder = StanRecorder(agent=mock_agent) + self.mock_suppressed_span = NonCallableMagicMock() + self.mock_suppressed_span.context = NonCallableMagicMock() + self.mock_suppressed_property = PropertyMock(return_value=True) + type(self.mock_suppressed_span.context).suppression = self.mock_suppressed_property + + def test_record_span_with_suppression(self): + # Ensure that the queue is empty + self.assertEqual(self.recorder.queue_size(), 0) + self.recorder.record_span(self.mock_suppressed_span) + # Ensure that even after adding a suppressed span + # the queue remains empty + self.assertEqual(self.recorder.queue_size(), 0) + # Ensure that the no recorded spans can be retrieved + self.assertEqual(self.recorder.queued_spans(), []) + + # Make sure that the success so far has indeed resulted after a getitem + # call to the 'suppression' property of the mock span context + self.mock_suppressed_property.assert_called_once_with()