Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import XCTest
class SentryNetworkTrackerIntegrationTestServerTests: XCTestCase {

func testGetRequest_SpanCreatedAndBaggageHeaderAdded() throws {
try ensureTestServerIsRunning()

let testBaggageURL = try XCTUnwrap(URL(string: "http://localhost:8080/echo-baggage-header"))

startSDK()

let transaction = try XCTUnwrap(SentrySDK.startTransaction(name: "Test Transaction", operation: "TEST", bindToScope: true) as? SentryTracer)

let expect = expectation(description: "Request completed")
// Cancelling the task in defer can trigger the completion handler again.
expect.assertForOverFulfill = false

let session = URLSession(configuration: URLSessionConfiguration.default)

let dataTask = session.dataTask(with: testBaggageURL) { (data, _, error) in
Expand All @@ -28,8 +34,10 @@ class SentryNetworkTrackerIntegrationTestServerTests: XCTestCase {
expect.fulfill()
}

defer { dataTask.cancel() }

dataTask.resume()
wait(for: [expect], timeout: 5)
wait(for: [expect], timeout: 10)

let children = try XCTUnwrap(Dynamic(transaction).children as [Span]?)

Expand All @@ -43,12 +51,18 @@ class SentryNetworkTrackerIntegrationTestServerTests: XCTestCase {
}

func testGetRequest_CompareSentryTraceHeader() throws {
try ensureTestServerIsRunning()

let testTraceURL = try XCTUnwrap(URL(string: "http://localhost:8080/echo-sentry-trace"))

startSDK()

let transaction = try XCTUnwrap(SentrySDK.startTransaction(name: "Test Transaction", operation: "TEST", bindToScope: true) as? SentryTracer)

let expect = expectation(description: "Request completed")
// Cancelling the task in defer can trigger the completion handler again.
expect.assertForOverFulfill = false

let session = URLSession(configuration: URLSessionConfiguration.default)
var response: String?
let dataTask = session.dataTask(with: testTraceURL) { (data, _, error) in
Expand All @@ -57,8 +71,10 @@ class SentryNetworkTrackerIntegrationTestServerTests: XCTestCase {
expect.fulfill()
}

defer { dataTask.cancel() }

dataTask.resume()
wait(for: [expect], timeout: 5)
wait(for: [expect], timeout: 10)

let children = Dynamic(transaction).children as [SentrySpan]?

Expand All @@ -70,9 +86,14 @@ class SentryNetworkTrackerIntegrationTestServerTests: XCTestCase {
}

func testGetCaptureFailedRequestsEnabled() throws {
try ensureTestServerIsRunning()

let clientErrorTraceURL = try XCTUnwrap(URL(string: "http://localhost:8080/http-client-error"))

let expect = expectation(description: "Request completed")
expect.expectedFulfillmentCount = 2
// Cancelling the task in defer can trigger the completion handler again.
expect.assertForOverFulfill = false

var sentryEvent: Event?

Expand All @@ -90,17 +111,21 @@ class SentryNetworkTrackerIntegrationTestServerTests: XCTestCase {

let dataTask = session.dataTask(with: clientErrorTraceURL) { (_, _, error) in
self.assertNetworkError(error)
expect.fulfill()
}

defer { dataTask.cancel() }

dataTask.resume()
wait(for: [expect], timeout: 5)
wait(for: [expect], timeout: 10)

XCTAssertNotNil(sentryEvent)
XCTAssertNotNil(sentryEvent?.request)

let sentryResponse = sentryEvent?.context?["response"]
let sentryResponse = try XCTUnwrap(sentryEvent?.context?["response"], "Expected context.response, but was nil")
let statusCode = try XCTUnwrap(sentryResponse["status_code"] as? NSNumber, "Expected context.response.status_code, but was nil")

XCTAssertEqual(sentryResponse?["status_code"] as? NSNumber, 400)
XCTAssertEqual(statusCode, 400)
}

private func assertNetworkError(_ error: Error?) {
Expand All @@ -109,6 +134,51 @@ class SentryNetworkTrackerIntegrationTestServerTests: XCTestCase {
}
}

// We can't use a XCTTestExpectation here because we want to retry multiple times.
// If a XCTestExpectation times out, the test would fail.
// swiftlint:disable avoid_dispatch_groups_in_tests
private func ensureTestServerIsRunning() throws {
let testUrl = try XCTUnwrap(URL(string: "http://localhost:8080/"))

let session = URLSession(configuration: URLSessionConfiguration.default)
let attempts = 20

//swiftlint:disable:next for_where
for attempt in 1..<attempts {
let group = DispatchGroup()
var isReady = false

group.enter()
let dataTask = session.dataTask(with: testUrl) { (_, response, error) in
if error == nil, let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
isReady = true
}
group.leave()
}

defer { dataTask.cancel() }

dataTask.resume()

// We don't care about the result, we just want to wait up to 2 seconds for the request to complete.
// If it doesn't work we retry.
_ = group.wait(timeout: .now() + 2)

if isReady {
print("Test server is ready after \(attempt) attempt(s)")
return
}

if attempt < 10 {
print("Test server not ready, retrying in 1 second... (attempt \(attempt)/10)")
Thread.sleep(forTimeInterval: 1.0)
}
}

XCTFail("Test server failed to become ready after \(attempts) attempts")
}
// swiftlint:enable avoid_dispatch_groups_in_tests

private func startSDK(function: String = #function, _ configureOptions: ((Options) -> Void)? = nil) {
let options = Options()
options.dsn = TestConstants.dsnAsString(username: "SentryNetworkTrackerIntegrationTestServerTests.\(function)")
Expand Down
Loading