1+ #!/usr/bin/env python3
2+
3+ import subprocess
4+ import re
5+ import os
6+
7+ def run_tests ():
8+ """Run the tests and return the output"""
9+ result = subprocess .run (
10+ ['go' , 'test' , '-v' , './enginetest' , '-run' , 'TestQueryPlans' , '-count=1' ],
11+ cwd = '/Users/amx/dolt_workspace/go-mysql-server' ,
12+ capture_output = True ,
13+ text = True
14+ )
15+ return result .stdout + result .stderr
16+
17+ def extract_failures (output ):
18+ """Extract expected and actual values from test output"""
19+ failures = []
20+
21+ # Find all "Not equal:" sections
22+ sections = re .split (r'Not equal:' , output )
23+
24+ for section in sections [1 :]: # Skip first empty section
25+ # Look for expected and actual strings
26+ expected_match = re .search (r'expected:\s*"([^"]*(?:\\.[^"]*)*)"' , section , re .DOTALL )
27+ actual_match = re .search (r'actual\s*:\s*"([^"]*(?:\\.[^"]*)*)"' , section , re .DOTALL )
28+
29+ if expected_match and actual_match :
30+ expected = expected_match .group (1 )
31+ actual = actual_match .group (1 )
32+
33+ # Unescape the strings
34+ expected = expected .replace ('\\ n' , '\n ' ).replace ('\\ "' , '"' ).replace ('\\ \\ ' , '\\ ' )
35+ actual = actual .replace ('\\ n' , '\n ' ).replace ('\\ "' , '"' ).replace ('\\ \\ ' , '\\ ' )
36+
37+ failures .append ((expected , actual ))
38+
39+ return failures
40+
41+ def update_file (file_path , failures ):
42+ """Update the file by replacing expected with actual"""
43+ with open (file_path , 'r' ) as f :
44+ content = f .read ()
45+
46+ original_content = content
47+ update_count = 0
48+
49+ for i , (expected , actual ) in enumerate (failures ):
50+ print (f"Processing failure { i + 1 } /{ len (failures )} ..." )
51+
52+ # Create properly escaped Go string literals
53+ expected_escaped = expected .replace ('\\ ' , '\\ \\ ' ).replace ('"' , '\\ "' ).replace ('\n ' , '\\ n' )
54+ actual_escaped = actual .replace ('\\ ' , '\\ \\ ' ).replace ('"' , '\\ "' ).replace ('\n ' , '\\ n' )
55+
56+ # Look for the exact quoted string in the file
57+ search_for = f'"{ expected_escaped } "'
58+ replace_with = f'"{ actual_escaped } "'
59+
60+ # Count how many times this pattern appears
61+ count = content .count (search_for )
62+ if count > 0 :
63+ content = content .replace (search_for , replace_with )
64+ update_count += count
65+ print (f" ✓ Replaced { count } occurrence(s)" )
66+ else :
67+ # Try to find a unique substring to help debug
68+ lines = expected .split ('\n ' )
69+ for line in lines [:3 ]: # Check first few lines
70+ line = line .strip ()
71+ if line and len (line ) > 15 : # Look for substantial lines
72+ line_escaped = line .replace ('\\ ' , '\\ \\ ' ).replace ('"' , '\\ "' )
73+ if line_escaped in content :
74+ print (f" Found line '{ line [:50 ]} ...' in file but couldn't match full string" )
75+ break
76+ else :
77+ print (f" ✗ Could not find any part of expected string in file" )
78+ # Print first few lines for debugging
79+ exp_lines = expected .split ('\n ' )[:3 ]
80+ print (f" Expected starts with: { exp_lines } " )
81+
82+ if update_count > 0 :
83+ with open (file_path , 'w' ) as f :
84+ f .write (content )
85+
86+ return update_count
87+
88+ def main ():
89+ query_plans_file = '/Users/amx/dolt_workspace/go-mysql-server/enginetest/queries/query_plans.go'
90+
91+ print ("Running tests to get failures..." )
92+ output = run_tests ()
93+
94+ print ("Extracting failures..." )
95+ failures = extract_failures (output )
96+
97+ if not failures :
98+ print ("No failures found to update" )
99+ return
100+
101+ print (f"Found { len (failures )} test failures" )
102+
103+ # Update the file
104+ print (f"Updating { query_plans_file } ..." )
105+ update_count = update_file (query_plans_file , failures )
106+
107+ print (f"\n Made { update_count } total replacements" )
108+
109+ # Run tests again to check improvement
110+ print ("\n Running tests again to check progress..." )
111+ output2 = run_tests ()
112+
113+ if 'FAIL' not in output2 :
114+ print ("✓ All tests now pass!" )
115+ else :
116+ failures2 = extract_failures (output2 )
117+ improvement = len (failures ) - len (failures2 )
118+ print (f"Failures: { len (failures )} → { len (failures2 )} (improved by { improvement } )" )
119+
120+ if __name__ == "__main__" :
121+ main ()
0 commit comments