def test_export(self):

        span_names = ("test1", "test2", "test3")
        trace_id = 0x6E0C63257DE34C926F9EFCD03927272E
        span_id = 0x34BF92DEEFC58C92
        parent_id = 0x1111111111111111
        other_id = 0x2222222222222222

        base_time = 683647322 * 10**9  # in ns
        start_times = (
            base_time,
            base_time + 150 * 10**6,
            base_time + 300 * 10**6,
        )
        durations = (50 * 10**6, 100 * 10**6, 200 * 10**6)
        end_times = (
            start_times[0] + durations[0],
            start_times[1] + durations[1],
            start_times[2] + durations[2],
        )

        span_context = trace_api.SpanContext(
            trace_id,
            span_id,
            trace_options=TraceOptions(TraceOptions.SAMPLED),
        )
        parent_context = trace_api.SpanContext(trace_id, parent_id)
        other_context = trace_api.SpanContext(trace_id, other_id)

        event_attributes = {
            "annotation_bool": True,
            "annotation_string": "annotation_test",
            "key_float": 0.3,
        }

        event_timestamp = base_time + 50 * 10**6
        event = trace_api.Event(
            name="event0",
            timestamp=event_timestamp,
            attributes=event_attributes,
        )

        link_attributes = {"key_bool": True}

        link = trace_api.Link(context=other_context,
                              attributes=link_attributes)

        otel_spans = [
            trace.Span(
                name=span_names[0],
                context=span_context,
                parent=parent_context,
                events=(event, ),
                links=(link, ),
            ),
            trace.Span(name=span_names[1], context=parent_context,
                       parent=None),
            trace.Span(name=span_names[2], context=other_context, parent=None),
        ]

        otel_spans[0].start_time = start_times[0]
        # added here to preserve order
        otel_spans[0].set_attribute("key_bool", False)
        otel_spans[0].set_attribute("key_string", "hello_world")
        otel_spans[0].set_attribute("key_float", 111.22)
        otel_spans[0].end_time = end_times[0]

        otel_spans[1].start_time = start_times[1]
        otel_spans[1].end_time = end_times[1]

        otel_spans[2].start_time = start_times[2]
        otel_spans[2].end_time = end_times[2]

        service_name = "test-service"
        local_endpoint = {
            "serviceName": service_name,
            "port": 9411,
        }

        exporter = ZipkinSpanExporter(service_name)
        expected = [
            {
                "traceId":
                format(trace_id, "x"),
                "id":
                format(span_id, "x"),
                "name":
                span_names[0],
                "timestamp":
                start_times[0] // 10**3,
                "duration":
                durations[0] // 10**3,
                "localEndpoint":
                local_endpoint,
                "kind":
                None,
                "tags": {
                    "key_bool": "False",
                    "key_string": "hello_world",
                    "key_float": "111.22",
                },
                "annotations": [{
                    "timestamp": event_timestamp // 10**3,
                    "value": "event0",
                }],
                "debug":
                1,
                "parentId":
                format(parent_id, "x"),
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(parent_id, "x"),
                "name": span_names[1],
                "timestamp": start_times[1] // 10**3,
                "duration": durations[1] // 10**3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": None,
                "annotations": None,
            },
            {
                "traceId": format(trace_id, "x"),
                "id": format(other_id, "x"),
                "name": span_names[2],
                "timestamp": start_times[2] // 10**3,
                "duration": durations[2] // 10**3,
                "localEndpoint": local_endpoint,
                "kind": None,
                "tags": None,
                "annotations": None,
            },
        ]

        mock_post = MagicMock()
        with patch("requests.post", mock_post):
            mock_post.return_value = MockResponse(200)
            status = exporter.export(otel_spans)
            self.assertEqual(SpanExportResult.SUCCESS, status)

        mock_post.assert_called_with(
            url="http://localhost:9411/api/v2/spans",
            data=json.dumps(expected),
            headers={"Content-Type": "application/json"},
        )
 def test_invalid_response(self, mock_post):
     mock_post.return_value = MockResponse(404)
     spans = []
     exporter = ZipkinSpanExporter("test-service")
     status = exporter.export(spans)
     self.assertEqual(SpanExportResult.FAILED_NOT_RETRYABLE, status)