blob: 2e2a4786752aea5b87657972691a5269fc3ff09d [file] [log] [blame]
#!/usr/bin/env python
import argparse
import os
import re
def main():
p = argparse.ArgumentParser()
p.add_argument('name', help='The name of the new benchmark to be created')
args = p.parse_args()
# adds benchmark to `CMakeLists.txt`
update_cmakelists(args.name)
# create benchmark Swift file
create_benchmark_file(args.name)
# imports the benchmark module in `main.swift`
add_import_benchmark(args.name)
# registers the benchmark with the driver in `main.swift`
add_register_benchmark(args.name)
def update_cmakelists(name):
"""Adds a new entry to the `CMakeLists.txt` file with the given
benchmark name.
"""
relative_path = create_relative_path('../CMakeLists.txt')
file_contents = []
with open(relative_path, 'r') as f:
file_contents = f.readlines()
file_new_contents = insert_line_alphabetically(
name,
' single-source/' + name + '\n',
file_contents,
r" single-source\/([a-zA-Z]+)"
)
with open(relative_path, 'w') as f:
for line in file_new_contents:
f.write(line)
def create_benchmark_file(name):
"""Creates a new Swift file with the given name based on the template
and places it in the `single-source` directory.
"""
template_path = create_relative_path('Template.swift')
benchmark_template = ''
with open(template_path, 'r') as f:
benchmark_template = ''.join(f.readlines())
# fill in template with benchmark name.
formatted_template = benchmark_template.format(name=name)
relative_path = create_relative_path('../single-source/')
source_file_path = os.path.join(relative_path, name + '.swift')
with open(source_file_path, 'w') as f:
f.write(formatted_template)
def add_import_benchmark(name):
"""Adds an `import` statement to the `main.swift` file for the new
benchmark.
"""
relative_path = create_relative_path('../utils/main.swift')
# read current contents into an array
file_contents = []
with open(relative_path, 'r') as f:
file_contents = f.readlines()
# the test dependencies are placed before all benchmarks, so we have to
# insert the benchmark in the right alphabetical order after we have seen
# all test dependencies.
read_test_dependencies = False
previous_benchmark_name = None
file_new_contents = []
for line in file_contents:
# check if this line is a definition of a benchmark and get its name
match = re.search(r"import ([a-zA-Z]+)", line)
if match and match.group(1):
benchmark_name = match.group(1)
# find where to insert the new benchmark in the right alphabetical
# order.
if (name < benchmark_name and previous_benchmark_name is None or
name < benchmark_name and name > previous_benchmark_name):
if read_test_dependencies:
file_new_contents.append('import ' + name + '\n' + line)
else:
# all test dependencies are first specified, so from now
# on we can look where to insert the new benchmark.
read_test_dependencies = True
file_new_contents.append(line)
else:
file_new_contents.append(line)
previous_benchmark_name = benchmark_name
else:
file_new_contents.append(line)
with open(relative_path, 'w') as f:
for line in file_new_contents:
f.write(line)
def add_register_benchmark(name):
"""Adds an `import` statement to the `main.swift` file for the new
benchmark.
"""
relative_path = create_relative_path('../utils/main.swift')
file_contents = []
with open(relative_path, 'r') as f:
file_contents = f.readlines()
file_new_contents = insert_line_alphabetically(
name,
'registerBenchmark(' + name + ')\n',
file_contents,
r"registerBenchmark\(([a-zA-Z]+)\)"
)
with open(relative_path, 'w') as f:
for line in file_new_contents:
f.write(line)
def insert_line_alphabetically(name, new_line, lines, regex):
"""Iterates through the given lines and executes the regex on each line to
find where the new benchmark should be inserted with the given `new_line`.
"""
# the name of the previous seen benchmark in order to insert the new
# one at the correct position
previous_benchmark_name = None
# the new contents of the file
updated_lines = []
for line in lines:
# apply regex and get name of benchmark on this line
match = re.search(regex, line)
if match and match.group(1):
benchmark_name = match.group(1)
# check if we're at the line where we have to insert the new
# benchmark in the correct alphabetical order
if (name < benchmark_name and previous_benchmark_name is None or
name < benchmark_name and name > previous_benchmark_name):
updated_lines.append(new_line + line)
else:
updated_lines.append(line)
previous_benchmark_name = benchmark_name
else:
updated_lines.append(line)
return updated_lines
def create_relative_path(file_path):
return os.path.join(os.path.dirname(__file__), file_path)
if __name__ == "__main__":
main()