Skip to content

Commit 7c103d8

Browse files
committed
Validate that benchmark commits contain freshly generated test harness
1 parent 11065be commit 7c103d8

File tree

3 files changed

+59
-32
lines changed

3 files changed

+59
-32
lines changed

benchmark/scripts/generate_harness/generate_harness.py

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,70 @@
1212
#
1313
# ===---------------------------------------------------------------------===//
1414

15-
# Generate CMakeLists.txt and utils/main.swift from templates.
15+
# Generate boilerplate, CMakeLists.txt and utils/main.swift from templates.
1616

1717
from __future__ import print_function
1818

19-
import glob
19+
import argparse
20+
import jinja2
2021
import os
2122
import re
2223
import subprocess
2324

24-
import jinja2
25-
2625
script_dir = os.path.dirname(os.path.realpath(__file__))
2726
perf_dir = os.path.realpath(os.path.join(script_dir, '../..'))
27+
gyb_script = os.path.realpath(os.path.join(perf_dir, '../utils/gyb'))
2828
single_source_dir = os.path.join(perf_dir, 'single-source')
2929
multi_source_dir = os.path.join(perf_dir, 'multi-source')
30+
parser = argparse.ArgumentParser()
31+
parser.add_argument("--output-dir",
32+
help="Output directory (for validation test)",
33+
default=perf_dir)
34+
args = parser.parse_args()
35+
output_dir = args.output_dir
3036

3137
template_map = {
32-
'CMakeLists.txt_template': os.path.join(perf_dir, 'CMakeLists.txt'),
33-
'main.swift_template': os.path.join(perf_dir, 'utils/main.swift')
38+
'CMakeLists.txt_template': os.path.join(output_dir, 'CMakeLists.txt'),
39+
'main.swift_template': os.path.join(output_dir, 'utils/main.swift')
3440
}
3541
ignored_run_funcs = ["Ackermann", "Fibonacci"]
3642

3743
template_loader = jinja2.FileSystemLoader(searchpath="/")
3844
template_env = jinja2.Environment(loader=template_loader, trim_blocks=True,
3945
lstrip_blocks=True)
4046

47+
def all_files(directory, extension): # matching: [directory]/**/*[extension]
48+
return [
49+
os.path.join(root, f)
50+
for root, _, files in os.walk(directory)
51+
for f in files if f.endswith(extension)
52+
]
53+
54+
def will_write(filename): # ensure path to file exists before writing
55+
print(filename)
56+
output_path = os.path.split(filename)[0]
57+
if not os.path.exists(output_path): os.makedirs(output_path)
58+
4159
if __name__ == '__main__':
42-
# Generate Your Boilerplate single-source
43-
gyb_files = glob.glob(os.path.join(single_source_dir, '*.swift.gyb'))
44-
gyb_script = os.path.realpath(os.path.join(perf_dir, '../utils/gyb'))
60+
# Generate Your Boilerplate
61+
gyb_files = all_files(perf_dir, '.swift.gyb')
4562
for f in gyb_files:
46-
print(f[:-4])
47-
subprocess.call([gyb_script, '--line-directive', '', '-o', f[:-4], f])
63+
relative_path = os.path.relpath(f[:-4], perf_dir)
64+
out_file = os.path.join(output_dir, relative_path)
65+
will_write(out_file)
66+
subprocess.call([gyb_script, '--line-directive', '', '-o', out_file, f])
4867

4968
# CMakeList single-source
50-
test_files = glob.glob(os.path.join(single_source_dir, '*.swift'))
69+
test_files = all_files(single_source_dir,'.swift')
5170
tests = sorted(os.path.basename(x).split('.')[0] for x in test_files)
5271

5372
# CMakeList multi-source
5473
class MultiSourceBench(object):
55-
5674
def __init__(self, path):
5775
self.name = os.path.basename(path)
5876
self.files = [x for x in os.listdir(path)
5977
if x.endswith('.swift')]
78+
6079
if os.path.isdir(multi_source_dir):
6180
multisource_benches = [
6281
MultiSourceBench(os.path.join(multi_source_dir, x))
@@ -75,26 +94,19 @@ def get_run_funcs(filepath):
7594
matches = re.findall(r'func run_(.*?)\(', content)
7695
return filter(lambda x: x not in ignored_run_funcs, matches)
7796

78-
def find_run_funcs(dirs):
79-
ret_run_funcs = []
80-
for d in dirs:
81-
for root, _, files in os.walk(d):
82-
for name in filter(lambda x: x.endswith('.swift'), files):
83-
run_funcs = get_run_funcs(os.path.join(root, name))
84-
ret_run_funcs.extend(run_funcs)
85-
return ret_run_funcs
86-
run_funcs = sorted(
87-
[(x, x)
88-
for x in find_run_funcs([single_source_dir, multi_source_dir])],
89-
key=lambda x: x[0]
90-
)
97+
def find_run_funcs():
98+
swift_files = all_files(perf_dir, '.swift')
99+
return [func for f in swift_files for func in get_run_funcs(f)]
100+
101+
run_funcs = [(f, f) for f in sorted(find_run_funcs())]
91102

92103
# Replace originals with files generated from templates
93104
for template_file in template_map:
94105
template_path = os.path.join(script_dir, template_file)
95106
template = template_env.get_template(template_path)
96-
print(template_map[template_file])
97-
open(template_map[template_file], 'w').write(
107+
out_file = template_map[template_file]
108+
will_write(out_file)
109+
open(out_file, 'w').write(
98110
template.render(tests=tests,
99111
multisource_benches=multisource_benches,
100112
imports=imports,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
3+
SWIFT_SRC_DIR="$1"
4+
BENCHMARK_DIR="${SWIFT_SRC_DIR}/benchmark"
5+
SCRIPT_DIR="${BENCHMARK_DIR}/scripts"
6+
TEMP_DIR="$2"
7+
8+
"${SCRIPT_DIR}/generate_harness/generate_harness.py" "--output-dir=${TEMP_DIR}"
9+
for f in $(cd "${TEMP_DIR}" && find ./ -type f); do
10+
diff "${TEMP_DIR}/${f}" "${BENCHMARK_DIR}/${f}"
11+
if [[ $? -ne 0 ]]; then
12+
exit 1
13+
fi
14+
done
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
This will just be a shell script along the lines of bug-reducer.test-sh that
2-
will generate the harness/gyb files in a temp directory and make sure that the
3-
diff to what is checked into tree is empty. Then at least we will know if
4-
someone forgets to regenerate the harness or gyb files.
1+
// RUN: rm -rfv %t
2+
// RUN: %swift_src_root/benchmarks/scripts/test_generate_harness.sh %swift_src_root %t
3+
// REQUIRES: OS=macosx
4+
// REQUIRES: asserts
5+
// REQUIRES: CMAKE_GENERATOR=Ninja

0 commit comments

Comments
 (0)