diff --git a/talk/app/webrtc/java/testcommon/src/org/webrtc/PeerConnectionTest.java b/talk/app/webrtc/java/testcommon/src/org/webrtc/PeerConnectionTest.java index 7affbd9e6f..001980f821 100644 --- a/talk/app/webrtc/java/testcommon/src/org/webrtc/PeerConnectionTest.java +++ b/talk/app/webrtc/java/testcommon/src/org/webrtc/PeerConnectionTest.java @@ -50,6 +50,7 @@ import static junit.framework.Assert.*; public class PeerConnectionTest { // Set to true to render video. private static final boolean RENDER_TO_GUI = false; + private static final int TIMEOUT_SECONDS = 20; private TreeSet threadsBeforeTest = null; private static class ObserverExpectations implements PeerConnection.Observer, @@ -347,7 +348,7 @@ public class PeerConnectionTest { return stillWaitingForExpectations; } - public void waitForAllExpectationsToBeSatisfied() { + public boolean waitForAllExpectationsToBeSatisfied(int timeoutSeconds) { // TODO(fischman): problems with this approach: // - come up with something better than a poll loop // - avoid serializing expectations explicitly; the test is not as robust @@ -357,6 +358,7 @@ public class PeerConnectionTest { // stall a wait). Use callbacks to fire off dependent steps instead of // explicitly waiting, so there can be just a single wait at the end of // the test. + long endTime = System.currentTimeMillis() + 1000 * timeoutSeconds; TreeSet prev = null; TreeSet stillWaitingForExpectations = unsatisfiedExpectations(); while (!stillWaitingForExpectations.isEmpty()) { @@ -367,6 +369,11 @@ public class PeerConnectionTest { "\n for: " + Arrays.toString(stillWaitingForExpectations.toArray())); } + if (endTime < System.currentTimeMillis()) { + System.out.println(name + " timed out waiting for: " + + Arrays.toString(stillWaitingForExpectations.toArray())); + return false; + } try { Thread.sleep(10); } catch (InterruptedException e) { @@ -379,6 +386,7 @@ public class PeerConnectionTest { System.out.println(name + " didn't need to wait at\n " + (new Throwable()).getStackTrace()[1]); } + return true; } // This methods return a list of all currently gathered ice candidates or waits until @@ -661,8 +669,8 @@ public class PeerConnectionTest { offeringPC.addIceCandidate(candidate); } - offeringExpectations.waitForAllExpectationsToBeSatisfied(); - answeringExpectations.waitForAllExpectationsToBeSatisfied(); + assertTrue(offeringExpectations.waitForAllExpectationsToBeSatisfied(TIMEOUT_SECONDS)); + assertTrue(answeringExpectations.waitForAllExpectationsToBeSatisfied(TIMEOUT_SECONDS)); assertEquals( PeerConnection.SignalingState.STABLE, offeringPC.signalingState()); @@ -675,7 +683,7 @@ public class PeerConnectionTest { DataChannel.Buffer buffer = new DataChannel.Buffer( ByteBuffer.wrap("hello!".getBytes(Charset.forName("UTF-8"))), false); assertTrue(offeringExpectations.dataChannel.send(buffer)); - answeringExpectations.waitForAllExpectationsToBeSatisfied(); + assertTrue(answeringExpectations.waitForAllExpectationsToBeSatisfied(TIMEOUT_SECONDS)); // Construct this binary message two different ways to ensure no // shortcuts are taken. @@ -688,7 +696,7 @@ public class PeerConnectionTest { assertTrue(answeringExpectations.dataChannel.send( new DataChannel.Buffer( ByteBuffer.wrap(new byte[] { 1, 2, 3, 4, 5 }), true))); - offeringExpectations.waitForAllExpectationsToBeSatisfied(); + assertTrue(offeringExpectations.waitForAllExpectationsToBeSatisfied(TIMEOUT_SECONDS)); offeringExpectations.expectStateChange(DataChannel.State.CLOSING); answeringExpectations.expectStateChange(DataChannel.State.CLOSING); @@ -734,14 +742,14 @@ public class PeerConnectionTest { expectations.dataChannel.dispose(); expectations.expectStatsCallback(); assertTrue(pc.getStats(expectations, null)); - expectations.waitForAllExpectationsToBeSatisfied(); + assertTrue(expectations.waitForAllExpectationsToBeSatisfied(TIMEOUT_SECONDS)); expectations.expectIceConnectionChange(IceConnectionState.CLOSED); expectations.expectSignalingChange(SignalingState.CLOSED); pc.close(); - expectations.waitForAllExpectationsToBeSatisfied(); + assertTrue(expectations.waitForAllExpectationsToBeSatisfied(TIMEOUT_SECONDS)); expectations.expectStatsCallback(); assertTrue(pc.getStats(expectations, null)); - expectations.waitForAllExpectationsToBeSatisfied(); + assertTrue(expectations.waitForAllExpectationsToBeSatisfied(TIMEOUT_SECONDS)); System.out.println("FYI stats: "); int reportIndex = -1; diff --git a/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.h b/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.h index 436515fa7c..7c49e1d768 100644 --- a/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.h +++ b/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.h @@ -54,6 +54,7 @@ - (void)expectMessage:(NSData*)message isBinary:(BOOL)isBinary; // Wait until all registered expectations above have been observed. -- (void)waitForAllExpectationsToBeSatisfied; +// Return false if expectations aren't met within |timeoutSeconds|. +- (BOOL)waitForAllExpectationsToBeSatisfiedWithTimeout:(NSTimeInterval)timeout; @end diff --git a/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m b/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m index daebc9523d..892c461980 100644 --- a/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m +++ b/talk/app/webrtc/objctests/RTCPeerConnectionSyncObserver.m @@ -139,14 +139,20 @@ [_expectedMessages addObject:buffer]; } -- (void)waitForAllExpectationsToBeSatisfied { +- (BOOL)waitForAllExpectationsToBeSatisfiedWithTimeout:(NSTimeInterval)timeout { + NSParameterAssert(timeout >= 0); // TODO (fischman): Revisit. Keeping in sync with the Java version, but // polling is not optimal. // https://code.google.com/p/libjingle/source/browse/trunk/talk/app/webrtc/javatests/src/org/webrtc/PeerConnectionTest.java?line=212#212 + NSDate *startTime = [NSDate date]; while (![self areAllExpectationsSatisfied]) { + if (startTime.timeIntervalSinceNow < -timeout) { + return NO; + } [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; } + return YES; } #pragma mark - RTCPeerConnectionDelegate methods diff --git a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm b/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm index f0703f5ad8..c43a6fcf24 100644 --- a/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm +++ b/talk/app/webrtc/objctests/RTCPeerConnectionTest.mm @@ -46,6 +46,8 @@ #error "This file requires ARC support." #endif +const NSTimeInterval kRTCPeerConnectionTestTimeout = 20; + @interface RTCFakeRenderer : NSObject @end @@ -238,8 +240,12 @@ [pcOffer addICECandidate:candidate]; } - [offeringExpectations waitForAllExpectationsToBeSatisfied]; - [answeringExpectations waitForAllExpectationsToBeSatisfied]; + EXPECT_TRUE( + [offeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); + EXPECT_TRUE( + [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); EXPECT_EQ(pcOffer.signalingState, RTCSignalingStable); EXPECT_EQ(pcAnswer.signalingState, RTCSignalingStable); @@ -251,7 +257,9 @@ [[RTCDataBuffer alloc] initWithData:textData isBinary:NO]; [answeringExpectations expectMessage:[textData copy] isBinary:NO]; EXPECT_TRUE([offeringExpectations.dataChannel sendData:buffer]); - [answeringExpectations waitForAllExpectationsToBeSatisfied]; + EXPECT_TRUE( + [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); // Test send and receive binary data const size_t byteLength = 5; @@ -260,7 +268,9 @@ buffer = [[RTCDataBuffer alloc] initWithData:byteData isBinary:YES]; [answeringExpectations expectMessage:[byteData copy] isBinary:YES]; EXPECT_TRUE([offeringExpectations.dataChannel sendData:buffer]); - [answeringExpectations waitForAllExpectationsToBeSatisfied]; + EXPECT_TRUE( + [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); [offeringExpectations expectStateChange:kRTCDataChannelStateClosing]; [answeringExpectations expectStateChange:kRTCDataChannelStateClosing]; @@ -270,8 +280,12 @@ [answeringExpectations.dataChannel close]; [offeringExpectations.dataChannel close]; - [offeringExpectations waitForAllExpectationsToBeSatisfied]; - [answeringExpectations waitForAllExpectationsToBeSatisfied]; + EXPECT_TRUE( + [offeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); + EXPECT_TRUE( + [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); // Don't need to listen to further state changes. // TODO(tkchin): figure out why Closed->Closing without this. offeringExpectations.dataChannel.delegate = nil; @@ -291,8 +305,12 @@ [pcOffer close]; [pcAnswer close]; - [offeringExpectations waitForAllExpectationsToBeSatisfied]; - [answeringExpectations waitForAllExpectationsToBeSatisfied]; + EXPECT_TRUE( + [offeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); + EXPECT_TRUE( + [answeringExpectations waitForAllExpectationsToBeSatisfiedWithTimeout: + kRTCPeerConnectionTestTimeout]); capturer = nil; videoSource = nil;