Skip to content

Commit

Permalink
[Fix]Failing iOS 15 tests (#572)
Browse files Browse the repository at this point in the history
  • Loading branch information
ipavlidakis authored Oct 18, 2024
1 parent f109a44 commit 004fba3
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 236 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ open class StreamDeviceOrientationAdapter: ObservableObject {
public typealias Provider = () -> StreamDeviceOrientation

/// The default provider for device orientation based on platform.
@MainActor
public static let defaultProvider: Provider = {
#if canImport(UIKit)
if let window = UIApplication.shared.connectedScenes.first as? UIWindowScene {
Expand Down Expand Up @@ -85,6 +86,7 @@ open class StreamDeviceOrientationAdapter: ObservableObject {
/// - Parameters:
/// - notificationCenter: The notification center to observe orientation changes.
/// - provider: A custom provider for determining device orientation.
@MainActor
public init(
notificationCenter: NotificationCenter = .default,
_ provider: @escaping Provider = StreamDeviceOrientationAdapter.defaultProvider
Expand All @@ -103,9 +105,7 @@ open class StreamDeviceOrientationAdapter: ObservableObject {
}
#endif

Task { @MainActor in
orientation = provider()
}
orientation = provider()
}

/// Cleans up resources when the adapter is deallocated.
Expand All @@ -119,11 +119,13 @@ open class StreamDeviceOrientationAdapter: ObservableObject {

/// Provides the default value of the `StreamPictureInPictureAdapter` class.
enum StreamDeviceOrientationAdapterKey: InjectionKey {
@MainActor
static var currentValue: StreamDeviceOrientationAdapter = .init()
}

extension InjectedValues {
/// Provides access to the `StreamDeviceOrientationAdapter` class to the views and view models.
@MainActor
public var orientationAdapter: StreamDeviceOrientationAdapter {
get {
Self[StreamDeviceOrientationAdapterKey.self]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ final class StreamVideoCaptureHandler: NSObject, RTCVideoCapturerDelegate {
colorSpace = CGColorSpaceCreateDeviceRGB()
super.init()

orientationCancellable = orientationAdapter
.$orientation
.removeDuplicates()
.receive(on: DispatchQueue.main)
.assign(to: \Self.sceneOrientation, onWeak: self)
sceneOrientation = orientationAdapter.orientation
Task { @MainActor in
orientationCancellable = orientationAdapter
.$orientation
.removeDuplicates()
.receive(on: DispatchQueue.main)
.assign(to: \Self.sceneOrientation, onWeak: self)
sceneOrientation = orientationAdapter.orientation
}
}

func capturer(
Expand Down
41 changes: 21 additions & 20 deletions Sources/StreamVideo/WebRTC/v2/WebRTCStateAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ actor WebRTCStateAdapter: ObservableObject {
}

/// Sets the session ID.
func set(sessionID value: String) { self.sessionID = value }
func set(sessionID value: String) {
self.sessionID = value
}

/// Sets the call settings.
func set(callSettings value: CallSettings) { self.callSettings = value }
Expand All @@ -141,7 +143,7 @@ actor WebRTCStateAdapter: ObservableObject {
func set(ownCapabilities value: Set<OwnCapability>) { self.ownCapabilities = value }

/// Sets the WebRTC stats reporter.
func set(statsReporter value: WebRTCStatsReporter) {
func set(statsReporter value: WebRTCStatsReporter?) {
self.statsReporter = value
}

Expand Down Expand Up @@ -286,38 +288,37 @@ actor WebRTCStateAdapter: ObservableObject {
self.subscriber = nil
self.statsReporter = nil
await sfuAdapter?.disconnect()
sfuAdapter = nil
token = ""
sessionID = ""
ownCapabilities = []
participants = [:]
participantsCount = 0
anonymousCount = 0
participantPins = []
enqueue { _ in [:] }
set(sfuAdapter: nil)
set(token: "")
set(sessionID: "")
set(ownCapabilities: [])
set(participantsCount: 0)
set(anonymousCount: 0)
set(participantPins: [])
audioTracks = [:]
videoTracks = [:]
screenShareTracks = [:]
}

/// Cleans up the session for reconnection, clearing adapters and tracks.
func cleanUpForReconnection() async {
sfuAdapter = nil
set(
participants: participants
.reduce(into: ParticipantsStorage()) { $0[$1.key] = $1.value.withUpdated(track: nil) }
)

peerConnectionsDisposableBag.removeAll()
await publisher?.prepareForClosing()
await subscriber?.prepareForClosing()
publisher = nil
subscriber = nil
statsReporter = nil
token = ""
set(sfuAdapter: nil)
set(statsReporter: nil)
set(token: "")
audioTracks = [:]
videoTracks = [:]
screenShareTracks = [:]
peerConnectionsDisposableBag.removeAll()

enqueue { participants in
participants.reduce(into: ParticipantsStorage()) { partialResult, entry in
partialResult[entry.key] = entry.value.withUpdated(track: nil)
}
}
}

/// Restores screen sharing if an active session exists.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import SnapshotTesting
import StreamSwiftTestHelpers
@testable import StreamVideo
@testable import StreamVideoSwiftUI
import XCTest
@preconcurrency import XCTest

@MainActor
final class ParticipantsGridLayout_Tests: StreamVideoUITestCase, @unchecked Sendable {

private var mockedOrientation: StreamDeviceOrientation! = .portrait(isUpsideDown: false)
Expand Down
9 changes: 9 additions & 0 deletions StreamVideoTests/Controllers/CallController_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -610,5 +610,14 @@ final class CallController_Tests: StreamVideoTestCase, @unchecked Sendable {
try await mockWebRTCCoordinatorFactory.mockCoordinatorStack.coordinator.stateAdapter.configurePeerConnections()
await mockWebRTCCoordinatorFactory.mockCoordinatorStack.coordinator.stateAdapter
.set(statsReporter: WebRTCStatsReporter(sessionID: .unique))

await fulfillment {
await self
.mockWebRTCCoordinatorFactory
.mockCoordinatorStack
.coordinator
.stateAdapter
.participants.count == 1
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import Foundation
@testable import StreamVideo
import StreamWebRTC
import XCTest
@preconcurrency import XCTest

final class StreamVideoCaptureHandler_Tests: XCTestCase {
final class StreamVideoCaptureHandler_Tests: XCTestCase, @unchecked Sendable {

private lazy var source: MockRTCVideoCapturerDelegate! = .init()
private lazy var subject: StreamVideoCaptureHandler! = .init(
Expand All @@ -27,6 +27,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {

// MARK: camera: front

@MainActor
func test_didCapture_orientationPortraitCameraFront_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .portrait(isUpsideDown: false),
Expand All @@ -35,6 +36,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {
)
}

@MainActor
func test_didCapture_orientationPortraitUpsideDownCameraFront_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .portrait(isUpsideDown: true),
Expand All @@ -43,6 +45,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {
)
}

@MainActor
func test_didCapture_orientationLandscapeLeftCameraFront_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .landscape(isLeft: true),
Expand All @@ -51,6 +54,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {
)
}

@MainActor
func test_didCapture_orientationLandscapeRightCameraFront_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .landscape(isLeft: false),
Expand All @@ -61,6 +65,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {

// MARK: camera: back

@MainActor
func test_didCapture_orientationPortraitCameraBack_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .portrait(isUpsideDown: false),
Expand All @@ -69,6 +74,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {
)
}

@MainActor
func test_didCapture_orientationPortraitUpsideDownCameraBack_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .portrait(isUpsideDown: true),
Expand All @@ -77,6 +83,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {
)
}

@MainActor
func test_didCapture_orientationLandscapeLeftCameraBack_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .landscape(isLeft: true),
Expand All @@ -85,6 +92,7 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {
)
}

@MainActor
func test_didCapture_orientationLandscapeRightCameraBack_frameHasExpectedOrientation() async throws {
try await assertFrameOrientation(
deviceOrientation: .landscape(isLeft: false),
Expand All @@ -95,17 +103,23 @@ final class StreamVideoCaptureHandler_Tests: XCTestCase {

// MARK: - Private Helpers

@MainActor
func assertFrameOrientation(
deviceOrientation: StreamDeviceOrientation,
cameraPosition: AVCaptureDevice.Position,
expected: RTCVideoRotation,
file: StaticString = #file,
line: UInt = #line
) async throws {
let orientationAdapter = StreamDeviceOrientationAdapter() { deviceOrientation }
var timesOrientationRequest = 0
let orientationAdapter = StreamDeviceOrientationAdapter() {
timesOrientationRequest += 1
return deviceOrientation
}
InjectedValues[\.orientationAdapter] = orientationAdapter
let capturer: RTCVideoCapturer! = .init()
_ = subject
await fulfillment { timesOrientationRequest == 1 }
subject.currentCameraPosition = cameraPosition
let frame = RTCVideoFrame(
buffer: RTCCVPixelBuffer(pixelBuffer: try .make()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,17 @@ final class WebRTCIntegrationTests: XCTestCase, @unchecked Sendable {
),

// -- Joining

.buildDefault(delay: 0.5) {
self.mockStack.joinResponse([
.dummy(id: await self.stateAdapter.sessionID)
])
},
.concurrent(
[
.init(delay: 0.5) { self.mockStack.joinResponse([.dummy(id: await self.stateAdapter.sessionID)]) },
.init {
self.mockStack.webRTCAuthenticator.stub(
for: .waitForConnect,
with: Result<Void, Error>.success(())
)
}
]
),
.concurrent(
[
.init {
Expand Down Expand Up @@ -133,15 +138,15 @@ final class WebRTCIntegrationTests: XCTestCase, @unchecked Sendable {
private func flowExecution(
of operations: [FlowOperation]
) async throws {
try await withThrowingTaskGroup(of: Void.self) { group in
for operation in operations {
switch operation {
case let .default(item):
if item.delay > 0 {
await self.wait(for: item.delay)
}
try await item.operation()
case let .concurrent(operations):
for operation in operations {
switch operation {
case let .default(item):
if item.delay > 0 {
await wait(for: item.delay)
}
try await item.operation()
case let .concurrent(operations):
try await withThrowingTaskGroup(of: Void.self) { group in
operations.forEach { item in
group.addTask {
if item.delay > 0 {
Expand Down
Loading

0 comments on commit 004fba3

Please sign in to comment.