| # Copyright 2017 The Emscripten Authors. All rights reserved. |
| # Emscripten is available under two separate licenses, the MIT license and the |
| # University of Illinois/NCSA Open Source License. Both these licenses can be |
| # found in the LICENSE file. |
| |
| ''' |
| 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 |
| ''' |
| |
| from __future__ import print_function |
| 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 = [line for line in ret.split('\n') if not line.startswith(' at ') and not name in line] |
| 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, end=' ') |
| 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)) |
| |