aboutsummaryrefslogtreecommitdiffstats
path: root/src/scripts/test_all_configs.py
blob: 208720c55d22c126abaca13c1f4cd5798e21414d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/python

"""
This configures and builds with many different sub-configurations
in an attempt to flush out missing feature macro checks, etc.

There is probably no reason for you to run this. Unless you want to.

(C) 2017 Jack Lloyd

Botan is released under the Simplified BSD License (see license.txt)
"""

import optparse # pylint: disable=deprecated-module
import sys
import subprocess

def get_module_list(configure_py):
    configure = subprocess.Popen([configure_py, '--list-modules'], stdout=subprocess.PIPE)

    (stdout, _) = configure.communicate()

    if configure.returncode != 0:
        raise Exception("Running configure.py --list-modules failed")

    modules = [s.decode('ascii') for s in stdout.split()]
    modules.remove('bearssl') # can't test
    modules.remove('tpm') # can't test
    modules.remove('base') # can't remove
    return modules

def get_concurrency():
    def_concurrency = 2

    try:
        import multiprocessing
        return max(def_concurrency, multiprocessing.cpu_count())
    except ImportError:
        return def_concurrency

def try_to_run(cmdline):
    print("Running %s ... " % (' '.join(cmdline)))
    sys.stdout.flush()

    cmd = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (stdout, stderr) = cmd.communicate()

    failed = (cmd.returncode != 0)

    if failed:
        print("FAILURE")
        print(stdout)
        print(stdout.decode('ascii'))
        print(stderr.decode('ascii'))
        sys.stdout.flush()
        #sys.exit(1)

    return not failed

def run_test_build(configure_py, modules, include, jobs, run_tests):
    config = [configure_py, '--without-documentation']

    print(modules)
    if include:
        config.append('--minimized')
        if modules:
            config.append('--enable-modules=' + ','.join(modules))
    else:
        config.append('--disable-modules=' + ','.join(modules))

    if try_to_run(config) is False:
        return False

    if try_to_run(['make', '-j', str(jobs)]) is False:
        return False

    if run_tests is False:
        return True

    return try_to_run(['./botan-test', '--test-threads=%d' % (jobs)])

def main(args):

    # TODO take configure.py and botan-test paths via options

    parser = optparse.OptionParser()

    parser.add_option('--run-tests', default=False, action='store_true')
    parser.add_option('--jobs', default=get_concurrency(),
                      help="jobs to run (default %default)")

    (options, args) = parser.parse_args(args)

    run_tests = options.run_tests
    jobs = int(options.jobs)

    configure_py = './configure.py'
    modules = get_module_list(configure_py)

    cant_disable = ['block', 'hash', 'hex', 'mac', 'modes', 'rng', 'stream', 'utils', 'cpuid', 'entropy']
    always_include = ['thread_utils', 'sha2_64']#, 'sha2_64', 'aes']

    failed = []

    for module in sorted(modules):
        if (module in always_include) or (module in cant_disable):
            continue # already testing it

        extra = []
        if module == 'auto_rng':
            extra.append('dev_random')
        if run_test_build(configure_py, [module] + always_include + extra, True, jobs, run_tests) is False:
            failed.append(module)

    for module in sorted(modules):
        if module in cant_disable or module in always_include:
            continue
        if run_test_build(configure_py, [module], False, jobs, run_tests) is False:
            failed.append(module)

    if len(failed) > 0:
        print("Failed building with %s" % (' '.join(failed)))
    else:
        print("All configurations ok")

if __name__ == '__main__':
    sys.exit(main(sys.argv))