From b415b6142f656c72378078e0fd186fd5c7a065f0 Mon Sep 17 00:00:00 2001 From: Matthew Chen <charlesmchen@gmail.com> Date: Wed, 1 Feb 2017 12:26:10 -0500 Subject: [PATCH] Respond to CR, mainly by fixing broken tests. // FREEBIE --- Signal/src/call/CallService.swift | 24 ++++++------- Signal/src/call/PeerConnectionClient.swift | 32 +++++++++++++++++ .../test/call/PeerConnectionClientTest.swift | 35 ++++++++++++++++--- 3 files changed, 75 insertions(+), 16 deletions(-) diff --git a/Signal/src/call/CallService.swift b/Signal/src/call/CallService.swift index 2e3ed4663..caee436d1 100644 --- a/Signal/src/call/CallService.swift +++ b/Signal/src/call/CallService.swift @@ -241,7 +241,7 @@ protocol CallServiceObserver: class { return Promise(error: CallError.assertionError(description: errorDescription)) } - return getIceServers().then(on: DispatchQueue.main) { iceServers -> Promise<HardenedRTCSessionDescription> in + return getIceServers().then() { iceServers -> Promise<HardenedRTCSessionDescription> in Logger.debug("\(self.TAG) got ice servers:\(iceServers)") let peerConnectionClient = PeerConnectionClient(iceServers: iceServers, delegate: self) @@ -253,13 +253,13 @@ protocol CallServiceObserver: class { self.peerConnectionClient = peerConnectionClient return self.peerConnectionClient!.createOffer() - }.then(on: DispatchQueue.main) { (sessionDescription: HardenedRTCSessionDescription) -> Promise<Void> in - return self.peerConnectionClient!.setLocalSessionDescription(sessionDescription).then(on: DispatchQueue.main) { + }.then() { (sessionDescription: HardenedRTCSessionDescription) -> Promise<Void> in + return self.peerConnectionClient!.setLocalSessionDescription(sessionDescription).then() { let offerMessage = OWSCallOfferMessage(callId: call.signalingId, sessionDescription: sessionDescription.sdp) let callMessage = OWSOutgoingCallMessage(thread: thread, offerMessage: offerMessage) return self.messageSender.sendCallMessage(callMessage) } - }.catch(on: DispatchQueue.main) { error in + }.catch() { error in Logger.error("\(self.TAG) placing call failed with error: \(error)") if let callError = error as? CallError { @@ -307,7 +307,7 @@ protocol CallServiceObserver: class { let sessionDescription = RTCSessionDescription(type: .answer, sdp: sessionDescription) _ = peerConnectionClient.setRemoteSessionDescription(sessionDescription).then { Logger.debug("\(self.TAG) successfully set remote description") - }.catch(on: DispatchQueue.main) { error in + }.catch() { error in if let callError = error as? CallError { self.handleFailedCall(error: callError) } else { @@ -392,7 +392,7 @@ protocol CallServiceObserver: class { incomingCallPromise = firstly { return getIceServers() - }.then(on: DispatchQueue.main) { (iceServers: [RTCIceServer]) -> Promise<HardenedRTCSessionDescription> in + }.then() { (iceServers: [RTCIceServer]) -> Promise<HardenedRTCSessionDescription> in // FIXME for first time call recipients I think we'll see mic/camera permission requests here, // even though, from the users perspective, no incoming call is yet visible. self.peerConnectionClient = PeerConnectionClient(iceServers: iceServers, delegate: self) @@ -402,14 +402,14 @@ protocol CallServiceObserver: class { // Find a sessionDescription compatible with my constraints and the remote sessionDescription return self.peerConnectionClient!.negotiateSessionDescription(remoteDescription: offerSessionDescription, constraints: constraints) - }.then(on: DispatchQueue.main) { (negotiatedSessionDescription: HardenedRTCSessionDescription) in + }.then() { (negotiatedSessionDescription: HardenedRTCSessionDescription) in Logger.debug("\(self.TAG) set the remote description") let answerMessage = OWSCallAnswerMessage(callId: newCall.signalingId, sessionDescription: negotiatedSessionDescription.sdp) let callAnswerMessage = OWSOutgoingCallMessage(thread: thread, answerMessage: answerMessage) return self.messageSender.sendCallMessage(callAnswerMessage) - }.then(on: DispatchQueue.main) { + }.then() { Logger.debug("\(self.TAG) successfully sent callAnswerMessage") let (promise, fulfill, _) = Promise<Void>.pending() @@ -423,7 +423,7 @@ protocol CallServiceObserver: class { self.fulfillCallConnectedPromise = fulfill return race(promise, timeout) - }.catch(on: DispatchQueue.main) { error in + }.catch() { error in if let callError = error as? CallError { self.handleFailedCall(error: callError) } else { @@ -738,9 +738,9 @@ protocol CallServiceObserver: class { // If the call hasn't started yet, we don't have a data channel to communicate the hang up. Use Signal Service Message. let hangupMessage = OWSCallHangupMessage(callId: call.signalingId) let callMessage = OWSOutgoingCallMessage(thread: thread, hangupMessage: hangupMessage) - _ = self.messageSender.sendCallMessage(callMessage).then(on: DispatchQueue.main) { + _ = self.messageSender.sendCallMessage(callMessage).then() { Logger.debug("\(self.TAG) successfully sent hangup call message to \(thread)") - }.catch(on: DispatchQueue.main) { error in + }.catch() { error in Logger.error("\(self.TAG) failed to send hangup call message to \(thread) with error: \(error)") } @@ -946,7 +946,7 @@ protocol CallServiceObserver: class { return firstly { return accountManager.getTurnServerInfo() - }.then(on: DispatchQueue.main) { turnServerInfo -> [RTCIceServer] in + }.then() { turnServerInfo -> [RTCIceServer] in Logger.debug("\(self.TAG) got turn server urls: \(turnServerInfo.urls)") return turnServerInfo.urls.map { url in diff --git a/Signal/src/call/PeerConnectionClient.swift b/Signal/src/call/PeerConnectionClient.swift index 3ff27d3d7..46aab4679 100644 --- a/Signal/src/call/PeerConnectionClient.swift +++ b/Signal/src/call/PeerConnectionClient.swift @@ -577,6 +577,38 @@ class PeerConnectionClient: NSObject, RTCPeerConnectionDelegate, RTCDataChannelD // Skipping check on <iOS10, since syntax is different and it's just a development convenience. } } + + // MARK: Test-only accessors + + internal func peerConnectionForTests() -> RTCPeerConnection { + AssertIsOnMainThread() + + var result: RTCPeerConnection? = nil + PeerConnectionClient.signalingQueue.sync { + result = peerConnection + Logger.info("\(self.TAG) called \(#function)") + } + return result! + } + + internal func dataChannelForTests() -> RTCDataChannel { + AssertIsOnMainThread() + + var result: RTCDataChannel? = nil + PeerConnectionClient.signalingQueue.sync { + result = dataChannel + Logger.info("\(self.TAG) called \(#function)") + } + return result! + } + + internal func flushSignalingQueueForTests() { + AssertIsOnMainThread() + + PeerConnectionClient.signalingQueue.sync { + // Noop. + } + } } /** diff --git a/Signal/test/call/PeerConnectionClientTest.swift b/Signal/test/call/PeerConnectionClientTest.swift index 4b2a4486f..85e615e1f 100644 --- a/Signal/test/call/PeerConnectionClientTest.swift +++ b/Signal/test/call/PeerConnectionClientTest.swift @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 1/11/17. -// Copyright © 2017 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// import XCTest import WebRTC @@ -32,6 +33,14 @@ class FakePeerConnectionClientDelegate: PeerConnectionClientDelegate { internal func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, received dataChannelMessage: OWSWebRTCProtosData) { dataChannelMessages.append(dataChannelMessage) } + + internal func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, didUpdateLocal videoTrack: RTCVideoTrack?) { + + } + + internal func peerConnectionClient(_ peerconnectionClient: PeerConnectionClient, didUpdateRemote videoTrack: RTCVideoTrack?) { + + } } class PeerConnectionClientTest: XCTestCase { @@ -47,9 +56,9 @@ class PeerConnectionClientTest: XCTestCase { let iceServers = [RTCIceServer]() clientDelegate = FakePeerConnectionClientDelegate() client = PeerConnectionClient(iceServers: iceServers, delegate: clientDelegate) - peerConnection = client.peerConnection + peerConnection = client.peerConnectionForTests() client.createSignalingDataChannel() - dataChannel = client.dataChannel! + dataChannel = client.dataChannelForTests() } override func tearDown() { @@ -62,12 +71,15 @@ class PeerConnectionClientTest: XCTestCase { XCTAssertNil(clientDelegate.connectionState) client.peerConnection(peerConnection, didChange: RTCIceConnectionState.connected) + waitForPeerConnectionClient() XCTAssertEqual(FakePeerConnectionClientDelegate.ConnectionState.connected, clientDelegate.connectionState) client.peerConnection(peerConnection, didChange: RTCIceConnectionState.completed) + waitForPeerConnectionClient() XCTAssertEqual(FakePeerConnectionClientDelegate.ConnectionState.connected, clientDelegate.connectionState) client.peerConnection(peerConnection, didChange: RTCIceConnectionState.failed) + waitForPeerConnectionClient() XCTAssertEqual(FakePeerConnectionClientDelegate.ConnectionState.failed, clientDelegate.connectionState) } @@ -82,9 +94,22 @@ class PeerConnectionClientTest: XCTestCase { client.peerConnection(peerConnection, didGenerate: candidate2) client.peerConnection(peerConnection, didGenerate: candidate3) + waitForPeerConnectionClient() + XCTAssertEqual(3, clientDelegate.localIceCandidates.count) } + func waitForPeerConnectionClient() { + // PeerConnectionClient processes RTCPeerConnectionDelegate invocations first on the signaling queue... + client.flushSignalingQueueForTests() + // ...then on the main queue. + let expectation = self.expectation(description: "Wait for PeerConnectionClient to call delegate method on main queue") + DispatchQueue.main.async { + expectation.fulfill() + } + self.waitForExpectations(timeout: 1.0, handler: nil) + } + func testDataChannelMessage() { XCTAssertEqual(0, clientDelegate.dataChannelMessages.count) @@ -92,6 +117,8 @@ class PeerConnectionClientTest: XCTestCase { let hangupBuffer = RTCDataBuffer(data: hangup.asData(), isBinary: false) client.dataChannel(dataChannel, didReceiveMessageWith: hangupBuffer) + waitForPeerConnectionClient() + XCTAssertEqual(1, clientDelegate.dataChannelMessages.count) let dataChannelMessageProto = clientDelegate.dataChannelMessages[0]