• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3# Copyright JS Foundation and other contributors, http://js.foundation
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#     http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17from __future__ import print_function
18
19import argparse
20import collections
21import hashlib
22import os
23import platform
24import subprocess
25import sys
26import settings
27
28OUTPUT_DIR = os.path.join(settings.PROJECT_DIR, 'build', 'tests')
29
30Options = collections.namedtuple('Options', ['name', 'build_args', 'test_args', 'skip'])
31Options.__new__.__defaults__ = ([], [], False)
32
33def skip_if(condition, desc):
34    return desc if condition else False
35
36OPTIONS_COMMON = ['--lto=off']
37OPTIONS_PROFILE_MIN = ['--profile=minimal']
38OPTIONS_PROFILE_ES51 = [] # NOTE: same as ['--profile=es5.1']
39OPTIONS_PROFILE_ES2015 = ['--profile=es2015-subset']
40OPTIONS_STACK_LIMIT = ['--stack-limit=96']
41OPTIONS_GC_MARK_LIMIT = ['--gc-mark-limit=16']
42OPTIONS_DEBUG = ['--debug']
43OPTIONS_SNAPSHOT = ['--snapshot-save=on', '--snapshot-exec=on', '--jerry-cmdline-snapshot=on']
44OPTIONS_UNITTESTS = ['--unittests=on', '--jerry-cmdline=off', '--error-messages=on',
45                     '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on',
46                     '--line-info=on', '--mem-stats=on']
47OPTIONS_DOCTESTS = ['--doctests=on', '--jerry-cmdline=off', '--error-messages=on',
48                    '--snapshot-save=on', '--snapshot-exec=on', '--vm-exec-stop=on']
49
50# Test options for unittests
51JERRY_UNITTESTS_OPTIONS = [
52    Options('unittests-es2015_subset',
53            OPTIONS_COMMON + OPTIONS_UNITTESTS + OPTIONS_PROFILE_ES2015),
54    Options('unittests-es2015_subset-debug',
55            OPTIONS_COMMON + OPTIONS_UNITTESTS + OPTIONS_PROFILE_ES2015 + OPTIONS_DEBUG),
56    Options('doctests-es2015_subset',
57            OPTIONS_COMMON + OPTIONS_DOCTESTS + OPTIONS_PROFILE_ES2015),
58    Options('doctests-es2015_subset-debug',
59            OPTIONS_COMMON + OPTIONS_DOCTESTS + OPTIONS_PROFILE_ES2015 + OPTIONS_DEBUG),
60    Options('unittests-es5.1',
61            OPTIONS_COMMON + OPTIONS_UNITTESTS + OPTIONS_PROFILE_ES51),
62    Options('unittests-es5.1-debug',
63            OPTIONS_COMMON + OPTIONS_UNITTESTS + OPTIONS_PROFILE_ES51 + OPTIONS_DEBUG),
64    Options('doctests-es5.1',
65            OPTIONS_COMMON + OPTIONS_DOCTESTS + OPTIONS_PROFILE_ES51),
66    Options('doctests-es5.1-debug',
67            OPTIONS_COMMON + OPTIONS_DOCTESTS + OPTIONS_PROFILE_ES51 + OPTIONS_DEBUG),
68    Options('unittests-es5.1-debug-init-fini',
69            OPTIONS_COMMON + OPTIONS_UNITTESTS + OPTIONS_PROFILE_ES51 + OPTIONS_DEBUG
70            + ['--cmake-param=-DFEATURE_INIT_FINI=ON'],
71            skip=skip_if((sys.platform == 'win32'), 'FEATURE_INIT_FINI build flag isn\'t supported on Windows,' +
72                         ' because Microsoft Visual C/C++ Compiler doesn\'t support' +
73                         ' library constructors and destructors.')),
74]
75
76# Test options for jerry-tests
77JERRY_TESTS_OPTIONS = [
78    Options('jerry_tests-es2015_subset-debug',
79            OPTIONS_COMMON + OPTIONS_PROFILE_ES2015 + OPTIONS_DEBUG + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT),
80    Options('jerry_tests-es5.1',
81            OPTIONS_COMMON + OPTIONS_PROFILE_ES51 + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT),
82    Options('jerry_tests-es5.1-snapshot',
83            OPTIONS_COMMON + OPTIONS_PROFILE_ES51 + OPTIONS_SNAPSHOT + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT,
84            ['--snapshot']),
85    Options('jerry_tests-es5.1-debug',
86            OPTIONS_COMMON + OPTIONS_PROFILE_ES51 + OPTIONS_DEBUG + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT),
87    Options('jerry_tests-es5.1-debug-snapshot',
88            OPTIONS_COMMON + OPTIONS_PROFILE_ES51 + OPTIONS_SNAPSHOT + OPTIONS_DEBUG + OPTIONS_STACK_LIMIT
89            + OPTIONS_GC_MARK_LIMIT, ['--snapshot']),
90    Options('jerry_tests-es5.1-debug-cpointer_32bit',
91            OPTIONS_COMMON + OPTIONS_PROFILE_ES51 + OPTIONS_DEBUG + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT
92            + ['--cpointer-32bit=on', '--mem-heap=1024']),
93    Options('jerry_tests-es5.1-debug-external_context',
94            OPTIONS_COMMON + OPTIONS_PROFILE_ES51 + OPTIONS_DEBUG + OPTIONS_STACK_LIMIT + OPTIONS_GC_MARK_LIMIT
95            + ['--external-context=on']),
96]
97
98# Test options for jerry-test-suite
99JERRY_TEST_SUITE_OPTIONS = JERRY_TESTS_OPTIONS[:]
100JERRY_TEST_SUITE_OPTIONS.extend([
101    Options('jerry_test_suite-minimal',
102            OPTIONS_COMMON + OPTIONS_PROFILE_MIN),
103    Options('jerry_test_suite-minimal-snapshot',
104            OPTIONS_COMMON + OPTIONS_PROFILE_MIN + OPTIONS_SNAPSHOT,
105            ['--snapshot']),
106    Options('jerry_test_suite-minimal-debug',
107            OPTIONS_COMMON + OPTIONS_PROFILE_MIN + OPTIONS_DEBUG),
108    Options('jerry_test_suite-minimal-debug-snapshot',
109            OPTIONS_COMMON + OPTIONS_PROFILE_MIN + OPTIONS_SNAPSHOT + OPTIONS_DEBUG,
110            ['--snapshot']),
111    Options('jerry_test_suite-es2015_subset',
112            OPTIONS_COMMON + OPTIONS_PROFILE_ES2015),
113    Options('jerry_test_suite-es2015_subset-snapshot',
114            OPTIONS_COMMON + OPTIONS_PROFILE_ES2015 + OPTIONS_SNAPSHOT,
115            ['--snapshot']),
116    Options('jerry_test_suite-es2015_subset-debug-snapshot',
117            OPTIONS_COMMON + OPTIONS_PROFILE_ES2015 + OPTIONS_SNAPSHOT + OPTIONS_DEBUG,
118            ['--snapshot']),
119])
120
121# Test options for test262
122TEST262_TEST_SUITE_OPTIONS = [
123    Options('test262_tests'),
124    Options('test262_tests-debug', OPTIONS_DEBUG)
125]
126
127# Test options for test262-es2015
128TEST262_ES2015_TEST_SUITE_OPTIONS = [
129    Options('test262_tests_es2015', OPTIONS_PROFILE_ES2015 + ['--line-info=on', '--error-messages=on']),
130]
131
132# Test options for jerry-debugger
133DEBUGGER_TEST_OPTIONS = [
134    Options('jerry_debugger_tests',
135            OPTIONS_DEBUG + ['--jerry-debugger=on'])
136]
137
138# Test options for buildoption-test
139JERRY_BUILDOPTIONS = [
140    Options('buildoption_test-lto',
141            ['--lto=on']),
142    Options('buildoption_test-error_messages',
143            ['--error-messages=on']),
144    Options('buildoption_test-logging',
145            ['--logging=on']),
146    Options('buildoption_test-all_in_one',
147            ['--all-in-one=on']),
148    Options('buildoption_test-valgrind',
149            ['--valgrind=on']),
150    Options('buildoption_test-mem_stats',
151            ['--mem-stats=on']),
152    Options('buildoption_test-show_opcodes',
153            ['--show-opcodes=on']),
154    Options('buildoption_test-show_regexp_opcodes',
155            ['--show-regexp-opcodes=on']),
156    Options('buildoption_test-cpointer_32bit',
157            ['--compile-flag=-m32', '--cpointer-32bit=on', '--system-allocator=on'],
158            skip=skip_if(
159                platform.system() != 'Linux' or (platform.machine() != 'i386' and platform.machine() != 'x86_64'),
160                '-m32 is only supported on x86[-64]-linux')
161           ),
162    Options('buildoption_test-no_jerry_libm',
163            ['--jerry-libm=off', '--link-lib=m'],
164            skip=skip_if((sys.platform == 'win32'), 'There is no separated libm on Windows')),
165    Options('buildoption_test-no_lcache_prophashmap',
166            ['--compile-flag=-DJERRY_LCACHE=0', '--compile-flag=-DJERRY_PROPRETY_HASHMAP=0']),
167    Options('buildoption_test-external_context',
168            ['--external-context=on']),
169    Options('buildoption_test-shared_libs',
170            ['--shared-libs=on'],
171            skip=skip_if((sys.platform == 'win32'), 'Not yet supported, link failure on Windows')),
172    Options('buildoption_test-cmdline_test',
173            ['--jerry-cmdline-test=on'],
174            skip=skip_if((sys.platform == 'win32'), 'rand() can\'t be overriden on Windows (benchmarking.c)')),
175    Options('buildoption_test-cmdline_snapshot',
176            ['--jerry-cmdline-snapshot=on']),
177    Options('buildoption_test-recursion_limit',
178            OPTIONS_STACK_LIMIT),
179    Options('buildoption_test-gc-mark_limit',
180            OPTIONS_GC_MARK_LIMIT),
181    Options('buildoption_test-single-source',
182            ['--cmake-param=-DENABLE_ALL_IN_ONE_SOURCE=ON']),
183    Options('buildoption_test-jerry-debugger',
184            ['--jerry-debugger=on']),
185]
186
187def get_arguments():
188    parser = argparse.ArgumentParser()
189    parser.add_argument('--toolchain', metavar='FILE',
190                        help='Add toolchain file')
191    parser.add_argument('-q', '--quiet', action='store_true',
192                        help='Only print out failing tests')
193    parser.add_argument('--buildoptions', metavar='LIST',
194                        help='Add a comma separated list of extra build options to each test')
195    parser.add_argument('--skip-list', metavar='LIST',
196                        help='Add a comma separated list of patterns of the excluded JS-tests')
197    parser.add_argument('--outdir', metavar='DIR', default=OUTPUT_DIR,
198                        help='Specify output directory (default: %(default)s)')
199    parser.add_argument('--check-signed-off', metavar='TYPE', nargs='?',
200                        choices=['strict', 'tolerant', 'travis'], const='strict',
201                        help='Run signed-off check (%(choices)s; default type if not given: %(const)s)')
202    parser.add_argument('--check-cppcheck', action='store_true',
203                        help='Run cppcheck')
204    parser.add_argument('--check-doxygen', action='store_true',
205                        help='Run doxygen')
206    parser.add_argument('--check-pylint', action='store_true',
207                        help='Run pylint')
208    parser.add_argument('--check-vera', action='store_true',
209                        help='Run vera check')
210    parser.add_argument('--check-license', action='store_true',
211                        help='Run license check')
212    parser.add_argument('--check-magic-strings', action='store_true',
213                        help='Run "magic string source code generator should be executed" check')
214    parser.add_argument('--jerry-debugger', action='store_true',
215                        help='Run jerry-debugger tests')
216    parser.add_argument('--jerry-tests', action='store_true',
217                        help='Run jerry-tests')
218    parser.add_argument('--jerry-test-suite', action='store_true',
219                        help='Run jerry-test-suite')
220    parser.add_argument('--test262', action='store_true',
221                        help='Run test262 - ES5.1')
222    parser.add_argument('--test262-es2015', action='store_true',
223                        help='Run test262 - ES2015')
224    parser.add_argument('--unittests', action='store_true',
225                        help='Run unittests (including doctests)')
226    parser.add_argument('--buildoption-test', action='store_true',
227                        help='Run buildoption-test')
228    parser.add_argument('--all', '--precommit', action='store_true',
229                        help='Run all tests')
230
231    if len(sys.argv) == 1:
232        parser.print_help()
233        sys.exit(1)
234
235    script_args = parser.parse_args()
236
237    return script_args
238
239BINARY_CACHE = {}
240
241TERM_NORMAL = '\033[0m'
242TERM_YELLOW = '\033[1;33m'
243TERM_BLUE = '\033[1;34m'
244TERM_RED = '\033[1;31m'
245
246def report_command(cmd_type, cmd, env=None):
247    sys.stderr.write('%s%s%s\n' % (TERM_BLUE, cmd_type, TERM_NORMAL))
248    if env is not None:
249        sys.stderr.write(''.join('%s%s=%r \\%s\n' % (TERM_BLUE, var, val, TERM_NORMAL)
250                                 for var, val in sorted(env.items())))
251    sys.stderr.write('%s%s%s\n' % (TERM_BLUE, (' \\%s\n\t%s' % (TERM_NORMAL, TERM_BLUE)).join(cmd), TERM_NORMAL))
252
253def report_skip(job):
254    sys.stderr.write('%sSkipping: %s' % (TERM_YELLOW, job.name))
255    if job.skip:
256        sys.stderr.write(' (%s)' % job.skip)
257    sys.stderr.write('%s\n' % TERM_NORMAL)
258
259def get_platform_cmd_prefix():
260    if sys.platform == 'win32':
261        return ['cmd', '/S', '/C']
262    return []
263
264def create_binary(job, options):
265    build_args = job.build_args[:]
266    if options.buildoptions:
267        for option in options.buildoptions.split(','):
268            if option not in build_args:
269                build_args.append(option)
270
271    build_cmd = get_platform_cmd_prefix()
272    build_cmd.append(settings.BUILD_SCRIPT)
273    build_cmd.extend(build_args)
274
275    build_dir_path = os.path.join(options.outdir, job.name)
276    build_cmd.append('--builddir=%s' % build_dir_path)
277
278    install_dir_path = os.path.join(build_dir_path, 'local')
279    build_cmd.append('--install=%s' % install_dir_path)
280
281    if options.toolchain:
282        build_cmd.append('--toolchain=%s' % options.toolchain)
283
284    report_command('Build command:', build_cmd)
285
286    binary_key = tuple(sorted(build_args))
287    if binary_key in BINARY_CACHE:
288        ret, build_dir_path = BINARY_CACHE[binary_key]
289        sys.stderr.write('(skipping: already built at %s with returncode %d)\n' % (build_dir_path, ret))
290        return ret, build_dir_path
291
292    try:
293        subprocess.check_output(build_cmd)
294        ret = 0
295    except subprocess.CalledProcessError as err:
296        print(err.output)
297        ret = err.returncode
298
299    BINARY_CACHE[binary_key] = (ret, build_dir_path)
300    return ret, build_dir_path
301
302def get_binary_path(build_dir_path):
303    executable_extension = '.exe' if sys.platform == 'win32' else ''
304    return os.path.join(build_dir_path, 'local', 'bin', 'jerry' + executable_extension)
305
306def hash_binary(bin_path):
307    blocksize = 65536
308    hasher = hashlib.sha1()
309    with open(bin_path, 'rb') as bin_file:
310        buf = bin_file.read(blocksize)
311        while buf:
312            hasher.update(buf)
313            buf = bin_file.read(blocksize)
314    return hasher.hexdigest()
315
316def iterate_test_runner_jobs(jobs, options):
317    tested_paths = set()
318    tested_hashes = {}
319
320    for job in jobs:
321        ret_build, build_dir_path = create_binary(job, options)
322        if ret_build:
323            yield job, ret_build, None
324
325        if build_dir_path in tested_paths:
326            sys.stderr.write('(skipping: already tested with %s)\n' % build_dir_path)
327            continue
328        else:
329            tested_paths.add(build_dir_path)
330
331        bin_path = get_binary_path(build_dir_path)
332        bin_hash = hash_binary(bin_path)
333
334        if bin_hash in tested_hashes:
335            sys.stderr.write('(skipping: already tested with equivalent %s)\n' % tested_hashes[bin_hash])
336            continue
337        else:
338            tested_hashes[bin_hash] = build_dir_path
339
340        test_cmd = get_platform_cmd_prefix()
341        test_cmd.extend([settings.TEST_RUNNER_SCRIPT, '--engine', bin_path])
342
343        yield job, ret_build, test_cmd
344
345def run_check(runnable, env=None):
346    report_command('Test command:', runnable, env=env)
347
348    if env is not None:
349        full_env = dict(os.environ)
350        full_env.update(env)
351        env = full_env
352
353    proc = subprocess.Popen(runnable, env=env)
354    proc.wait()
355    return proc.returncode
356
357def run_jerry_debugger_tests(options):
358    ret_build = ret_test = 0
359    for job in DEBUGGER_TEST_OPTIONS:
360        ret_build, build_dir_path = create_binary(job, options)
361        if ret_build:
362            print("\n%sBuild failed%s\n" % (TERM_RED, TERM_NORMAL))
363            break
364
365        for channel in ["websocket", "rawpacket"]:
366            for test_file in os.listdir(settings.DEBUGGER_TESTS_DIR):
367                if test_file.endswith(".cmd"):
368                    test_case, _ = os.path.splitext(test_file)
369                    test_case_path = os.path.join(settings.DEBUGGER_TESTS_DIR, test_case)
370                    test_cmd = [
371                        settings.DEBUGGER_TEST_RUNNER_SCRIPT,
372                        get_binary_path(build_dir_path),
373                        channel,
374                        settings.DEBUGGER_CLIENT_SCRIPT,
375                        os.path.relpath(test_case_path, settings.PROJECT_DIR)
376                    ]
377
378                    if job.test_args:
379                        test_cmd.extend(job.test_args)
380
381                    ret_test |= run_check(test_cmd)
382
383    return ret_build | ret_test
384
385def run_jerry_tests(options):
386    ret_build = ret_test = 0
387    for job, ret_build, test_cmd in iterate_test_runner_jobs(JERRY_TESTS_OPTIONS, options):
388        if ret_build:
389            break
390
391        test_cmd.append('--test-dir')
392        test_cmd.append(settings.JERRY_TESTS_DIR)
393
394        if options.quiet:
395            test_cmd.append("-q")
396
397        skip_list = []
398
399        if '--profile=es2015-subset' in job.build_args:
400            skip_list.append(os.path.join('es5.1', ''))
401        else:
402            skip_list.append(os.path.join('es2015', ''))
403
404        if options.skip_list:
405            skip_list.append(options.skip_list)
406
407        if skip_list:
408            test_cmd.append("--skip-list=" + ",".join(skip_list))
409
410        if job.test_args:
411            test_cmd.extend(job.test_args)
412
413        ret_test |= run_check(test_cmd, env=dict(TZ='UTC'))
414
415    return ret_build | ret_test
416
417def run_jerry_test_suite(options):
418    ret_build = ret_test = 0
419    for job, ret_build, test_cmd in iterate_test_runner_jobs(JERRY_TEST_SUITE_OPTIONS, options):
420        if ret_build:
421            break
422
423        skip_list = []
424
425        if '--profile=minimal' in job.build_args:
426            test_cmd.append('--test-list')
427            test_cmd.append(settings.JERRY_TEST_SUITE_MINIMAL_LIST)
428        else:
429            test_cmd.append('--test-dir')
430            test_cmd.append(settings.JERRY_TEST_SUITE_DIR)
431            if '--profile=es2015-subset' in job.build_args:
432                skip_list.append(os.path.join('es5.1', ''))
433            else:
434                skip_list.append(os.path.join('es2015', ''))
435
436        if options.quiet:
437            test_cmd.append("-q")
438
439        if options.skip_list:
440            skip_list.append(options.skip_list)
441
442        if skip_list:
443            test_cmd.append("--skip-list=" + ",".join(skip_list))
444
445        if job.test_args:
446            test_cmd.extend(job.test_args)
447
448        ret_test |= run_check(test_cmd)
449
450    return ret_build | ret_test
451
452def run_test262_test_suite(options):
453    ret_build = ret_test = 0
454
455    jobs = []
456    if options.test262:
457        jobs.extend(TEST262_TEST_SUITE_OPTIONS)
458    if options.test262_es2015:
459        jobs.extend(TEST262_ES2015_TEST_SUITE_OPTIONS)
460
461    for job in jobs:
462        ret_build, build_dir_path = create_binary(job, options)
463        if ret_build:
464            print("\n%sBuild failed%s\n" % (TERM_RED, TERM_NORMAL))
465            break
466
467        test_cmd = get_platform_cmd_prefix() + [
468            settings.TEST262_RUNNER_SCRIPT,
469            '--engine', get_binary_path(build_dir_path),
470            '--test-dir', settings.TEST262_TEST_SUITE_DIR
471        ]
472
473        if '--profile=es2015-subset' in job.build_args:
474            test_cmd.append('--es2015')
475        else:
476            test_cmd.append('--es51')
477
478        if job.test_args:
479            test_cmd.extend(job.test_args)
480
481        ret_test |= run_check(test_cmd, env=dict(TZ='America/Los_Angeles'))
482
483    return ret_build | ret_test
484
485def run_unittests(options):
486    ret_build = ret_test = 0
487    for job in JERRY_UNITTESTS_OPTIONS:
488        if job.skip:
489            report_skip(job)
490            continue
491        ret_build, build_dir_path = create_binary(job, options)
492        if ret_build:
493            print("\n%sBuild failed%s\n" % (TERM_RED, TERM_NORMAL))
494            break
495
496        if sys.platform == 'win32':
497            if "--debug" in job.build_args:
498                build_config = "Debug"
499            else:
500                build_config = "MinSizeRel"
501        else:
502            build_config = ""
503
504
505        ret_test |= run_check(
506            get_platform_cmd_prefix() +
507            [settings.UNITTEST_RUNNER_SCRIPT] +
508            [os.path.join(build_dir_path, 'tests', build_config)] +
509            (["-q"] if options.quiet else [])
510        )
511
512    return ret_build | ret_test
513
514def run_buildoption_test(options):
515    for job in JERRY_BUILDOPTIONS:
516        if job.skip:
517            report_skip(job)
518            continue
519
520        ret, _ = create_binary(job, options)
521        if ret:
522            print("\n%sBuild failed%s\n" % (TERM_RED, TERM_NORMAL))
523            break
524
525    return ret
526
527Check = collections.namedtuple('Check', ['enabled', 'runner', 'arg'])
528
529def main(options):
530    checks = [
531        Check(options.check_signed_off, run_check, [settings.SIGNED_OFF_SCRIPT]
532              + {'tolerant': ['--tolerant'], 'travis': ['--travis']}.get(options.check_signed_off, [])),
533        Check(options.check_cppcheck, run_check, [settings.CPPCHECK_SCRIPT]),
534        Check(options.check_doxygen, run_check, [settings.DOXYGEN_SCRIPT]),
535        Check(options.check_pylint, run_check, [settings.PYLINT_SCRIPT]),
536        Check(options.check_vera, run_check, [settings.VERA_SCRIPT]),
537        Check(options.check_license, run_check, [settings.LICENSE_SCRIPT]),
538        Check(options.check_magic_strings, run_check, [settings.MAGIC_STRINGS_SCRIPT]),
539        Check(options.jerry_debugger, run_jerry_debugger_tests, options),
540        Check(options.jerry_tests, run_jerry_tests, options),
541        Check(options.jerry_test_suite, run_jerry_test_suite, options),
542        Check(options.test262 or options.test262_es2015, run_test262_test_suite, options),
543        Check(options.unittests, run_unittests, options),
544        Check(options.buildoption_test, run_buildoption_test, options),
545    ]
546
547    for check in checks:
548        if check.enabled or options.all:
549            ret = check.runner(check.arg)
550            if ret:
551                sys.exit(ret)
552
553if __name__ == "__main__":
554    main(get_arguments())
555