text: import pytest
  
  from ddtrace import tracer, Span
  from ddtrace.http import store_request_headers, store_response_headers
  from ddtrace.settings import Config, IntegrationConfig
  
  
  class TestHeaders(object):
  
      @pytest.fixture()
      def span(self):
          yield Span(tracer, 'some_span')
  
      @pytest.fixture()
      def config(self):
          yield Config()
  
      @pytest.fixture()
      def integration_config(self, config):
          yield IntegrationConfig(config, 'test')
  
      def test_it_does_not_break_if_no_headers(self, span, integration_config):
          store_request_headers(None, span, integration_config)
          store_response_headers(None, span, integration_config)
  
      def test_it_does_not_break_if_headers_are_not_a_dict(self, span, integration_config):
          store_request_headers(list(), span, integration_config)
          store_response_headers(list(), span, integration_config)
  
      def test_it_accept_headers_as_list_of_tuples(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers(['Content-Type', 'Max-Age'])
          store_request_headers([('Content-Type', 'some;value;content-type')], span, integration_config)
          assert span.get_tag('http.request.headers.content-type') == 'some;value;content-type'
          assert None is span.get_tag('http.request.headers.other')
  
      def test_store_multiple_request_headers_as_dict(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers(['Content-Type', 'Max-Age'])
          store_request_headers({
              'Content-Type': 'some;value;content-type',
              'Max-Age': 'some;value;max_age',
              'Other': 'some;value;other',
          }, span, integration_config)
          assert span.get_tag('http.request.headers.content-type') == 'some;value;content-type'
          assert span.get_tag('http.request.headers.max-age') == 'some;value;max_age'
          assert None is span.get_tag('http.request.headers.other')
  
      def test_store_multiple_response_headers_as_dict(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers(['Content-Type', 'Max-Age'])
          store_response_headers({
              'Content-Type': 'some;value;content-type',
              'Max-Age': 'some;value;max_age',
              'Other': 'some;value;other',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.content-type') == 'some;value;content-type'
          assert span.get_tag('http.response.headers.max-age') == 'some;value;max_age'
          assert None is span.get_tag('http.response.headers.other')
  
      def test_numbers_in_headers_names_are_allowed(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers('Content-Type123')
          store_response_headers({
              'Content-Type123': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.content-type123') == 'some;value'
  
      def test_allowed_chars_not_replaced_in_tag_name(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          # See: https://docs.datadoghq.com/tagging/#defining-tags
          integration_config.http.trace_headers('C0n_t:e/nt-Type')
          store_response_headers({
              'C0n_t:e/nt-Type': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.c0n_t:e/nt-type') == 'some;value'
  
      def test_period_is_replaced_by_underscore(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          # Deviation from https://docs.datadoghq.com/tagging/#defining-tags in order to allow
          # consistent representation of headers having the period in the name.
          integration_config.http.trace_headers('api.token')
          store_response_headers({
              'api.token': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.api_token') == 'some;value'
  
      def test_non_allowed_chars_replaced(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          # See: https://docs.datadoghq.com/tagging/#defining-tags
          integration_config.http.trace_headers('C!#ontent-Type')
          store_response_headers({
              'C!#ontent-Type': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.c__ontent-type') == 'some;value'
  
      def test_key_trim_leading_trailing_spaced(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers('Content-Type')
          store_response_headers({
              '   Content-Type   ': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.content-type') == 'some;value'
  
      def test_value_not_trim_leading_trailing_spaced(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers('Content-Type')
          store_response_headers({
              'Content-Type': '   some;value   ',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.content-type') == '   some;value   '
  
      def test_no_allowlist(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          store_response_headers({
              'Content-Type': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.content-type') is None
  
      def test_allowlist_exact(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers('content-type')
          store_response_headers({
              'Content-Type': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.content-type') == 'some;value'
  
      def test_allowlist_case_insensitive(self, span, integration_config):
          """
          :type span: Span
          :type integration_config: IntegrationConfig
          """
          integration_config.http.trace_headers('CoNtEnT-tYpE')
          store_response_headers({
              'cOnTeNt-TyPe': 'some;value',
          }, span, integration_config)
          assert span.get_tag('http.response.headers.content-type') == 'some;value'
  