add line bisector tool
This commit is contained in:
Родитель
a4ae7a1c29
Коммит
4ed0af723b
|
@ -0,0 +1,63 @@
|
|||
'''
|
||||
Given two similar files, for example one with an additional optimization pass,
|
||||
and with different results, will bisect between them to find the smallest
|
||||
diff that makes the outputs different.
|
||||
Unlike bisect_pairs, this uses lines instead of diffs. We replace line by line. This assumes
|
||||
the programs differ on each line but lines have not been added or removed
|
||||
'''
|
||||
|
||||
import os, sys, shutil
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
__rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
def path_from_root(*pathelems):
|
||||
return os.path.join(__rootpath__, *pathelems)
|
||||
exec(open(path_from_root('tools', 'shared.py'), 'r').read())
|
||||
|
||||
file1 = open(sys.argv[1]).read()
|
||||
file2 = open(sys.argv[2]).read()
|
||||
|
||||
leftf = open('left', 'w')
|
||||
leftf.write(file1)
|
||||
leftf.close()
|
||||
|
||||
rightf = open('right', 'w')
|
||||
rightf.write(file2)
|
||||
rightf.close()
|
||||
|
||||
def run_code(name):
|
||||
ret = run_js(name, stderr=PIPE, full_output=True)
|
||||
# fix stack traces
|
||||
ret = filter(lambda line: not line.startswith(' at ') and not name in line, ret.split('\n'))
|
||||
return '\n'.join(ret)
|
||||
|
||||
print 'running files'
|
||||
left_result = run_code('left')
|
||||
right_result = run_code('right') # right as in left-right, not as in correct
|
||||
assert left_result != right_result
|
||||
|
||||
low = 0
|
||||
high = file1.count('\n')
|
||||
|
||||
print 'beginning bisection, %d lines' % high
|
||||
|
||||
left_lines = file1.split('\n')
|
||||
right_lines = file2.split('\n')
|
||||
|
||||
while True:
|
||||
mid = int((low + high)/2)
|
||||
print low, high, ' current: %d' % mid,
|
||||
open('middle', 'w').write('\n'.join(left_lines[:mid] + right_lines[mid:]))
|
||||
shutil.copyfile('middle', 'middle' + str(mid))
|
||||
result = run_code('middle')
|
||||
print result == left_result, result == right_result#, 'XXX', left_result, 'YYY', result, 'ZZZ', right_result
|
||||
if mid == low or mid == high: break
|
||||
if result == right_result:
|
||||
low = mid
|
||||
elif result == left_result:
|
||||
high = mid
|
||||
else:
|
||||
raise Exception('new result!?!?')
|
||||
|
||||
print 'middle%d is like left, middle%d is like right' % (mid+1, mid)
|
||||
|
Загрузка…
Ссылка в новой задаче