Skip to content

Commit 1bae12b

Browse files
committed
refactor(tests): Use of thekind parameter.
This commit updates all tests to use the `kind` parameter while creating a new `InstanaSpan` or `ReadableSpan`. This commit fixes #813. Signed-off-by: Paulo Vital <paulo.vital@ibm.com>
1 parent 29f78aa commit 1bae12b

5 files changed

Lines changed: 326 additions & 8 deletions

File tree

tests/collector/test_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ def test_format_span(self, context: Context) -> None:
3939
formatted_spans = format_span(span_list)
4040
assert len(formatted_spans) == 2
4141
assert formatted_spans[0].t == expected_trace_id
42-
assert formatted_spans[0].k == 1
42+
assert formatted_spans[0].k == 3
4343
assert formatted_spans[0].s == expected_span_id
4444
assert formatted_spans[0].n == "span1"
4545

4646
assert formatted_spans[1].t == expected_trace_id
4747
assert formatted_spans[1].p == formatted_spans[0].s
48-
assert formatted_spans[1].k == 1
48+
assert formatted_spans[1].k == 3
4949
assert formatted_spans[1].s != formatted_spans[0].s
5050
assert formatted_spans[1].n == "span2"
5151
assert formatted_spans[1].n == "span2"

tests/span/test_base_span.py

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# (c) Copyright IBM Corp. 2024
22

3-
from typing import Generator
43
from unittest.mock import Mock, patch
54

6-
import pytest
5+
from opentelemetry.trace import SpanKind
76

