s3: tests: Add new test_stream_dir_rename.sh test.
[Samba.git] / script / bisect-test.py
blob7c5cd635f58f033c653196e11f6d2e9b3d811e90
1 #!/usr/bin/env python3
2 # use git bisect to work out what commit caused a test failure
3 # Copyright Andrew Tridgell 2010
4 # released under GNU GPL v3 or later
7 from subprocess import call, check_call, Popen, PIPE
8 import os
9 import tempfile
10 import sys
11 from optparse import OptionParser
13 parser = OptionParser()
14 parser.add_option("", "--good", help="known good revision (default HEAD~100)", default='HEAD~100')
15 parser.add_option("", "--bad", help="known bad revision (default HEAD)", default='HEAD')
16 parser.add_option("", "--skip-build-errors", help="skip revision where make fails",
17 action='store_true', default=False)
18 parser.add_option("", "--autogen", help="run autogen before each build", action="store_true", default=False)
19 parser.add_option("", "--autogen-command", help="command to use for autogen (default ./autogen.sh)",
20 type='str', default="./autogen.sh")
21 parser.add_option("", "--configure", help="run configure.developer before each build",
22 action="store_true", default=False)
23 parser.add_option("", "--configure-command", help="the command for configure (default ./configure.developer)",
24 type='str', default="./configure.developer")
25 parser.add_option("", "--build-command", help="the command to build the tree (default 'make -j')",
26 type='str', default="make -j")
27 parser.add_option("", "--test-command", help="the command to test the tree (default 'make test')",
28 type='str', default="make test")
29 parser.add_option("", "--clean", help="run make clean before each build",
30 action="store_true", default=False)
33 (opts, args) = parser.parse_args()
36 def run_cmd(cmd, dir=".", show=True, output=False, checkfail=True):
37 if show:
38 print("Running: '%s' in '%s'" % (cmd, dir))
39 if output:
40 return Popen([cmd], shell=True, stdout=PIPE, cwd=dir).communicate()[0]
41 elif checkfail:
42 return check_call(cmd, shell=True, cwd=dir)
43 else:
44 return call(cmd, shell=True, cwd=dir)
47 def find_git_root():
48 '''get to the top of the git repo'''
49 p = os.getcwd()
50 while p != '/':
51 if os.path.exists(os.path.join(p, ".git")):
52 return p
53 p = os.path.abspath(os.path.join(p, '..'))
54 return None
57 cwd = os.getcwd()
58 gitroot = find_git_root()
60 # create a bisect script
61 f = tempfile.NamedTemporaryFile(delete=False, mode="w+t")
62 f.write("set -x\n")
63 f.write("cd %s || exit 125\n" % cwd)
64 if opts.autogen:
65 f.write("%s || exit 125\n" % opts.autogen_command)
66 if opts.configure:
67 f.write("%s || exit 125\n" % opts.configure_command)
68 if opts.clean:
69 f.write("make clean || exit 125\n")
70 if opts.skip_build_errors:
71 build_err = 125
72 else:
73 build_err = 1
74 f.write("%s || exit %u\n" % (opts.build_command, build_err))
75 f.write("%s || exit 1\n" % opts.test_command)
76 f.write("exit 0\n")
77 f.close()
80 def cleanup():
81 run_cmd("git bisect reset", dir=gitroot)
82 os.unlink(f.name)
83 sys.exit(-1)
86 # run bisect
87 ret = -1
88 try:
89 run_cmd("git bisect reset", dir=gitroot, show=False, checkfail=False)
90 run_cmd("git bisect start %s %s --" % (opts.bad, opts.good), dir=gitroot)
91 ret = run_cmd("git bisect run bash %s" % f.name, dir=gitroot, show=True, checkfail=False)
92 except KeyboardInterrupt:
93 print("Cleaning up")
94 cleanup()
95 except Exception as reason:
96 print("Failed bisect: %s" % reason)
97 cleanup()
99 run_cmd("git bisect reset", dir=gitroot)
100 os.unlink(f.name)
101 sys.exit(ret)