1#!/usr/bin/python 2 3""" 4This configures and builds with many different sub-configurations 5in an attempt to flush out missing feature macro checks, etc. 6 7There is probably no reason for you to run this. Unless you want to. 8 9(C) 2017 Jack Lloyd 10 11Botan is released under the Simplified BSD License (see license.txt) 12""" 13 14import optparse # pylint: disable=deprecated-module 15import sys 16import subprocess 17 18def get_module_list(configure_py): 19 configure = subprocess.Popen([configure_py, '--list-modules'], stdout=subprocess.PIPE) 20 21 (stdout, _) = configure.communicate() 22 23 if configure.returncode != 0: 24 raise Exception("Running configure.py --list-modules failed") 25 26 modules = [s.decode('ascii') for s in stdout.split()] 27 modules.remove('tpm') # can't test 28 modules.remove('base') # can't remove 29 return modules 30 31def get_concurrency(): 32 def_concurrency = 2 33 34 try: 35 import multiprocessing 36 return max(def_concurrency, multiprocessing.cpu_count()) 37 except ImportError: 38 return def_concurrency 39 40def try_to_run(cmdline): 41 print("Running %s ... " % (' '.join(cmdline))) 42 sys.stdout.flush() 43 44 cmd = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 45 (stdout, stderr) = cmd.communicate() 46 47 failed = (cmd.returncode != 0) 48 49 if failed: 50 print("FAILURE") 51 print(stdout) 52 print(stderr) 53 sys.stdout.flush() 54 55 return not failed 56 57def run_test_build(configure_py, modules, include, jobs, run_tests): 58 config = [configure_py, '--without-documentation'] 59 60 if include: 61 config.append('--minimized') 62 if modules: 63 config.append('--enable-modules=' + ','.join(modules)) 64 else: 65 config.append('--disable-modules=' + ','.join(modules)) 66 67 if try_to_run(config) is False: 68 return False 69 70 if try_to_run(['make', '-j', str(jobs)]) is False: 71 return False 72 73 if run_tests is False: 74 return True 75 76 # Flaky test causing errors when running tests 77 tests_to_skip = [] 78 79 cmdline = ['./botan-test', '--test-threads=%d' % (jobs)] 80 81 if len(tests_to_skip) > 0: 82 cmdline.append('--skip-tests=%s' % (','.join(tests_to_skip))) 83 84 return try_to_run(cmdline) 85 86def main(args): 87 88 # TODO take configure.py and botan-test paths via options 89 90 parser = optparse.OptionParser() 91 92 parser.add_option('--run-tests', default=False, action='store_true') 93 parser.add_option('--jobs', default=get_concurrency(), 94 help="jobs to run (default %default)") 95 96 (options, args) = parser.parse_args(args) 97 98 run_tests = options.run_tests 99 jobs = int(options.jobs) 100 101 configure_py = './configure.py' 102 modules = get_module_list(configure_py) 103 104 cant_disable = ['block', 'hash', 'hex', 'mac', 'modes', 'rng', 'stream', 'utils', 'cpuid', 'entropy'] 105 always_include = ['thread_utils', 'sha2_64']#, 'sha2_64', 'aes'] 106 107 fails = 0 108 failed = [] 109 110 for module in sorted(modules): 111 if (module in always_include) or (module in cant_disable): 112 continue # already testing it 113 114 extra = [] 115 if module == 'auto_rng': 116 extra.append('dev_random') 117 if run_test_build(configure_py, [module] + always_include + extra, True, jobs, run_tests) is False: 118 failed.append(module) 119 fails += 1 120 121 for module in sorted(modules): 122 if module in cant_disable or module in always_include: 123 continue 124 if run_test_build(configure_py, [module], False, jobs, run_tests) is False: 125 failed.append(module) 126 fails += 1 127 128 if len(failed) > 0: 129 print("Failed building with %s" % (' '.join(failed))) 130 else: 131 print("All configurations ok") 132 133 return fails 134 135if __name__ == '__main__': 136 sys.exit(main(sys.argv)) 137