| # 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()) |