Added basic fuzzer for new API and made both work.

Added a nice mode, cleaned up.

BUG=

Review URL: https://webrtc-codereview.appspot.com/832004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2807 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
phoglund@webrtc.org 2012-09-24 07:44:02 +00:00
parent 60c741281d
commit 69d46b4821
4 changed files with 204 additions and 20 deletions

View File

@ -41,24 +41,24 @@ INCLUDE_FUZZ_SDP_JS
return offer.toSdp(); return offer.toSdp();
} }
function receiveCall(offer_sdp) { function receiveCall(offerSdp) {
gSecondConnection = new webkitPeerConnection00( gSecondConnection = new webkitPeerConnection00(
null, onIceCandidateToSecond); null, onIceCandidateToSecond);
gSecondConnection.onaddstream = onRemoteStream; gSecondConnection.onaddstream = onRemoteStream;
var parsed_offer = new SessionDescription(offer_sdp); var parsedOffer = new SessionDescription(offerSdp);
gSecondConnection.setRemoteDescription( gSecondConnection.setRemoteDescription(
webkitPeerConnection00.SDP_OFFER, parsed_offer); webkitPeerConnection00.SDP_OFFER, parsedOffer);
var answer = gSecondConnection.createAnswer( var answer = gSecondConnection.createAnswer(
offer_sdp, { has_audio: true, has_video: true }); offerSdp, { has_audio: true, has_video: true });
gSecondConnection.setLocalDescription( gSecondConnection.setLocalDescription(
webkitPeerConnection00.SDP_ANSWER, answer); webkitPeerConnection00.SDP_ANSWER, answer);
gSecondConnection.startIce(); gSecondConnection.startIce();
return answer.toSdp(); return answer.toSdp();
} }
function handleAnswer(answer_sdp) { function handleAnswer(answerSdp) {
var parsed_answer = new SessionDescription(answer_sdp); var parsed_answer = new SessionDescription(answerSdp);
gFirstConnection.setRemoteDescription( gFirstConnection.setRemoteDescription(
webkitPeerConnection00.SDP_ANSWER, parsed_answer); webkitPeerConnection00.SDP_ANSWER, parsed_answer);
gFirstConnection.startIce(); gFirstConnection.startIce();
@ -68,13 +68,13 @@ INCLUDE_FUZZ_SDP_JS
var localStreamUrl = webkitURL.createObjectURL(localStream); var localStreamUrl = webkitURL.createObjectURL(localStream);
document.getElementById('local-view').src = localStreamUrl; document.getElementById('local-view').src = localStreamUrl;
var offer_sdp = callUsingStream(localStream); var offerSdp = callUsingStream(localStream);
offer_sdp = gTransformOfferSdp(offer_sdp); offerSdp = gTransformOfferSdp(offerSdp);
var answer_sdp = receiveCall(offer_sdp); var answerSdp = receiveCall(offerSdp);
answer_sdp = gTransformAnswerSdp(answer_sdp); answerSdp = gTransformAnswerSdp(answerSdp);
console.log(offer_sdp); console.log(offerSdp);
console.log(answer_sdp); console.log(answerSdp);
handleAnswer(answer_sdp); handleAnswer(answerSdp);
} }
function onIceCandidateToFirst(candidate, more) { function onIceCandidateToFirst(candidate, more) {

View File

@ -0,0 +1,124 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<!--
Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
Use of this source code is governed by a BSD-style license
that can be found in the LICENSE file in the root of the source
tree. An additional intellectual property rights grant can be found
in the file PATENTS. All contributing project authors may
be found in the AUTHORS file in the root of the source tree.
-->
<html>
<head>
<title>WebRTC PeerConnection Fuzz Test Template</title>
INCLUDE_RANDOM_JS
INCLUDE_FUZZ_SDP_JS
<script type="text/javascript">
var gFirstConnection = null;
var gSecondConnection = null;
// Variables in caps are filled in by the fuzzer.
var gTransformOfferSdp = TRANSFORM_OFFER_SDP;
var gTransformAnswerSdp = TRANSFORM_ANSWER_SDP;
function startTest() {
navigator.webkitGetUserMedia(REQUEST_AUDIO_AND_VIDEO,
getUserMediaOkCallback,
getUserMediaFailedCallback);
}
function getUserMediaFailedCallback(error) {
console.log('getUserMedia request failed with code ' + error.code);
}
function getUserMediaOkCallback(localStream) {
var localStreamUrl = webkitURL.createObjectURL(localStream);
document.getElementById('local-view').src = localStreamUrl;
callUsingStream(localStream);
}
function callUsingStream(localStream) {
gFirstConnection = new webkitRTCPeerConnection(null, null);
gFirstConnection.onicecandidate = onIceCandidateToFirst;
gFirstConnection.addStream(localStream);
gFirstConnection.createOffer(onOfferCreated);
}
function onOfferCreated(offer) {
gFirstConnection.setLocalDescription(offer);
var offerSdp = gTransformOfferSdp(offer.sdp);
console.log("OFFER SDP MESSAGE===========================\n" + offerSdp);
receiveCall(offerSdp);
}
function receiveCall(offerSdp) {
gSecondConnection = new webkitRTCPeerConnection(null, null);
gSecondConnection.onicecandidate = onIceCandidateToSecond;
gSecondConnection.onaddstream = onRemoteStream;
var parsedOffer = new RTCSessionDescription({ type: "offer",
sdp: offerSdp });
gSecondConnection.setRemoteDescription(parsedOffer);
gSecondConnection.createAnswer(onAnswerCreated);
}
function onAnswerCreated(answer) {
gSecondConnection.setLocalDescription(answer);
answerSdp = gTransformAnswerSdp(answer.sdp);
console.log("ANSWER SDP MESSAGE===========================\n" + answerSdp);
handleAnswer(answerSdp);
}
function handleAnswer(answerSdp) {
var parsedAnswer = new RTCSessionDescription({ type: "answer",
sdp: answerSdp });
gFirstConnection.setRemoteDescription(parsedAnswer);
}
function onIceCandidateToFirst(event) {
if (event.candidate) {
var candidate = new RTCIceCandidate(event.candidate);
gSecondConnection.addIceCandidate(candidate);
}
}
function onIceCandidateToSecond(event) {
if (event.candidate) {
var candidate = new RTCIceCandidate(event.candidate);
gFirstConnection.addIceCandidate(candidate);
}
}
function onRemoteStream(e) {
var remoteStreamUrl = webkitURL.createObjectURL(e.stream);
document.getElementById('remote-view').src = remoteStreamUrl;
}
window.onload = function() {
setRandomRolls(gRandomRolls);
startTest();
}
// This variable is placed here since its value is pretty big.
var gRandomRolls = ARRAY_OF_RANDOM_ROLLS;
</script>
</head>
<body>
<table border="0">
<tr>
<td>Local Preview</td>
<td>Remote Stream</td>
</tr>
<tr>
<td><video width="320" height="240" id="local-view"
autoplay="autoplay"></video></td>
<td><video width="320" height="240" id="remote-view"
autoplay="autoplay"></video></td>
</tr>
</table>
</body>
</html>

View File

@ -7,11 +7,27 @@
# in the file PATENTS. All contributing project authors may # in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree. # be found in the AUTHORS file in the root of the source tree.
# Based on the ClusterFuzz simple fuzzer template. """Fuzzer for peerconnection.
Based on the ClusterFuzz simple fuzzer template.
I generally use it like this when developing:
./src/test/fuzz/peerconnection/fuzz_main_run.py --no_of_files=1 \
--output_dir=. --input_dir=src/test/fuzz/peerconnection/corpus/; \
cat fuzz-*; mv fuzz-* /home/phoglund/www/fuzz/fuzz.html; \
cp src/test/fuzz/peerconnection/corpus/* /home/phoglund/www/fuzz/; \
chmod a+r /home/phoglund/www/fuzz/
Add the --be_nice flag to the fuzzer to generate a page that should be able
to set up a call. If a --be_nice-generated page doesn't get a call up, the
code doesn't work with whatever version of the WebRTC spec your current version
of Chrome implements.
"""
import getopt import getopt
import os import os
import random
import sys import sys
import tempfile import tempfile
import time import time
@ -42,13 +58,31 @@ def _IncludeJsFile(js_include_to_replace, js_path, file_data):
return FillInParameter(js_include_to_replace, js_file_data, file_data) return FillInParameter(js_include_to_replace, js_file_data, file_data)
def GenerateData(): def GenerateData(be_nice):
"""Generates a html page from the template, with or without fuzzing.
Args:
be_nice: If true, we won't fuzz the data but rather produce a complete
standard-compliant file.
Returns:
A tuple (file_data, file_extension).
"""
this_scripts_path = os.path.dirname(os.path.realpath(__file__)) this_scripts_path = os.path.dirname(os.path.realpath(__file__))
corpus_path = os.path.join(this_scripts_path, 'corpus'); corpus_path = os.path.join(this_scripts_path, 'corpus');
template = _ReadFile(os.path.join(corpus_path, 'template.html')) # Choose the newest version of the API more often than the old one.
if random.random() < 0.8:
template_to_use = 'template01.html'
else:
template_to_use = 'template00.html'
template = _ReadFile(os.path.join(corpus_path, template_to_use))
file_extension = 'html' file_extension = 'html'
if be_nice:
file_data = peerconnection_fuzz.MakeWorkingFile(template)
else:
file_data = peerconnection_fuzz.Fuzz(template) file_data = peerconnection_fuzz.Fuzz(template)
# Paste the javascript code in directly since it's hard to make javascript # Paste the javascript code in directly since it's hard to make javascript
@ -69,18 +103,20 @@ if __name__ == '__main__':
no_of_files = None no_of_files = None
input_dir = None input_dir = None
output_dir = None output_dir = None
be_nice = False
optlist, args = getopt.getopt(sys.argv[1:], '', \ optlist, args = getopt.getopt(sys.argv[1:], '', \
['no_of_files=', 'output_dir=', 'input_dir=']) ['no_of_files=', 'output_dir=', 'input_dir=', 'be_nice'])
for option, value in optlist: for option, value in optlist:
if option == '--no_of_files': no_of_files = int(value) if option == '--no_of_files': no_of_files = int(value)
elif option == '--output_dir': output_dir = value elif option == '--output_dir': output_dir = value
elif option == '--input_dir': input_dir = value elif option == '--input_dir': input_dir = value
elif option == '--be_nice': be_nice = True
assert no_of_files is not None, 'Missing "--no_of_files" argument' assert no_of_files is not None, 'Missing "--no_of_files" argument'
assert output_dir is not None, 'Missing "--output_dir" argument' assert output_dir is not None, 'Missing "--output_dir" argument'
assert input_dir is not None, 'Missing "--input_dir" argument' assert input_dir is not None, 'Missing "--input_dir" argument'
for file_no in range(no_of_files): for file_no in range(no_of_files):
file_data, file_extension = GenerateData() file_data, file_extension = GenerateData(be_nice)
file_data = file_data.encode('utf-8') file_data = file_data.encode('utf-8')
file_descriptor, file_path = tempfile.mkstemp( file_descriptor, file_path = tempfile.mkstemp(
prefix='fuzz-http-%d-%d' % (start_time, file_no), prefix='fuzz-http-%d-%d' % (start_time, file_no),

View File

@ -57,6 +57,7 @@ def _RandomSdpTransform():
def Fuzz(file_data): def Fuzz(file_data):
"""Fuzzes the passed in template."""
file_data = file_data.decode('utf-8') file_data = file_data.decode('utf-8')
# Generate a bunch of random numbers and encode them into the page. Since the # Generate a bunch of random numbers and encode them into the page. Since the
@ -75,3 +76,26 @@ def Fuzz(file_data):
file_data) file_data)
return file_data return file_data
def MakeWorkingFile(file_data):
"""Fills in arguments to make a basic working file.
Used for ensuring that the basic template is standards-compliant.
"""
file_data = file_data.decode('utf-8')
file_data = FillInParameter('ARRAY_OF_RANDOM_ROLLS',
_ArrayOfRandomRolls(500),
file_data)
file_data = FillInParameter('REQUEST_AUDIO_AND_VIDEO',
'{ video: true, audio: true }',
file_data)
file_data = FillInParameter('TRANSFORM_OFFER_SDP',
_ReturnFirstArgument(),
file_data)
file_data = FillInParameter('TRANSFORM_ANSWER_SDP',
_ReturnFirstArgument(),
file_data)
return file_data