| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Script to generate Web Bluetooth Layout Tests that can be run in ClusterFuzz. |
| 6 |
| 7 This script uses templates in the templates/ directory to generate html files |
| 8 that can be run as Layout Tests. The script reads a template, includes files |
| 9 necessary to run as a layout test, fuzzes its parameters and saves the result in |
| 10 a new file in the directory specified when running the script. |
| 11 """ |
| 12 |
| 13 import argparse |
| 14 import glob |
| 15 import os |
| 16 import sys |
| 17 import tempfile |
| 18 import time |
| 19 |
| 20 from fuzzer_helpers import FillInParameter |
| 21 import parameter_fuzzer |
| 22 import test_case_fuzzer |
| 23 |
| 24 JS_FILES_AND_PARAMETERS = ( |
| 25 ('testharness.js', 'INCLUDE_TESTHARNESS'), |
| 26 ('testharnessreport.js', 'INCLUDE_REPORT'), |
| 27 ('bluetooth-helpers.js', 'INCLUDE_BLUETOOTH_HELPERS')) |
| 28 |
| 29 SCRIPT_PREFIX = '<script type="text/javascript">\n' |
| 30 SCRIPT_SUFFIX = '\n</script>\n' |
| 31 |
| 32 |
| 33 def _GetArguments(): |
| 34 """Parses the arguments passed when running this script. |
| 35 |
| 36 Returns: |
| 37 An argparse.Namespace object containing the arguments in sys.argv. |
| 38 """ |
| 39 parser = argparse.ArgumentParser() |
| 40 |
| 41 # Arguments used by ClusterFuzz: |
| 42 parser.add_argument('-n', '--no_of_files', type=int, required=True, |
| 43 help='The number of test cases that the fuzzer is ' |
| 44 'expected to generate') |
| 45 parser.add_argument('-i', '--input_dir', |
| 46 help='The directory containing the fuzzer\'s data ' |
| 47 'bundle.') |
| 48 parser.add_argument('-o', '--output_dir', required=True, |
| 49 help='The directory where test case files should be ' |
| 50 'written to.') |
| 51 |
| 52 parser.add_argument('--content_shell_dir', |
| 53 help='The directory of content shell. If present the ' |
| 54 'program will print a command to run the ' |
| 55 'generated test file.') |
| 56 |
| 57 return parser.parse_args() |
| 58 |
| 59 |
| 60 def FuzzTemplate(template_path, resources_path): |
| 61 """Uses a template to return a test case that can be run as a layout test. |
| 62 |
| 63 This functions reads the template in |template_path|, injects the necessary |
| 64 js files to run as a layout test and fuzzes the template's parameters to |
| 65 generate a test case. |
| 66 |
| 67 Args: |
| 68 template_path: The path to the template that will be used to generate |
| 69 a new test case. |
| 70 resources_path: Path to the js files that need to be included. |
| 71 |
| 72 Returns: |
| 73 A string containing the test case. |
| 74 """ |
| 75 print 'Generating test file based on {}'.format(template_path) |
| 76 |
| 77 # Read the template. |
| 78 template_file_handle = open(template_path) |
| 79 template_file_data = template_file_handle.read().decode('utf-8') |
| 80 template_file_handle.close() |
| 81 |
| 82 # Generate a test file based on the template. |
| 83 generated_test = test_case_fuzzer.GenerateTestFile(template_file_data) |
| 84 # Fuzz parameters. |
| 85 fuzzed_file_data = parameter_fuzzer.FuzzParameters(generated_test) |
| 86 |
| 87 # Add includes |
| 88 for (js_file_name, include_parameter) in JS_FILES_AND_PARAMETERS: |
| 89 # Read js file. |
| 90 js_file_handle = open(os.path.join(resources_path, js_file_name)) |
| 91 js_file_data = js_file_handle.read() |
| 92 js_file_handle.close() |
| 93 |
| 94 js_file_data = (SCRIPT_PREFIX + js_file_data + SCRIPT_SUFFIX) |
| 95 |
| 96 fuzzed_file_data = FillInParameter(include_parameter, |
| 97 lambda data=js_file_data: data, |
| 98 fuzzed_file_data) |
| 99 |
| 100 return fuzzed_file_data.encode('utf-8') |
| 101 |
| 102 |
| 103 def WriteTestFile(test_file_data, test_file_prefix, output_dir): |
| 104 """Creates a new file with a unique name and writes the test case to it. |
| 105 |
| 106 Args: |
| 107 test_file_data: The data to be included in the new file. |
| 108 test_file_prefix: Used as a prefix when generating a new file. |
| 109 output_dir: The directory where the new file should be created. |
| 110 |
| 111 Returns: |
| 112 A string representing the file path to access the new file. |
| 113 """ |
| 114 |
| 115 file_descriptor, file_path = tempfile.mkstemp( |
| 116 prefix=test_file_prefix, |
| 117 suffix='.html', |
| 118 dir=output_dir) |
| 119 |
| 120 with os.fdopen(file_descriptor, 'wb') as output: |
| 121 print 'Writing {} bytes to \'{}\''.format(len(test_file_data), |
| 122 file_path) |
| 123 output.write(test_file_data) |
| 124 |
| 125 return file_path |
| 126 |
| 127 |
| 128 def main(): |
| 129 args = _GetArguments() |
| 130 |
| 131 print 'Generating {} test file(s).'.format(args.no_of_files) |
| 132 print 'Writing test files to: \'{}\''.format(args.output_dir) |
| 133 if args.input_dir: |
| 134 print 'Reading data bundle from: \'{}\''.format(args.input_dir) |
| 135 |
| 136 # Get Templates |
| 137 current_path = os.path.dirname(os.path.realpath(__file__)) |
| 138 available_templates = glob.glob(os.path.join(current_path, |
| 139 'templates', |
| 140 '*.html')) |
| 141 |
| 142 # Generate Test Files |
| 143 resources_path = os.path.join(current_path, 'resources') |
| 144 start_time = time.time() |
| 145 for file_no in range(args.no_of_files): |
| 146 template_path = available_templates[file_no % len(available_templates)] |
| 147 |
| 148 test_file_data = FuzzTemplate(template_path, resources_path) |
| 149 |
| 150 # Get Test File |
| 151 template_name = os.path.splitext(os.path.basename(template_path))[0] |
| 152 test_file_name = 'fuzz-{}-{}-{}'.format(template_name, |
| 153 int(start_time), |
| 154 int(file_no)) |
| 155 |
| 156 test_file_path = WriteTestFile(test_file_data, |
| 157 test_file_name, |
| 158 args.output_dir) |
| 159 |
| 160 if args.content_shell_dir: |
| 161 print '{} --run-layout-test {}'.format(args.content_shell_dir, |
| 162 test_file_path) |
| 163 |
| 164 |
| 165 if __name__ == '__main__': |
| 166 sys.exit(main()) |
| OLD | NEW |