Skip to content

Commit bad2097

Browse files
authored
Merge pull request #2453 from DataDog/ncreated/chore/merge-app-state-enhancements-to-develop
chore: Consolidate Session Lifecycle Optimizations
2 parents 792a6cb + 863da08 commit bad2097

108 files changed

Lines changed: 7345 additions & 1809 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Datadog/Datadog.xcodeproj/project.pbxproj

Lines changed: 114 additions & 22 deletions
Large diffs are not rendered by default.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2019-Present Datadog, Inc.
5+
*/
6+
7+
import Foundation
8+
import TestUtilities
9+
10+
/// Defines a chain of `AppRunStep`s representing a test scenario for SDK integration testing.
11+
/// Allows building scenarios using `given()`, `when()`, and `then()` for fluent test composition.
12+
internal struct AppRun: Hashable {
13+
/// Ordered steps to perform in this run.
14+
let steps: [AppRunStep]
15+
16+
/// Starts a new test scenario with the initial step.
17+
/// - Parameter initialStep: The first step to define the starting point of the test.
18+
static func given(_ initialStep: AppRunStep) -> Self {
19+
return AppRun(steps: [initialStep])
20+
}
21+
22+
/// Adds a step to the scenario in the "when" phase.
23+
/// - Parameter step: The next step representing an action or change.
24+
func when(_ step: AppRunStep) -> Self {
25+
return .init(steps: steps + [step])
26+
}
27+
28+
/// Adds an additional step to the scenario (alias for `when()`).
29+
/// - Parameter step: The additional step to append to the sequence.
30+
func and(_ step: AppRunStep) -> Self {
31+
return when(step)
32+
}
33+
34+
/// Executes the defined scenario and returns the resulting RUM sessions.
35+
/// - Returns: An array of RUM session matchers.
36+
func then() throws -> [RUMSessionMatcher] {
37+
let app = AppRunner()
38+
app.setUp()
39+
defer { app.tearDown() }
40+
41+
// Perform all steps:
42+
steps.forEach { step in
43+
step.perform(app)
44+
}
45+
46+
// Get recorded sessions:
47+
let sessions = try app.recordedRUMSessions()
48+
return sessions
49+
}
50+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2019-Present Datadog, Inc.
5+
*/
6+
7+
import Foundation
8+
@testable import DatadogCore
9+
@testable import DatadogRUM
10+
11+
extension AppRunStep {
12+
// MARK: - App Lifecycle
13+
14+
static func appLaunch(type: AppRunner.ProcessLaunchType) -> AppRunStep {
15+
return AppRunStep({ app in
16+
app.launch(type)
17+
})
18+
}
19+
20+
static func advanceTime(by duration: TimeInterval) -> AppRunStep {
21+
return AppRunStep({ app in
22+
app.advanceTime(by: duration)
23+
})
24+
}
25+
26+
static func appBecomesActive(after dt: TimeInterval) -> AppRunStep {
27+
return AppRunStep({ app in
28+
app.advanceTime(by: dt)
29+
app.transitionToActive()
30+
})
31+
}
32+
33+
static func appEntersBackground(after dt: TimeInterval) -> AppRunStep {
34+
return AppRunStep({ app in
35+
app.advanceTime(by: dt)
36+
app.transitionToBackground()
37+
})
38+
}
39+
40+
// MARK: - RUM Use Cases
41+
42+
static func enableRUM(
43+
after dt: TimeInterval,
44+
sdkSetup: AppRunner.SDKSetup? = nil,
45+
rumSetup: AppRunner.RUMSetup? = nil
46+
) -> AppRunStep {
47+
return AppRunStep({ app in
48+
app.advanceTime(by: dt)
49+
app.initializeSDK(sdkSetup ?? { _ in })
50+
app.enableRUM { rumConfig in
51+
rumSetup?(&rumConfig)
52+
rumConfig.sessionEndedSampleRate = 0 // TODO: RUM-9335 Enable "Session Ended" telemetry after fixing `application.id` value for session stop
53+
rumConfig.telemetrySampleRate = 0
54+
}
55+
})
56+
}
57+
58+
static func stopSession(after dt: TimeInterval) -> AppRunStep {
59+
return AppRunStep({ app in
60+
app.advanceTime(by: dt)
61+
app.rum.stopSession()
62+
})
63+
}
64+
65+
static func timeoutSession() -> AppRunStep {
66+
return AppRunStep({ app in
67+
app.advanceTime(by: RUMSessionScope.Constants.sessionTimeoutDuration)
68+
})
69+
}
70+
71+
static func startManualView(after dt: TimeInterval, viewName: String, viewKey: String = "view") -> AppRunStep {
72+
return AppRunStep({ app in
73+
app.advanceTime(by: dt)
74+
app.rum.startView(key: viewKey, name: viewName)
75+
})
76+
}
77+
78+
static func stopManualView(after dt: TimeInterval, viewKey: String = "view") -> AppRunStep {
79+
return AppRunStep({ app in
80+
app.advanceTime(by: dt)
81+
app.rum.stopView(key: viewKey)
82+
})
83+
}
84+
85+
static func startAutomaticView(after dt: TimeInterval, viewController: UIViewController) -> AppRunStep {
86+
return AppRunStep({ app in
87+
app.advanceTime(by: dt)
88+
app.viewDidAppear(vc: viewController)
89+
})
90+
}
91+
92+
static func stopAutomaticView(after dt: TimeInterval, viewController: UIViewController) -> AppRunStep {
93+
return AppRunStep({ app in
94+
app.advanceTime(by: dt)
95+
app.viewDidDisappear(vc: viewController)
96+
})
97+
}
98+
99+
static func trackTwoActions(after1 dt1: TimeInterval, after2 dt2: TimeInterval) -> AppRunStep {
100+
return AppRunStep({ app in
101+
app.advanceTime(by: dt1)
102+
app.rum.addAction(type: .custom, name: "CustomAction1")
103+
app.advanceTime(by: dt2)
104+
app.rum.addAction(type: .custom, name: "CustomAction2")
105+
})
106+
}
107+
108+
static func trackResource(after dt: TimeInterval, duration: TimeInterval) -> AppRunStep {
109+
return AppRunStep({ app in
110+
app.advanceTime(by: dt)
111+
app.rum.startResource(resourceKey: "resource", url: URL(string: "https://resource.url")!)
112+
app.advanceTime(by: duration)
113+
app.rum.stopResource(resourceKey: "resource", response: .mockAny())
114+
})
115+
}
116+
117+
static func trackTwoLongTasks(after1 dt1: TimeInterval, after2 dt2: TimeInterval, duration1: TimeInterval = 0.1, duration2: TimeInterval = 0.1) -> AppRunStep {
118+
return AppRunStep({ app in
119+
app.advanceTime(by: dt1)
120+
app.rum._internal?.addLongTask(at: app.currentTime, duration: duration1)
121+
app.advanceTime(by: dt2)
122+
app.rum._internal?.addLongTask(at: app.currentTime, duration: duration2)
123+
})
124+
}
125+
126+
static func startResource(after dt: TimeInterval, key: String, url: URL) -> AppRunStep {
127+
return AppRunStep({ app in
128+
app.advanceTime(by: dt)
129+
app.rum.startResource(resourceKey: key, url: url)
130+
})
131+
}
132+
133+
static func stopResource(after dt: TimeInterval, key: String) -> AppRunStep {
134+
return AppRunStep({ app in
135+
app.advanceTime(by: dt)
136+
app.rum.stopResource(resourceKey: key, response: .mockAny())
137+
})
138+
}
139+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2019-Present Datadog, Inc.
5+
*/
6+
7+
import Foundation
8+
9+
/// Represents a single test action to be performed in an `AppRun`.
10+
internal struct AppRunStep: Hashable {
11+
/// Unique identifier used for distinguishing steps.
12+
let uuid = UUID()
13+
14+
/// The action to perform, provided with an `AppRunner` context.
15+
let perform: (AppRunner) -> Void
16+
17+
/// Creates a new step with the given execution closure.
18+
/// - Parameter perform: The closure that defines the step logic using the `AppRunner`.
19+
init(_ perform: @escaping (AppRunner) -> Void) {
20+
self.perform = perform
21+
}
22+
23+
// MARK: – Equatable
24+
25+
static func == (lhs: AppRunStep, rhs: AppRunStep) -> Bool { lhs.uuid == rhs.uuid }
26+
27+
// MARK: – Hashable
28+
29+
func hash(into hasher: inout Hasher) { hasher.combine(uuid) }
30+
}

0 commit comments

Comments
 (0)