1*36713a47SJustin Fargnoli#!/usr/bin/env python3 257196dbaSDaniel Berlin# This script is used to bisect skip and count arguments for --debug-counter. 357196dbaSDaniel Berlin# It is similar to bisect, except it understands how to increase skip and decrease count 47efbd8daSDavid Greene# 57efbd8daSDavid Greene# Typical usage: 67efbd8daSDavid Greene# 77efbd8daSDavid Greene# bisect-skip-count bisect-command.sh "%(skip)d" "%(count)d" 2>&1 | tee bisect.out 87efbd8daSDavid Greene# 97efbd8daSDavid Greene# bisect-command.sh is something like this: 107efbd8daSDavid Greene# #! /bin/bash 117efbd8daSDavid Greene# 127efbd8daSDavid Greene# skip=$1 137efbd8daSDavid Greene# count=$2 147efbd8daSDavid Greene# 157efbd8daSDavid Greene# opt -debug-counter=my-counter-skip=${skip},my-counter-count=${count} 167efbd8daSDavid Greene# ... Test output of opt and exit zero for pass, non-zero for fail 177efbd8daSDavid Greene# 187efbd8daSDavid Greene# Examine bisect.out to look for "Last good skip" and "Last good 197efbd8daSDavid Greene# count" to find the values of the counter that produce a passing 207efbd8daSDavid Greene# result. Incrementing the last good count by one or decrementing the 217efbd8daSDavid Greene# last good skip by one should produce a failure. 227efbd8daSDavid Greene# 23cfe8bedcSMikhail Maltsevfrom __future__ import print_function 2457196dbaSDaniel Berlinimport os 2557196dbaSDaniel Berlinimport sys 2657196dbaSDaniel Berlinimport argparse 2757196dbaSDaniel Berlin# This is for timeout support. Use the recommended way of import. 2857196dbaSDaniel Berlin# We do timeouts because when doing, execution testing, we have a habit 2957196dbaSDaniel Berlin# of finding variants that infinite loop 3057196dbaSDaniel Berlinif os.name == 'posix' and sys.version_info[0] < 3: 3157196dbaSDaniel Berlin import subprocess32 as subprocess 3257196dbaSDaniel Berlinelse: 3357196dbaSDaniel Berlin import subprocess 3457196dbaSDaniel Berlinparser = argparse.ArgumentParser() 3557196dbaSDaniel Berlin 3657196dbaSDaniel Berlinparser.add_argument('--skipstart', type=int, default=0) 3757196dbaSDaniel Berlinparser.add_argument('--skipend', type=int, default=(1 << 32)) 3857196dbaSDaniel Berlinparser.add_argument('--countstart', type=int, default=0) 3957196dbaSDaniel Berlinparser.add_argument('--countend', type=int, default=(1 << 32)) 4057196dbaSDaniel Berlinparser.add_argument('--timeout', type=int, default=None) 4157196dbaSDaniel Berlin# Use shell support if you need to use complex shell expressions in your command 4257196dbaSDaniel Berlinparser.add_argument('--shell', type=bool, default=False) 4357196dbaSDaniel Berlinparser.add_argument('command', nargs='+') 4457196dbaSDaniel Berlin 4557196dbaSDaniel Berlinargs = parser.parse_args() 4657196dbaSDaniel Berlin 4757196dbaSDaniel Berlinstart = args.skipstart 4857196dbaSDaniel Berlinend = args.skipend 4957196dbaSDaniel Berlin 5057196dbaSDaniel Berlinprint("Bisect of Skip starting!") 5157196dbaSDaniel Berlinprint("Start: %d" % start) 5257196dbaSDaniel Berlinprint("End: %d" % end) 5357196dbaSDaniel Berlin 5457196dbaSDaniel Berlinlast = None 5557196dbaSDaniel Berlinwhile start != end and start != end-1: 56cfe8bedcSMikhail Maltsev count = start + (end - start)//2 5757196dbaSDaniel Berlin print("Visiting Skip: %d with (Start, End) = (%d,%d)" % (count, start, end)) 5857196dbaSDaniel Berlin cmd = [x % {'skip':count, 'count':-1} for x in args.command] 59cfe8bedcSMikhail Maltsev print(cmd) 6057196dbaSDaniel Berlin try: 6157196dbaSDaniel Berlin result = subprocess.call(cmd, shell=args.shell, timeout=args.timeout) 6257196dbaSDaniel Berlin if result == 0: 6357196dbaSDaniel Berlin print(" PASSES! Setting end to count") 6457196dbaSDaniel Berlin end = count 6557196dbaSDaniel Berlin else: 6657196dbaSDaniel Berlin print(" FAILS! Setting start to count") 6757196dbaSDaniel Berlin start = count 6857196dbaSDaniel Berlin except: 6957196dbaSDaniel Berlin print(" TIMEOUT, setting end to count") 7057196dbaSDaniel Berlin end = count 7157196dbaSDaniel Berlinfirstcount = start 7257196dbaSDaniel Berlinprint("Last good skip: %d" % start) 7357196dbaSDaniel Berlinstart = args.countstart 7457196dbaSDaniel Berlinend = args.countend 7557196dbaSDaniel Berlinprint("Bisect of Count starting!") 7657196dbaSDaniel Berlinprint("Start: %d" % start) 7757196dbaSDaniel Berlinprint("End: %d" % end) 7857196dbaSDaniel Berlinwhile start != end and start != end-1: 79cfe8bedcSMikhail Maltsev count = start + (end - start)//2 8057196dbaSDaniel Berlin print("Visiting Count: %d with (Start, End) = (%d,%d)" % (count, start, end)) 8157196dbaSDaniel Berlin cmd = [x % {'count':count, 'skip':firstcount } for x in args.command] 82cfe8bedcSMikhail Maltsev print(cmd) 8357196dbaSDaniel Berlin try: 84392da4bcSDaniel Berlin result = subprocess.call(cmd, shell=args.shell, timeout=args.timeout) 8557196dbaSDaniel Berlin if result == 0: 8657196dbaSDaniel Berlin print(" PASSES! Setting start to count") 8757196dbaSDaniel Berlin start = count 8857196dbaSDaniel Berlin else: 8957196dbaSDaniel Berlin print(" FAILS! Setting end to count") 9057196dbaSDaniel Berlin end = count 9157196dbaSDaniel Berlin except: 9257196dbaSDaniel Berlin print(" TIMEOUT, setting start to count") 9357196dbaSDaniel Berlin start = count 9457196dbaSDaniel Berlin 9557196dbaSDaniel Berlinprint("Last good count: %d" % start) 96