Commit 63622282 authored by Harald Alvestrand's avatar Harald Alvestrand Committed by Commit Bot

Fix RTCPeerConnection tests that timed out after real PC

Rewrote RTCPeerConnection-lifetime and RTCPeerCOnnection-ontrack
to work with real peerconnections.

Deleted three tests that should have appropriate coverage
in existing WPT tests.

Bug: 771540
Change-Id: I1d5d26bb48ce4993714115bdcfb9ceb2edd02947
Reviewed-on: https://chromium-review.googlesource.com/715597
Commit-Queue: Harald Alvestrand <hta@chromium.org>
Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Reviewed-by: default avatarGuido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#509284}
parent 31c85e74
......@@ -3738,11 +3738,6 @@ crbug.com/770971 [ Win7 ] fast/forms/suggested-value.html [ Pass Failure ]
crbug.com/771492 [ Win Linux Mac ] external/wpt/css/css-tables-3/table-model-fixup-2.html [ Failure ]
# Suspended WebRTC tests
crbug.com/771540 fast/peerconnection/RTCPeerConnection-dtmf.html [ Timeout ]
crbug.com/771540 fast/peerconnection/RTCPeerConnection-ice-promise.html [ Timeout ]
crbug.com/771540 fast/peerconnection/RTCPeerConnection-ice.html [ Timeout ]
crbug.com/771540 fast/peerconnection/RTCPeerConnection-lifetime.html [ Timeout ]
crbug.com/771540 fast/peerconnection/RTCPeerConnection-ontrack.html [ Timeout ]
# Test fails, and output changes for each run.
crbug.com/771540 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Failure ]
# Test is flaky after removing mock PeerConnectionHandler
......
......@@ -121,7 +121,7 @@ function connect_pcs(pc_a, pc_b) {
return pc_b.setLocalDescription(answer);
})
.then(function() {
return pc_a.setRemoteDescription(pc2.localDescription);
return pc_a.setRemoteDescription(pc_b.localDescription);
})
}
......
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<script>
description("Tests RTCDTMFSender.");
var pc = null;
var stream = null;
var dtmfsender = null;
function error() {
testFailed('Error callback called.');
finishJSTest();
}
var firstCall = true;
function ontonechange(e) {
testPassed("ontonechange was called.");
event = e;
if (firstCall) {
shouldBeEqualToString('event.tone', "1");
firstCall = false;
} else {
shouldBeEqualToString('event.tone', "");
finishJSTest();
}
}
function pc_onicechange() {
if (pc.iceConnectionState === "completed") {
testPassed("pc is connected");
track = stream.getAudioTracks()[0];
shouldThrow('dtmfsender = pc.createDTMFSender(null);');
shouldThrow('dtmfsender = pc.createDTMFSender(track);');
pc.addStream(stream);
shouldNotThrow('dtmfsender = pc.createDTMFSender(track);');
shouldBeTrue('dtmfsender.canInsertDTMF');
dtmfsender.ontonechange = ontonechange;
dtmfsender.insertDTMF("1");
shouldBeEqualToString('dtmfsender.toneBuffer', "1");
}
}
function gotStream(s) {
stream = s;
testPassed('Stream generated.');
shouldBe('stream.getAudioTracks().length', '1');
shouldBe('stream.getVideoTracks().length', '0');
pc = new RTCPeerConnection();
pc.oniceconnectionstatechange = pc_onicechange;
}
shouldNotThrow("navigator.webkitGetUserMedia({audio:true}, gotStream, error);");
window.jsTestIsAsync = true;
window.successfullyParsed = true;
</script>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<script>
description("Tests the RTCPeerConnection Ice functionality.");
var pc = null;
var iceCandidate = null;
function onIceChange2()
{
if (pc.iceConnectionState === "closed") {
testPassed("iceConnectionState is closed.");
finishJSTest();
}
}
function addIceCandidateSuccess()
{
testPassed("addIceCandidateSuccess was called.");
pc.oniceconnectionstatechange = onIceChange2;
pc.close();
}
function addIceCandidateFailure()
{
testFailed("addIceCandidateFailure was called.");
finishJSTest();
}
function unexpectedSuccess()
{
testFailed("unexpectedSuccess was called.");
finishJSTest();
}
function expectedTypeError(error)
{
window.error = error;
shouldBe('error.name', '"TypeError"')
testPassed('expectedTypeError was called.')
}
function onIceChange1()
{
if (pc.iceConnectionState === "completed") {
testPassed("iceConnectionState is completed");
iceCandidate = new RTCIceCandidate({candidate:"nano nano"});
shouldNotThrow('pc.addIceCandidate(null).then(unexpectedSuccess, expectedTypeError);');
shouldNotThrow('pc.addIceCandidate(iceCandidate).then(addIceCandidateSuccess, addIceCandidateFailure);');
}
}
shouldNotThrow('pc = new RTCPeerConnection();');
pc.oniceconnectionstatechange = onIceChange1;
window.jsTestIsAsync = true;
window.successfullyParsed = true;
</script>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
</head>
<body>
<script>
async_test(function(t) {
const localPeerConnection = new RTCPeerConnection();
localPeerConnection.close();
let counter = 0;
window.events = [];
Promise.resolve().then(_ => events[counter++] = 1);
const iceCandidate = new RTCIceCandidate({candidate: 'nano nano'});
const unexpectedCallback = t.step_func(function() {
assert_unreached('Unexpected callback');
});
localPeerConnection.addIceCandidate(iceCandidate, unexpectedCallback, t.step_func(error => {
assert_equals(error.name, 'InvalidStateError');
assert_equals(error.toString(), 'InvalidStateError: The RTCPeerConnection\'s signalingState is \'closed\'.');
events[counter++] = 2;
}));
Promise.resolve().then(t.step_func_done(_ => {
events[counter++] = 3;
assert_array_equals(events, [1, 2, 3]);
}));
}, 'Tests closed connection execution order.');
async_test(function(t) {
const unexpectedCallback = t.step_func(function() {
assert_unreached('Unexpected callback');
});
const expectedTypeError = t.step_func(function(error) {
assert_equals(error.name, 'TypeError');
calledCallbacks.push('expectedTypeError');
});
const addIceCandidateSuccess1 = t.step_func(function() {
calledCallbacks.push('success1');
pc.addIceCandidate({candidate: 'candidate', sdpMid: 0}, addIceCandidateSuccess2, unexpectedCallback);
});
const addIceCandidateSuccess2 = t.step_func(function() {
calledCallbacks.push('success2');
pc.addIceCandidate({candidate: 'candidate', sdpMLineIndex: 0}, addIceCandidateSuccess3, unexpectedCallback);
});
const addIceCandidateSuccess3 = t.step_func(function() {
calledCallbacks.push('success3');
pc.addIceCandidate({candidate: 'candidate', sdpMid: 0, sdpMLineIndex: 0}, addIceCandidateSuccess4, unexpectedCallback);
});
const addIceCandidateSuccess4 = t.step_func(function() {
calledCallbacks.push('success4');
pc.oniceconnectionstatechange = t.step_func_done(onIceChange2);
pc.close();
});
const onIceChange1 = t.step_func(function() {
if (pc.iceConnectionState === 'completed') {
calledCallbacks.push('iceConnectionState complete');
const iceCandidate = new RTCIceCandidate({candidate: 'nano nano'});
pc.addIceCandidate(null, unexpectedCallback, unexpectedCallback).catch(expectedTypeError);
pc.addIceCandidate({candidate: 'candidate'}, unexpectedCallback, unexpectedCallback).catch(expectedTypeError);
pc.addIceCandidate(iceCandidate, null, unexpectedCallback).catch(expectedTypeError);
pc.addIceCandidate(iceCandidate, unexpectedCallback, null).catch(expectedTypeError);
pc.addIceCandidate(iceCandidate, addIceCandidateSuccess1, unexpectedCallback);
}
});
const onIceChange2 = t.step_func_done(function() {
if (pc.iceConnectionState === 'closed') {
calledCallbacks.push('iceConnectionState closed');
assert_array_equals(calledCallbacks, [
'iceConnectionState complete',
'expectedTypeError',
'expectedTypeError',
'expectedTypeError',
'expectedTypeError',
'success1',
'success2',
'success3',
'success4',
'iceConnectionState closed'
]);
}
});
const calledCallbacks = [];
const pc = new RTCPeerConnection();
pc.oniceconnectionstatechange = t.step_func(onIceChange1);
}, 'Tests the RTCPeerConnection Ice functionality.');
</script>
</body>
</html>
Tests the RTCPeerConnection lifetime.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS observationA.wasCollected is true
PASS observationB.wasCollected is false
PASS dataChannelOpen
PASS dc.send('xyzzy'); did not throw exception.
PASS dataChannelMessage
PASS successfullyParsed is true
TEST COMPLETE
......@@ -6,8 +6,11 @@
<body>
<script>
description("Tests the RTCPeerConnection lifetime.");
// This test uses Chrome internals, and is therefore not
// suitable for migrating to a Web Platform Tests - test.
var dc = null;
var dc2 = null;
function dataChannelMessage(m)
{
......@@ -18,16 +21,50 @@ function dataChannelMessage(m)
function dataChannelOpen()
{
testPassed("dataChannelOpen");
dc.onmessage = dataChannelMessage;
shouldNotThrow("dc.send('xyzzy');");
}
function connect_pcs(pc_a, pc_b) {
pc_a.onicecandiate = function(event) {
if (event.candidate) {
pc_b.addIceCandidate(event.candidate);
}
}
pc_b.onicecandidate = function(event) {
if (event.candidate) {
pc_a.addIceCandidate(event.candidate);
}
}
pc_a.createOffer()
.then(function(offer) {
return pc_a.setLocalDescription(offer);
})
.then(function() {
return pc_b.setRemoteDescription(pc_a.localDescription);
})
.then(function() {
return pc_b.createAnswer();
})
.then(function(answer) {
return pc_b.setLocalDescription(answer);
})
.then(function() {
return pc_a.setRemoteDescription(pc_b.localDescription);
});
}
function createPeerConnectionAndDataChannel()
{
// The Peer Connection object is leaked
var pc = new RTCPeerConnection();
var pc2 = new RTCPeerConnection();
dc = pc.createDataChannel("label");
dc.onopen = dataChannelOpen;
pc2.ondatachannel = function(e) {
dc2 = e.channel;
dc2.onmessage = dataChannelMessage;
};
connect_pcs(pc, pc2);
}
var pcB = null;
......
......@@ -7,86 +7,86 @@
</head>
<body>
<script>
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let eventSequence = [];
return createStreams({audio:true, video:false}, 1)
.then(function(streams) {
pc.addStream(streams[0]);
let resolvers = Resolver.createResolvers(2);
pc.ontrack = function() {
pc2.ontrack = function() {
eventSequence.push('ontrack');
resolvers.shift().resolve();
}
setRemoteDescriptionRemoteStreamsMatchLocal(pc).then(function() {
createAndSetRemoteDescription(pc, pc2).then(function() {
eventSequence.push('setRemoteDescription');
resolvers.shift().resolve();
});
return Promise.all(Resolver.promises(resolvers));
}).then(function() {
// TODO(hbos): We might want to change this so that track events fire
// before the promise is resolved, see spec discussion
// https://github.com/w3c/webrtc-pc/issues/1508.
let expectedEventSequence = [ 'setRemoteDescription',
'ontrack' ];
assert_array_equals(eventSequence, expectedEventSequence);
let expectedEventSequence = [ 'setRemoteDescription', 'ontrack' ];
assert_array_equals(expectedEventSequence, eventSequence);
});
}, 'ontrack fires after setRemoteDescription is resolved.');
}, 'ontrack fires before negotiation done.');
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let eventSequence = [];
return createStreams({audio:true, video:false}, 1)
.then(function(streams) {
pc.addStream(streams[0]);
let resolvers = Resolver.createResolvers(2);
pc.onaddstream = function() {
pc2.onaddstream = function() {
eventSequence.push('onaddstream');
resolvers.shift().resolve();
}
setRemoteDescriptionRemoteStreamsMatchLocal(pc).then(function() {
createAndSetRemoteDescription(pc, pc2).then(function() {
eventSequence.push('setRemoteDescription');
resolvers.shift().resolve();
});
return Promise.all(Resolver.promises(resolvers));
}).then(function() {
let expectedEventSequence = [ 'setRemoteDescription',
'onaddstream' ];
let expectedEventSequence = [ 'setRemoteDescription', 'onaddstream' ];
assert_array_equals(eventSequence, expectedEventSequence);
});
}, 'onaddstream fires after setRemoteDescription is resolved.');
}, 'onaddstream fires before negotation done.');
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let eventSequence = [];
return createStreams({audio:true, video:false}, 2)
.then(function(streams) {
pc.addStream(streams[0]);
pc.addStream(streams[1]);
let resolvers = Resolver.createResolvers(4);
pc.onaddstream = function(event) {
pc2.onaddstream = function(event) {
eventSequence.push('stream:' + event.stream.id);
resolvers.shift().resolve();
};
pc.ontrack = function(event) {
pc2.ontrack = function(event) {
eventSequence.push('track:' + event.track.id);
resolvers.shift().resolve();
};
return Promise.all(
Resolver.promises(resolvers).concat(
setRemoteDescriptionRemoteStreamsMatchLocal(pc)));
createAndSetRemoteDescription(pc, pc2)));
}).then(function() {
let expectedEventSequence =
[ 'stream:' + pc.getRemoteStreams()[0].id,
'track:' + pc.getRemoteStreams()[0].getAudioTracks()[0].id,
'stream:' + pc.getRemoteStreams()[1].id,
'track:' + pc.getRemoteStreams()[1].getAudioTracks()[0].id ];
[ 'stream:' + pc2.getRemoteStreams()[0].id,
'track:' + pc2.getRemoteStreams()[0].getAudioTracks()[0].id,
'stream:' + pc2.getRemoteStreams()[1].id,
'track:' + pc2.getRemoteStreams()[1].getAudioTracks()[0].id ];
assert_array_equals(eventSequence, expectedEventSequence);
});
}, 'ontrack and onaddstream fires in the expected relative order.');
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let eventSequence = [];
return createStreams({audio:true, video:false}, 1)
.then(function(streams) {
......@@ -102,76 +102,80 @@ promise_test(function() {
eventSequence.push('track or stream fired');
resolvers.shift().resolve();
}
pc.onaddstream = callback;
pc.ontrack = callback;
pc2.onaddstream = callback;
pc2.ontrack = callback;
return Promise.all(
Resolver.promises(resolvers).concat(
setRemoteDescriptionRemoteStreamsMatchLocal(pc)));
createAndSetRemoteDescription(pc, pc2)));
}).then(function() {
assert_array_equals(
eventSequence,
[ 'track or stream fired', 'track or stream fired', 'new task' ]);
[ 'track or stream fired', 'track or stream fired', 'new task' ]);
});
}, 'ontrack and onaddstream fires in the same task.');
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
return createStreams({audio:true, video:false}, 1)
.then(function(streams) {
pc.addStream(streams[0]);
let resolver = new Resolver();
pc.ontrack = function(event) {
let remoteStream = pc.getRemoteStreams()[0];
pc2.ontrack = function(event) {
let remoteStream = pc2.getRemoteStreams()[0];
let remoteAudioTrack = remoteStream.getAudioTracks()[0];
assert_equals(event.track, remoteAudioTrack);
resolver.resolve();
};
return Promise.all([ resolver.promise,
setRemoteDescriptionRemoteStreamsMatchLocal(pc) ]);
createAndSetRemoteDescription(pc, pc2) ]);
});
}, 'ontrack event\'s track matches track in getRemoteStreams().');
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
return createStreams({audio:true, video:false}, 1)
.then(function(streams) {
pc.addStream(streams[0]);
let resolver = new Resolver();
pc.ontrack = function(event) {
let receiver = pc.getReceivers()[0];
pc2.ontrack = function(event) {
let receiver = pc2.getReceivers()[0];
assert_equals(event.receiver, receiver);
resolver.resolve();
};
return Promise.all([ resolver.promise,
setRemoteDescriptionRemoteStreamsMatchLocal(pc) ]);
createAndSetRemoteDescription(pc, pc2) ]);
});
}, 'ontrack event\'s receiver matches getReceivers().');
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
return createStreams({audio:true, video:false}, 1)
.then(function(streams) {
pc.addStream(streams[0]);
let resolver = new Resolver();
pc.ontrack = function(event) {
assert_array_equals(event.streams, pc.getRemoteStreams())
pc2.ontrack = function(event) {
assert_array_equals(event.streams, pc2.getRemoteStreams())
resolver.resolve();
};
return Promise.all([ resolver.promise,
setRemoteDescriptionRemoteStreamsMatchLocal(pc) ]);
createAndSetRemoteDescription(pc, pc2) ]);
});
}, 'ontrack event\'s streams match getRemoteStreams().');
promise_test(function() {
let pc = new RTCPeerConnection();
let pc2 = new RTCPeerConnection();
let firedForAudioTrack = false;
let firedForVideoTrack = false;
return createStreams({audio:true, video:true}, 1)
.then(function(streams) {
pc.addStream(streams[0]);
let resolvers = Resolver.createResolvers(2);
pc.ontrack = function(event) {
let remoteStream = pc.getRemoteStreams()[0];
pc2.ontrack = function(event) {
let remoteStream = pc2.getRemoteStreams()[0];
if (event.track == remoteStream.getAudioTracks()[0])
firedForAudioTrack = true;
else if (event.track == remoteStream.getVideoTracks()[0])
......@@ -180,7 +184,7 @@ promise_test(function() {
};
return Promise.all(
Resolver.promises(resolvers).concat(
setRemoteDescriptionRemoteStreamsMatchLocal(pc)));
createAndSetRemoteDescription(pc, pc2)));
}).then(function() {
assert_true(firedForAudioTrack && firedForVideoTrack);
});
......@@ -203,18 +207,15 @@ function createStreams(constraints, numStreams, streamsSoFar = []) {
}
/**
* Makes the peer connection's remote streams match its local streams. New local
* streams result in cloning, removed local streams result in removing the
* corresponding remote stream.
*
* Returns a promise.
* Makes the setup step necessary to cause pc_b to emit events.
* Note: This does not set up a connection.
* Returns the promise resulting from pc_b.setRemoteDescription.
*/
function setRemoteDescriptionRemoteStreamsMatchLocal(pc) {
// In LayoutTests a |MockWebRTCPeerConnectionHandler| is used and as such we
// cannot establish a real call. Instead we rely on the mock making remote
// streams match the local streams on |setRemoteDescription|.
return pc.setRemoteDescription(
new RTCSessionDescription({type:'answer', sdp:'remote'}));
function createAndSetRemoteDescription(pc_a, pc_b) {
return pc_a.createOffer()
.then(function(offer) {
return pc_b.setRemoteDescription(offer);
})
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment