Skip to content

Commit 26212d5

Browse files
committed
add tests for the global Tracer methods
1 parent b9d9254 commit 26212d5

File tree

2 files changed

+194
-7
lines changed

2 files changed

+194
-7
lines changed

Tests/TracingTests/TestTracer.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ extension ServiceContext {
118118

119119
/// Only intended to be used in single-threaded testing.
120120
final class TestSpan: Span {
121-
private let kind: SpanKind
121+
let kind: SpanKind
122122

123123
private var status: SpanStatus?
124124

Tests/TracingTests/TracingInstrumentationSystemTests.swift

Lines changed: 193 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,218 @@ final class GlobalTracingInstrumentationSystemTests: XCTestCase {
3737
super.tearDown()
3838
InstrumentationSystem.bootstrapInternal(nil)
3939
}
40-
40+
4141
func testItProvidesAccessToATracer() {
4242
let tracer = TestTracer()
43-
43+
4444
XCTAssertNil(InstrumentationSystem._legacyTracer(of: TestTracer.self))
4545
XCTAssertNil(InstrumentationSystem._tracer(of: TestTracer.self))
46-
46+
4747
InstrumentationSystem.bootstrapInternal(tracer)
4848
XCTAssertFalse(InstrumentationSystem.instrument is MultiplexInstrument)
4949
XCTAssert(InstrumentationSystem._instrument(of: TestTracer.self) === tracer)
5050
XCTAssertNil(InstrumentationSystem._instrument(of: NoOpInstrument.self))
51-
51+
5252
XCTAssert(InstrumentationSystem._legacyTracer(of: TestTracer.self) === tracer)
5353
XCTAssert(InstrumentationSystem.legacyTracer is TestTracer)
5454
XCTAssert(InstrumentationSystem._tracer(of: TestTracer.self) === tracer)
5555
XCTAssert(InstrumentationSystem.tracer is TestTracer)
56-
56+
5757
let multiplexInstrument = MultiplexInstrument([tracer])
5858
InstrumentationSystem.bootstrapInternal(multiplexInstrument)
5959
XCTAssert(InstrumentationSystem.instrument is MultiplexInstrument)
6060
XCTAssert(InstrumentationSystem._instrument(of: TestTracer.self) === tracer)
61-
61+
6262
XCTAssert(InstrumentationSystem._legacyTracer(of: TestTracer.self) === tracer)
6363
XCTAssert(InstrumentationSystem.legacyTracer is TestTracer)
6464
XCTAssert(InstrumentationSystem._tracer(of: TestTracer.self) === tracer)
6565
XCTAssert(InstrumentationSystem.tracer is TestTracer)
6666
}
6767
}
68+
69+
final class GlobalTracingMethodsTests: XCTestCase {
70+
override class func tearDown() {
71+
super.tearDown()
72+
InstrumentationSystem.bootstrapInternal(nil)
73+
}
74+
75+
func testGlobalTracingMethods() async {
76+
// Bootstrap with TestTracer to capture spans
77+
let tracer = TestTracer()
78+
InstrumentationSystem.bootstrapInternal(tracer)
79+
80+
// Create custom timestamps for testing
81+
let clock = DefaultTracerClock()
82+
let customInstant1 = clock.now
83+
let customInstant2 = clock.now
84+
let customInstant3 = clock.now
85+
86+
// Create custom contexts to verify they're preserved
87+
var customContext1 = ServiceContext.topLevel
88+
customContext1[TestContextKey.self] = "context1"
89+
90+
var customContext2 = ServiceContext.topLevel
91+
customContext2[TestContextKey.self] = "context2"
92+
93+
// Test 1: startSpan with custom instant
94+
let span1 = startSpan(
95+
"startSpan-with-instant",
96+
at: customInstant1,
97+
context: customContext1,
98+
ofKind: .client
99+
)
100+
span1.end()
101+
102+
// Test 2: startSpan without instant (uses default)
103+
let span2 = startSpan(
104+
"startSpan-default-instant",
105+
context: customContext2,
106+
ofKind: .server
107+
)
108+
span2.end()
109+
110+
// Test 3: startSpan with instant (different parameter order)
111+
let span3 = startSpan(
112+
"startSpan-instant-alt",
113+
context: .topLevel,
114+
ofKind: .producer,
115+
at: customInstant2
116+
)
117+
span3.end()
118+
119+
// Test 4: withSpan synchronous with custom instant
120+
let result1 = withSpan(
121+
"withSpan-sync-instant",
122+
at: customInstant3,
123+
context: customContext1,
124+
ofKind: .consumer
125+
) { span -> String in
126+
XCTAssertEqual(span.operationName, "withSpan-sync-instant")
127+
return "sync-result"
128+
}
129+
XCTAssertEqual(result1, "sync-result")
130+
131+
// Test 5: withSpan synchronous without instant
132+
let result2 = withSpan(
133+
"withSpan-sync-default",
134+
context: customContext2,
135+
ofKind: .internal
136+
) { span -> Int in
137+
XCTAssertEqual(span.operationName, "withSpan-sync-default")
138+
return 42
139+
}
140+
XCTAssertEqual(result2, 42)
141+
142+
// Test 6: withSpan synchronous with instant (alt parameter order)
143+
let result3 = withSpan(
144+
"withSpan-sync-instant-alt",
145+
context: .topLevel,
146+
ofKind: .server,
147+
at: clock.now
148+
) { _ in
149+
"alt-result"
150+
}
151+
XCTAssertEqual(result3, "alt-result")
152+
153+
// Test 7: withSpan async with custom instant and isolation
154+
let result4 = await withSpan(
155+
"withSpan-async-instant-isolation",
156+
at: clock.now,
157+
context: customContext1,
158+
ofKind: .client,
159+
isolation: nil
160+
) { span -> String in
161+
XCTAssertEqual(span.operationName, "withSpan-async-instant-isolation")
162+
return "async-result"
163+
}
164+
XCTAssertEqual(result4, "async-result")
165+
166+
// Test 8: withSpan async without instant but with isolation
167+
let result5 = await withSpan(
168+
"withSpan-async-default-isolation",
169+
context: customContext2,
170+
ofKind: .producer,
171+
isolation: nil
172+
) { span -> Bool in
173+
XCTAssertEqual(span.operationName, "withSpan-async-default-isolation")
174+
return true
175+
}
176+
XCTAssertEqual(result5, true)
177+
178+
// Test 9: withSpan async with instant, isolation (alt parameter order)
179+
let result6 = await withSpan(
180+
"withSpan-async-instant-isolation-alt",
181+
context: .topLevel,
182+
ofKind: .consumer,
183+
at: clock.now,
184+
isolation: nil
185+
) { _ in
186+
99
187+
}
188+
XCTAssertEqual(result6, 99)
189+
190+
// Verify all spans were recorded with correct properties
191+
let finishedSpans = tracer.spans
192+
XCTAssertEqual(finishedSpans.count, 9, "Expected 9 finished spans")
193+
194+
// Verify span 1: startSpan with custom instant
195+
let recorded1 = finishedSpans[0]
196+
XCTAssertEqual(recorded1.operationName, "startSpan-with-instant")
197+
XCTAssertEqual(recorded1.kind, .client)
198+
XCTAssertEqual(recorded1.context[TestContextKey.self], "context1")
199+
XCTAssertEqual(recorded1.startTimestampNanosSinceEpoch, customInstant1.nanosecondsSinceEpoch)
200+
201+
// Verify span 2: startSpan without instant
202+
let recorded2 = finishedSpans[1]
203+
XCTAssertEqual(recorded2.operationName, "startSpan-default-instant")
204+
XCTAssertEqual(recorded2.kind, .server)
205+
XCTAssertEqual(recorded2.context[TestContextKey.self], "context2")
206+
// Note: Can't verify exact instant since it used DefaultTracerClock.now
207+
208+
// Verify span 3: startSpan with instant (alt)
209+
let recorded3 = finishedSpans[2]
210+
XCTAssertEqual(recorded3.operationName, "startSpan-instant-alt")
211+
XCTAssertEqual(recorded3.kind, .producer)
212+
XCTAssertEqual(recorded3.startTimestampNanosSinceEpoch, customInstant2.nanosecondsSinceEpoch)
213+
214+
// Verify span 4: withSpan sync with instant
215+
let recorded4 = finishedSpans[3]
216+
XCTAssertEqual(recorded4.operationName, "withSpan-sync-instant")
217+
XCTAssertEqual(recorded4.kind, .consumer)
218+
XCTAssertEqual(recorded4.context[TestContextKey.self], "context1")
219+
XCTAssertEqual(recorded4.startTimestampNanosSinceEpoch, customInstant3.nanosecondsSinceEpoch)
220+
221+
// Verify span 5: withSpan sync without instant
222+
let recorded5 = finishedSpans[4]
223+
XCTAssertEqual(recorded5.operationName, "withSpan-sync-default")
224+
XCTAssertEqual(recorded5.kind, .internal)
225+
XCTAssertEqual(recorded5.context[TestContextKey.self], "context2")
226+
227+
// Verify span 6: withSpan sync with instant (alt)
228+
let recorded6 = finishedSpans[5]
229+
XCTAssertEqual(recorded6.operationName, "withSpan-sync-instant-alt")
230+
XCTAssertEqual(recorded6.kind, .server)
231+
232+
// Verify span 7: withSpan async with instant and isolation
233+
let recorded7 = finishedSpans[6]
234+
XCTAssertEqual(recorded7.operationName, "withSpan-async-instant-isolation")
235+
XCTAssertEqual(recorded7.kind, .client)
236+
XCTAssertEqual(recorded7.context[TestContextKey.self], "context1")
237+
238+
// Verify span 8: withSpan async without instant but with isolation
239+
let recorded8 = finishedSpans[7]
240+
XCTAssertEqual(recorded8.operationName, "withSpan-async-default-isolation")
241+
XCTAssertEqual(recorded8.kind, .producer)
242+
XCTAssertEqual(recorded8.context[TestContextKey.self], "context2")
243+
244+
// Verify span 9: withSpan async with instant and isolation (alt)
245+
let recorded9 = finishedSpans[8]
246+
XCTAssertEqual(recorded9.operationName, "withSpan-async-instant-isolation-alt")
247+
XCTAssertEqual(recorded9.kind, .consumer)
248+
}
249+
}
250+
251+
// Test context key for verification
252+
private enum TestContextKey: ServiceContextKey {
253+
typealias Value = String
254+
}

0 commit comments

Comments
 (0)