@@ -162,8 +162,11 @@ def Indent(s, spaces):
162
162
163
163
164
164
def DiffLines (expected , actual ):
165
- expected_lines = [line for line in expected .splitlines () if line ]
166
- actual_lines = [line for line in actual .splitlines () if line ]
165
+ def Decode (s ):
166
+ return s .decode ('utf-8' , 'replace' )
167
+
168
+ expected_lines = [Decode (line ) for line in expected .splitlines () if line ]
169
+ actual_lines = [Decode (line ) for line in actual .splitlines () if line ]
167
170
return list (
168
171
difflib .unified_diff (expected_lines , actual_lines , fromfile = 'expected' ,
169
172
tofile = 'actual' , lineterm = '' ))
@@ -268,7 +271,7 @@ def KillProcess(timeout=True):
268
271
process = subprocess .Popen (self .args , cwd = cwd , env = env ,
269
272
stdout = None if console_out else subprocess .PIPE ,
270
273
stderr = None if console_out else subprocess .PIPE ,
271
- universal_newlines = True , ** kwargs )
274
+ ** kwargs )
272
275
timer = threading .Timer (timeout , KillProcess )
273
276
try :
274
277
timer .start ()
@@ -315,8 +318,8 @@ class TestResult(object):
315
318
316
319
def __init__ (self ):
317
320
self .results = []
318
- self .stdout = ''
319
- self .stderr = ''
321
+ self .stdout = b ''
322
+ self .stderr = b ''
320
323
self .duration = 0
321
324
322
325
def GetLastCommand (self ):
@@ -479,7 +482,8 @@ def Parse(self, filename):
479
482
self .filename = filename
480
483
481
484
test_path = os .path .join (REPO_ROOT_DIR , filename )
482
- with open (test_path ) as f :
485
+ # Read/write as binary because spec tests may have invalid UTF-8 codes.
486
+ with open (test_path , 'rb' ) as f :
483
487
state = 'header'
484
488
empty = True
485
489
header_lines = []
@@ -488,19 +492,29 @@ def Parse(self, filename):
488
492
stderr_lines = []
489
493
for line in f .readlines ():
490
494
empty = False
491
- m = re .match (r'\ s*\(;; (STDOUT|STDERR) ;;;$' , line )
495
+ m = re .match (b' \\ s*\\ (;; (STDOUT|STDERR) ;;;$' , line . strip () )
492
496
if m :
493
- directive = m .group (1 )
497
+ directive = m .group (1 ). decode ( 'utf-8' )
494
498
if directive == 'STDERR' :
495
499
state = 'stderr'
496
500
continue
497
501
elif directive == 'STDOUT' :
498
502
state = 'stdout'
499
503
continue
500
504
else :
501
- m = re .match (r' \s*;;;(.*)$' , line )
505
+ m = re .match (b' \ \ s*;;;(.*)$' , line )
502
506
if m :
503
- directive = m .group (1 ).strip ()
507
+ # The matched string has type bytes, but in python2
508
+ # that is the same as str. In python3 that needs to be
509
+ # decoded first. If we decode the string in python2 the
510
+ # result is a unicode string, which doesn't work
511
+ # everywhere (as used in a subprocess environment, for
512
+ # example).
513
+ if sys .version_info .major == 3 :
514
+ directive = m .group (1 ).decode ('utf-8' ).strip ()
515
+ else :
516
+ directive = m .group (1 ).strip ()
517
+
504
518
if state == 'header' :
505
519
key , value = directive .split (':' , 1 )
506
520
key = key .strip ()
@@ -517,7 +531,7 @@ def Parse(self, filename):
517
531
state = 'input'
518
532
519
533
if state == 'header' :
520
- header_lines .append (line )
534
+ header_lines .append (line . decode ( 'utf-8' ) )
521
535
if state == 'input' :
522
536
if self .input_filename :
523
537
raise Error ('Can\' t have STDIN_FILE and input' )
@@ -530,9 +544,9 @@ def Parse(self, filename):
530
544
raise Error ('empty test file' )
531
545
532
546
self .header = '' .join (header_lines )
533
- self .input_ = '' .join (input_lines )
534
- self .expected_stdout = '' .join (stdout_lines )
535
- self .expected_stderr = '' .join (stderr_lines )
547
+ self .input_ = b '' .join (input_lines )
548
+ self .expected_stdout = b '' .join (stdout_lines )
549
+ self .expected_stderr = b '' .join (stderr_lines )
536
550
537
551
if not self .cmds :
538
552
raise Error ('test has no commands' )
@@ -555,23 +569,23 @@ def CreateInputFile(self):
555
569
else :
556
570
# add an empty line for each header line so the line numbers match
557
571
gen_input_file .write (('\n ' * self .header .count ('\n ' )).encode ('ascii' ))
558
- gen_input_file .write (self .input_ . encode ( 'ascii' ) )
572
+ gen_input_file .write (self .input_ )
559
573
gen_input_file .flush ()
560
574
return gen_input_file .name
561
575
562
576
def Rebase (self , stdout , stderr ):
563
577
test_path = os .path .join (REPO_ROOT_DIR , self .filename )
564
578
with open (test_path , 'wb' ) as f :
565
- f .write (self .header )
579
+ f .write (self .header . encode ( 'ascii' ) )
566
580
f .write (self .input_ )
567
581
if stderr :
568
- f .write ('(;; STDERR ;;;\n ' )
582
+ f .write (b '(;; STDERR ;;;\n ' )
569
583
f .write (stderr )
570
- f .write (';;; STDERR ;;)\n ' )
584
+ f .write (b ';;; STDERR ;;)\n ' )
571
585
if stdout :
572
- f .write ('(;; STDOUT ;;;\n ' )
586
+ f .write (b '(;; STDOUT ;;;\n ' )
573
587
f .write (stdout )
574
- f .write (';;; STDOUT ;;)\n ' )
588
+ f .write (b ';;; STDOUT ;;)\n ' )
575
589
576
590
def Diff (self , stdout , stderr ):
577
591
msg = ''
0 commit comments