blob: 7bd532996ba6023f270b0d7d406aa8dbe48f78ae [file] [log] [blame]
#!/usr/bin/env python
# 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.
import random
import re
import string
import unicodedata
from common.fuzz_parameters import FillInParameter, MissingParameterException
from common.random_javascript import *
def _ArrayOfRandomRolls(num_rolls):
return str([random.random() for x in xrange(num_rolls)])
def _RandomAudioOrVideo():
roll = random.random()
if roll < 0.5:
return '{ video: true, audio:true }'
elif roll < 0.7:
return '{ video: true, audio: false }'
elif roll < 0.9:
return '{ video: false, audio: true }'
else:
return '{ video: false, audio: true }'
def _ReturnFirstArgument():
return 'function(arg) { return arg; }'
def _ReturnRandomUtf8String():
unicode_glyphs = ''.join(unichr(char) for char in xrange(0x10ffff + 1)
if unicodedata.category(unichr(char))[0] in ('LMNPSZ'))
oh_dear = random.sample(unicode_glyphs, random.randint(50, 1500))
return 'function(arg) { return "%s"; }' % ''.join(oh_dear)
def _ReturnFuzzedSdp():
return 'function(arg) { return fuzzSdp(arg); }'
def _RandomSdpTransform():
roll = random.random()
if roll < 0.1:
return _ReturnRandomUtf8String()
elif roll < 0.5:
return _ReturnFuzzedSdp()
else:
return _ReturnFirstArgument()
def _InsertRandomLocationReload(list_of_lines, num_to_insert):
length = len(list_of_lines)
assert length > num_to_insert
# Randomly choose insertion points to insert at (if
# num_to_insert == length - 1, all will be replaced).
lines_to_insert_behind = sorted(random.sample(xrange(length - 1),
num_to_insert))
result = list(list_of_lines)
num_inserted = 0
for i in lines_to_insert_behind:
# We're just guessing the indentation the reloads will be at, but that's
# just cosmetic anyway.
result.insert(num_inserted + i + 1, ' location.reload()')
num_inserted += 1
return result
def _InsertRandomLocationReloads(file_data, replace_all):
lines = file_data.split(';\n')
if replace_all:
lines = _InsertRandomLocationReload(lines, len(lines) - 1)
else:
num_lines_to_insert = random.randint(1, 3)
lines = _InsertRandomLocationReload(lines, num_lines_to_insert)
return ';\n'.join(lines)
def _InsertRandomLocationReloadsWithinMarkers(file_data,
insert_everywhere=False):
"""Inserts random location.reload() statements in the file.
We can insert statements after other statements (e.g. after ; and newline).
We only consider the text between the "reload injection markers" so that we
can avoid injecting location.reload()s into the HTML or after variable
declarations, for instance. Therefore, the markers must be present in the
file data passed into this function.
Args:
file_data: The template file data as a string.
insert_everywhere: If true, will replace at all possible injection points.
If false, we will randomly choose 1-3 injection points.
"""
start_marker = '// START_OF_POSSIBLE_INJECTED_LOCATION_RELOADS'
end_marker = '// END_OF_POSSIBLE_INJECTED_LOCATION_RELOADS'
within_markers_regex = re.compile(start_marker + '(.+)' + end_marker,
re.DOTALL)
within_markers = within_markers_regex.search(file_data)
if not within_markers:
raise MissingParameterException(
'Missing %s and/or %s in template.' % (start_marker, end_marker))
# Now insert the location.reload()s.
modified_data = _InsertRandomLocationReloads(
within_markers.group(1), insert_everywhere)
return within_markers_regex.sub(modified_data, file_data)
def Fuzz(file_data):
"""Fuzzes the passed in template."""
file_data = file_data.decode('utf-8')
# Generate a bunch of random numbers and encode them into the page. Since the
# values get hard-coded into the page the page's choices will be reproducible.
file_data = FillInParameter('ARRAY_OF_RANDOM_ROLLS',
_ArrayOfRandomRolls(500),
file_data)
# Randomly decide how to fuzz SDP data.
file_data = FillInParameter('REQUEST_AUDIO_AND_VIDEO',
_RandomAudioOrVideo(),
file_data)
file_data = FillInParameter('TRANSFORM_OFFER_SDP',
_RandomSdpTransform(),
file_data)
file_data = FillInParameter('TRANSFORM_ANSWER_SDP',
_RandomSdpTransform(),
file_data)
# Random location.reload() calls in the call sequence can be challenging for
# the code to deal with, so insert some here and there.
if random.random() < 0.3:
file_data = _InsertRandomLocationReloadsWithinMarkers(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