87
from instana.recorder import StanRecorder
98
from instana.span.base_span import BaseSpan
@@ -173,3 +172,82 @@ def test_convert_attribute_value_exception(
173172

174173
converted_value = base_span._convert_attribute_value(mock)
175174
assert not converted_value
175+
176+
177+
def test_basespan_does_not_store_kind(
178+
span_context: SpanContext,
179+
span_processor: StanRecorder,
180+
) -> None:
181+
"""Test that BaseSpan does not directly store or interfere with kind parameter."""
182+
span = InstanaSpan(
183+
"test-base-span", span_context, span_processor, kind=SpanKind.CLIENT
184+
)
185+
base_span = BaseSpan(span, None)
186+
187+
# BaseSpan should not have a kind attribute
188+
assert not hasattr(base_span, "k")
189+
assert not hasattr(base_span, "kind")
190+
191+
# But the original span should still have it
192+
assert span.kind == SpanKind.CLIENT
193+
194+
195+
def test_basespan_with_different_span_kinds(
196+
span_context: SpanContext,
197+
span_processor: StanRecorder,
198+
) -> None:
199+
"""Test that BaseSpan works correctly with spans of different kinds."""
200+
kinds = [
201+
SpanKind.INTERNAL,
202+
SpanKind.SERVER,
203+
SpanKind.CLIENT,
204+
SpanKind.PRODUCER,
205+
SpanKind.CONSUMER,
206+
]
207+
208+
for kind in kinds:
209+
span = InstanaSpan(
210+
f"test-span-{kind.name}", span_context, span_processor, kind=kind
211+
)
212+
base_span = BaseSpan(span, None)
213+
214+
# Verify BaseSpan is created successfully regardless of kind
215+
assert base_span.t == span_context.trace_id
216+
assert base_span.s == span_context.span_id
217+
218+
# Verify original span retains its kind
219+
assert span.kind == kind
220+
221+
222+
def test_basespan_kind_inheritance_to_registered_span(
223+
span_context: SpanContext,
224+
span_processor: StanRecorder,
225+
) -> None:
226+
"""Test that kind is properly inherited by RegisteredSpan through BaseSpan."""
227+
from instana.span.registered_span import RegisteredSpan
228+
229+
span = InstanaSpan("wsgi", span_context, span_processor, kind=SpanKind.SERVER)
230+
reg_span = RegisteredSpan(span, None, "test-service")
231+
232+
# RegisteredSpan should have k field set correctly
233+
assert reg_span.k == SpanKind.SERVER
234+
# Verify it inherits BaseSpan attributes
235+
assert reg_span.t == span_context.trace_id
236+
assert reg_span.s == span_context.span_id
237+
238+
239+
def test_basespan_kind_inheritance_to_sdk_span(
240+
span_context: SpanContext,
241+
span_processor: StanRecorder,
242+
) -> None:
243+
"""Test that kind is accessible by SDKSpan through BaseSpan."""
244+
from instana.span.sdk_span import SDKSpan
245+
246+
span = InstanaSpan("test-sdk", span_context, span_processor, kind=SpanKind.PRODUCER)
247+
sdk_span = SDKSpan(span, None, "test-service")
248+
249+
# SDKSpan should be able to access span.kind
250+
assert span.kind == SpanKind.PRODUCER
251+
# Verify it inherits BaseSpan attributes
252+
assert sdk_span.t == span_context.trace_id
253+
assert sdk_span.s == span_context.span_id

tests/span/test_readable_span.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Generator
55

66
import pytest
7+
from opentelemetry.trace import SpanKind
78
from opentelemetry.trace.status import Status, StatusCode
89

910
from instana.span.readable_span import Event, ReadableSpan
@@ -26,6 +27,8 @@ def test_readablespan(
2627
) -> None:
2728
span_name = "test-span"
2829
timestamp = time.time_ns()
30+
time.sleep(0.01)
31+
2932
self.span = ReadableSpan(span_name, span_context)
3033

3134
assert self.span is not None
@@ -45,10 +48,10 @@ def test_readablespan(
4548
assert not self.span.events
4649
assert not self.span.parent_id
4750
assert not self.span.duration
48-
assert self.span.status
49-
5051
assert not self.span.stack
5152
assert self.span.synthetic is False
53+
assert self.span.status
54+
assert self.span.kind == SpanKind.INTERNAL
5255

5356
def test_readablespan_with_params(
5457
self,
@@ -63,6 +66,8 @@ def test_readablespan_with_params(
6366
events = [Event(event_name, attributes, start_time)]
6467
status = Status(StatusCode.OK)
6568
stack = ["span-1", "span-2"]
69+
kind = SpanKind.CLIENT
70+
6671
self.span = ReadableSpan(
6772
span_name,
6873
span_context,
@@ -73,6 +78,7 @@ def test_readablespan_with_params(
7378
events,
7479
status,
7580
stack,
81+
kind,
7682
)
7783

7884
assert self.span.name == span_name
@@ -84,3 +90,51 @@ def test_readablespan_with_params(
8490
assert self.span.status == status
8591
assert self.span.duration == end_time - start_time
8692
assert self.span.stack == stack
93+
assert self.span.kind == kind
94+
assert self.span.kind != SpanKind.INTERNAL
95+
96+
@pytest.mark.parametrize(
97+
"kind",
98+
[
99+
SpanKind.INTERNAL,
100+
SpanKind.SERVER,
101+
SpanKind.CLIENT,
102+
SpanKind.PRODUCER,
103+
SpanKind.CONSUMER,
104+
],
105+
)
106+
def test_readablespan_all_kind_values(
107+
self,
108+
span_context: SpanContext,
109+
kind: SpanKind,
110+
) -> None:
111+
"""Test that ReadableSpan correctly stores all SpanKind enum values."""
112+
span_name = "test-span-kind"
113+
self.span = ReadableSpan(span_name, span_context, kind=kind)
114+
115+
assert self.span.kind == kind
116+
assert isinstance(self.span.kind, SpanKind)
117+
118+
def test_readablespan_kind_default(
119+
self,
120+
span_context: SpanContext,
121+
) -> None:
122+
"""Test that ReadableSpan defaults to SpanKind.INTERNAL when kind is not specified."""
123+
span_name = "test-span-default-kind"
124+
self.span = ReadableSpan(span_name, span_context)
125+
126+
assert self.span.kind == SpanKind.INTERNAL
127+
128+
def test_readablespan_kind_property_readonly(
129+
self,
130+
span_context: SpanContext,
131+
) -> None:
132+
"""Test that kind property is read-only and cannot be modified after creation."""
133+
span_name = "test-span-readonly"
134+
self.span = ReadableSpan(span_name, span_context, kind=SpanKind.SERVER)
135+
136+
assert self.span.kind == SpanKind.SERVER
137+
138+
# Verify kind is stored in private attribute and property returns it
139+
assert hasattr(self.span, "_kind")
140+
assert self.span._kind == SpanKind.SERVER

tests/span/test_registered_span.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,3 +495,70 @@ def test_collect_kafka_attributes(
495495

496496
assert excepted_result["kafka.service"] == reg_span.data["kafka"]["service"]
497497
assert excepted_result["kafka.access"] == reg_span.data["kafka"]["access"]
498+
499+
@pytest.mark.parametrize(
500+
"span_name, expected_kind",
501+
[
502+
("wsgi", SpanKind.SERVER),
503+
("django", SpanKind.SERVER),
504+
("rabbitmq", SpanKind.SERVER),
505+
("redis", SpanKind.CLIENT),
506+
("mysql", SpanKind.CLIENT),
507+
("mongodb", SpanKind.CLIENT),
508+
("urllib", SpanKind.CLIENT),
509+
("asyncio", SpanKind.INTERNAL),
510+
("render", SpanKind.INTERNAL),
511+
("gcps-producer", SpanKind.CLIENT),
512+
("gcps-consumer", SpanKind.SERVER),
513+
("kafka-producer", SpanKind.CLIENT),
514+
("kafka-consumer", SpanKind.SERVER),
515+
],
516+
)
517+
def test_registered_span_kind_from_instana_span(
518+
self,
519+
span_context: SpanContext,
520+
span_processor: StanRecorder,
521+
span_name: str,
522+
expected_kind: SpanKind,
523+
) -> None:
524+
"""Test that RegisteredSpan uses kind from InstanaSpan when provided."""
525+
service_name = "test-service"
526+
527+
# Create InstanaSpan with explicit kind
528+
self.span = InstanaSpan(
529+
span_name, span_context, span_processor, kind=expected_kind
530+
)
531+
reg_span = RegisteredSpan(self.span, None, service_name)
532+
533+
# Verify RegisteredSpan has correct kind for ENTRY span
534+
assert reg_span.k == expected_kind
535+
536+
# Verify name unification
537+
if "gcps" in span_name:
538+
assert reg_span.n == "gcps"
539+
elif "kafka" in span_name:
540+
assert reg_span.n == "kafka"
541+
else:
542+
assert reg_span.n == span_name
543+
544+
def test_registered_span_rabbitmq_publish_override(
545+
self,
546+
span_context: SpanContext,
547+
span_processor: StanRecorder,
548+
) -> None:
549+
"""Test that rabbitmq with sort=publish overrides to SpanKind.CLIENT."""
550+
span_name = "rabbitmq"
551+
attributes = {"sort": "publish"}
552+
553+
self.span = InstanaSpan(
554+
span_name,
555+
span_context,
556+
span_processor,
557+
kind=SpanKind.SERVER,
558+
attributes=attributes,
559+
)
560+
reg_span = RegisteredSpan(self.span, None, "test-service")
561+
562+
# Should be overridden to CLIENT for publish operation
563+
assert reg_span.k == SpanKind.CLIENT
564+
assert reg_span.data["rabbitmq"]["sort"] == "publish"

0 commit comments

Comments
 (0)