blob: d4f2f055f3873f3a7e78b3483f300bb134b0ae35 [file] [log] [blame]
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Script to generate Web Bluetooth web tests that can be run in ClusterFuzz.
This script uses templates in the templates/ directory to generate html files
that can be run as web tests. The script reads a template, includes files
necessary to run as a web test, fuzzes its parameters and saves the result in
a new file in the directory specified when running the script.
"""
import argparse
import glob
import os
import sys
import tempfile
import time
from fuzzer_helpers import FillInParameter
import parameter_fuzzer
import test_case_fuzzer
JS_FILES_AND_PARAMETERS = (
('testharness.js', 'INCLUDE_TESTHARNESS'),
('testharnessreport.js', 'INCLUDE_REPORT'),
('bluetooth-helpers.js', 'INCLUDE_BLUETOOTH_HELPERS'))
SCRIPT_PREFIX = '<script type="text/javascript">\n'
SCRIPT_SUFFIX = '\n</script>\n'
def _GetArguments():
"""Parses the arguments passed when running this script.
Returns:
An argparse.Namespace object containing the arguments in sys.argv.
"""
parser = argparse.ArgumentParser()
# Arguments used by ClusterFuzz:
parser.add_argument('-n', '--no_of_files', type=int, required=True,
help='The number of test cases that the fuzzer is '
'expected to generate')
parser.add_argument('-i', '--input_dir',
help='The directory containing the fuzzer\'s data '
'bundle.')
parser.add_argument('-o', '--output_dir', required=True,
help='The directory where test case files should be '
'written to.')
parser.add_argument('--content_shell_dir',
help='The directory of content shell. If present the '
'program will print a command to run the '
'generated test file.')
return parser.parse_args()
def FuzzTemplate(template_path, resources_path):
"""Uses a template to return a test case that can be run as a web test.
This functions reads the template in |template_path|, injects the necessary
js files to run as a web test and fuzzes the template's parameters to
generate a test case.
Args:
template_path: The path to the template that will be used to generate
a new test case.
resources_path: Path to the js files that need to be included.
Returns:
A string containing the test case.
"""
print 'Generating test file based on {}'.format(template_path)
# Read the template.
template_file_handle = open(template_path)
template_file_data = template_file_handle.read().decode('utf-8')
template_file_handle.close()
# Generate a test file based on the template.
generated_test = test_case_fuzzer.GenerateTestFile(template_file_data)
# Fuzz parameters.
fuzzed_file_data = parameter_fuzzer.FuzzParameters(generated_test)
# Add includes
for (js_file_name, include_parameter) in JS_FILES_AND_PARAMETERS:
# Read js file.
js_file_handle = open(os.path.join(resources_path, js_file_name))
js_file_data = js_file_handle.read()
js_file_handle.close()
js_file_data = (SCRIPT_PREFIX + js_file_data + SCRIPT_SUFFIX)
fuzzed_file_data = FillInParameter(include_parameter,
lambda data=js_file_data: data,
fuzzed_file_data)
return fuzzed_file_data.encode('utf-8')
def WriteTestFile(test_file_data, test_file_prefix, output_dir):
"""Creates a new file with a unique name and writes the test case to it.
Args:
test_file_data: The data to be included in the new file.
test_file_prefix: Used as a prefix when generating a new file.
output_dir: The directory where the new file should be created.
Returns:
A string representing the file path to access the new file.
"""
file_descriptor, file_path = tempfile.mkstemp(
prefix=test_file_prefix,
suffix='.html',
dir=output_dir)
with os.fdopen(file_descriptor, 'wb') as output:
print 'Writing {} bytes to \'{}\''.format(len(test_file_data),
file_path)
output.write(test_file_data)
return file_path
def main():
args = _GetArguments()
print 'Generating {} test file(s).'.format(args.no_of_files)
print 'Writing test files to: \'{}\''.format(args.output_dir)
if args.input_dir:
print 'Reading data bundle from: \'{}\''.format(args.input_dir)
# Get Templates
current_path = os.path.dirname(os.path.realpath(__file__))
available_templates = glob.glob(os.path.join(current_path,
'templates',
'*.html'))
# Generate Test Files
resources_path = os.path.join(current_path, 'resources')
start_time = time.time()
for file_no in range(args.no_of_files):
template_path = available_templates[file_no % len(available_templates)]
test_file_data = FuzzTemplate(template_path, resources_path)
# Get Test File
template_name = os.path.splitext(os.path.basename(template_path))[0]
test_file_name = 'fuzz-{}-{}-{}'.format(template_name,
int(start_time),
int(file_no))
test_file_path = WriteTestFile(test_file_data,
test_file_name,
args.output_dir)
if args.content_shell_dir:
print '{} --run-web-tests {}'.format(args.content_shell_dir,
test_file_path)
if __name__ == '__main__':
sys.exit(main())