1+ import tempfile
2+ import os
3+
4+ def analyze_line_endings (content ):
5+ """Analyze line endings in bytes content, handling the last line correctly"""
6+ if not content :
7+ return []
8+
9+ # Split into lines but keep line endings
10+ lines = []
11+ current_pos = 0
12+ content_len = len (content )
13+
14+ while current_pos < content_len :
15+ next_lf = content .find (b'\n ' , current_pos )
16+ if next_lf == - 1 :
17+ # Last line without line ending
18+ lines .append (content [current_pos :])
19+ break
20+
21+ # Include the line ending in the line
22+ lines .append (content [current_pos :next_lf + 1 ])
23+ current_pos = next_lf + 1
24+
25+ return lines
26+
27+ def test_line_endings_case (content , expected_line_endings , test_name ):
28+ print (f"\n === Testing { test_name } ===" )
29+ print ("Input file contents (bytes):" , repr (content ))
30+
31+ # Create a temporary file with given content
32+ with tempfile .NamedTemporaryFile (mode = 'wb' , delete = False ) as f :
33+ f .write (content )
34+ temp_path = f .name
35+
36+ # Modify file using ModifyCode functionality
37+ from patchwork .steps .ModifyCode .ModifyCode import replace_code_in_file
38+ replace_code_in_file (temp_path , 1 , 2 , "new_line2" )
39+
40+ # Check resulting content
41+ with open (temp_path , 'rb' ) as f :
42+ modified_content = f .read ()
43+ print ("Modified contents (bytes):" , repr (modified_content ))
44+
45+ # Analyze line endings
46+ original_lines = analyze_line_endings (content )
47+ modified_lines = analyze_line_endings (modified_content )
48+
49+ print ("\n Line ending analysis:" )
50+ print ("Original:" )
51+ for i , line in enumerate (original_lines ):
52+ ending = "CRLF" if line .endswith (b'\r \n ' ) else "LF" if line .endswith (b'\n ' ) else "None"
53+ print (f" Line { i + 1 } : { ending } - { repr (line )} " )
54+
55+ print ("Modified:" )
56+ for i , line in enumerate (modified_lines ):
57+ ending = "CRLF" if line .endswith (b'\r \n ' ) else "LF" if line .endswith (b'\n ' ) else "None"
58+ print (f" Line { i + 1 } : { ending } - { repr (line )} " )
59+
60+ # Verify against expected line endings
61+ success = True
62+ for i , (line , expected ) in enumerate (zip (modified_lines , expected_line_endings )):
63+ actual = "CRLF" if line .endswith (b'\r \n ' ) else "LF" if line .endswith (b'\n ' ) else "None"
64+ if actual != expected :
65+ print (f"ERROR: Line { i + 1 } has { actual } ending, expected { expected } " )
66+ success = False
67+
68+ os .unlink (temp_path )
69+ return success
70+
71+ def test_new_file_case ():
72+ """Special test case for creating a new file (when file doesn't exist)"""
73+ print ("\n === Testing New File Creation ===" )
74+
75+ temp_path = os .path .join (tempfile .gettempdir (), "newfile_test.txt" )
76+ if os .path .exists (temp_path ):
77+ os .unlink (temp_path )
78+
79+ print ("Creating new file..." )
80+ from patchwork .steps .ModifyCode .ModifyCode import replace_code_in_file
81+ replace_code_in_file (temp_path , None , None , "line1\n line2\n line3\n " )
82+
83+ with open (temp_path , 'rb' ) as f :
84+ content = f .read ()
85+ print ("File contents (bytes):" , repr (content ))
86+
87+ lines = analyze_line_endings (content )
88+ print ("\n Line ending analysis:" )
89+ success = True
90+ for i , line in enumerate (lines ):
91+ ending = "CRLF" if line .endswith (b'\r \n ' ) else "LF" if line .endswith (b'\n ' ) else "None"
92+ print (f" Line { i + 1 } : { ending } - { repr (line )} " )
93+ # For new files, we expect LF endings by default
94+ if ending != "LF" :
95+ print (f"ERROR: Line { i + 1 } has { ending } ending, expected LF" )
96+ success = False
97+
98+ os .unlink (temp_path )
99+ return success
100+
101+ def run_all_tests ():
102+ test_cases = [
103+ {
104+ "name" : "CRLF file" ,
105+ "content" : b"line1\r \n line2\r \n line3\r \n " ,
106+ "expected_endings" : ["CRLF" , "CRLF" , "CRLF" ]
107+ },
108+ {
109+ "name" : "LF file" ,
110+ "content" : b"line1\n line2\n line3\n " ,
111+ "expected_endings" : ["LF" , "LF" , "LF" ]
112+ },
113+ {
114+ "name" : "Mixed line endings" ,
115+ "content" : b"line1\r \n line2\n line3\r \n " ,
116+ "expected_endings" : ["CRLF" , "CRLF" , "CRLF" ] # Should normalize to the first line ending type
117+ },
118+ {
119+ "name" : "No trailing newline CRLF" ,
120+ "content" : b"line1\r \n line2\r \n line3" , # Note: no trailing newline
121+ "expected_endings" : ["CRLF" , "CRLF" , "None" ]
122+ }
123+ ] # Close test_cases list
124+
125+ all_passed = True
126+
127+ # Run modification tests
128+ print ("\n === Running File Modification Tests ===" )
129+ for test in test_cases :
130+ success = test_line_endings_case (
131+ test ["content" ],
132+ test ["expected_endings" ],
133+ test ["name" ]
134+ )
135+ all_passed = all_passed and success
136+
137+ # Run new file creation test
138+ print ("\n === Running New File Creation Test ===" )
139+ new_file_success = test_new_file_case ()
140+ all_passed = all_passed and new_file_success
141+
142+ print ("\n === Final Test Summary ===" )
143+ print ("All tests passed!" if all_passed else "Some tests failed!" )
144+ return all_passed
145+
146+ if __name__ == "__main__" :
147+ run_all_tests ()
0 commit comments