@@ -34,6 +34,12 @@ def print_vals(vals, name="Values"):
3434 """Print an array of floats."""
3535 print (name + ': ' + ', ' .join ('{:f}' .format (v ) for v in vals ))
3636
37+ def is_float (test_string ):
38+ try :
39+ float (test_string )
40+ return True
41+ except ValueError :
42+ return False
3743
3844class TestCase :
3945
@@ -104,6 +110,8 @@ def __init__(self,tag_in):
104110 self .command = self .Command ()
105111 self .timeout = 0
106112 self .tol = 0.0
113+ self .tol_file_percent = 0.0
114+ self .comp_threshold = 0.0
107115
108116 # Options for file-comparison tests
109117 self .reference_file = "of_grad.dat.ref"
@@ -313,6 +321,7 @@ def run_filediff(self):
313321 print ("Output from the failed case:" )
314322 subprocess .call (["cat" , logfilename ])
315323
324+ diff_time_start = datetime .datetime .now ()
316325 if not timed_out and passed :
317326 # Compare files
318327 fromfile = self .reference_file
@@ -325,7 +334,90 @@ def run_filediff(self):
325334 try :
326335 todate = time .ctime (os .stat (tofile ).st_mtime )
327336 tolines = open (tofile , 'U' ).readlines ()
328- diff = list (difflib .unified_diff (fromlines , tolines , fromfile , tofile , fromdate , todate ))
337+
338+ # If file tolerance is set to 0, make regular diff
339+ if self .tol_file_percent == 0.0 :
340+ diff = list (difflib .unified_diff (fromlines , tolines , fromfile , tofile , fromdate , todate ))
341+
342+ # Else test word by word with given tolerance
343+ else :
344+
345+ diff = []
346+ max_delta = 0
347+ compare_counter = 0
348+ ignore_counter = 0
349+
350+ # Assert that both files have the same number of lines
351+ if len (fromlines ) != len (tolines ):
352+ diff = ["ERROR: Number of lines in " + fromfile + " and " + tofile + " differ." ]
353+ passed = False
354+
355+ # Loop through all lines
356+ for i_line in range (0 , len (fromlines )):
357+
358+ if passed == False : break
359+
360+ # Extract next line and split it
361+ from_line = fromlines [i_line ].split ()
362+ to_line = tolines [i_line ].split ()
363+
364+ # Assert that both lines have the same number of words
365+ if len (from_line ) != len (to_line ):
366+ diff = ["ERROR: Number of words in line " + str (i_line + 1 ) + " differ." ]
367+ passed = False
368+ break
369+
370+ # Loop through all words of one line
371+ for i_word in range (0 , len (from_line )):
372+
373+ # Extract next word and strip whitespace and commas
374+ from_word = from_line [i_word ].strip ().strip (',' )
375+ to_word = to_line [i_word ].strip ().strip (',' )
376+
377+ # Assert that words are either both numeric or both non-numeric
378+ from_isfloat = is_float (from_word )
379+ to_isfloat = is_float (to_word )
380+ if from_isfloat != to_isfloat :
381+ diff = ["ERROR: File entries '" + from_word + "' and '" + to_word + "' in line " + str (i_line + 1 ) + ", word " + str (i_word + 1 ) + " differ." ]
382+ passed = False
383+ delta = 0.0
384+ max_delta = "Not applicable"
385+ break
386+
387+ # Make actual comparison
388+ # Compare floats
389+ if from_isfloat :
390+ try :
391+ # Only do a relative comparison when the threshold is met.
392+ # This is to prevent large relative differences for very small numbers.
393+ if (abs (float (from_word )) > self .comp_threshold ):
394+ delta = abs ( (float (from_word ) - float (to_word )) / float (from_word ) ) * 100
395+ compare_counter += 1
396+ else :
397+ delta = 0.0
398+ ignore_counter += 1
399+
400+ max_delta = max (max_delta , delta )
401+
402+ except ZeroDivisionError :
403+ ignore_counter += 1
404+ continue
405+
406+ # Compare non-floats
407+ else :
408+ delta = 0.0
409+ compare_counter += 1
410+ if from_word != to_word :
411+ diff = ["ERROR: File entries '" + from_word + "' and '" + to_word + "' in line " + str (i_line + 1 ) + ", word " + str (i_word + 1 ) + " differ." ]
412+ passed = False
413+ max_delta = "Not applicable"
414+ break
415+
416+ if delta > self .tol_file_percent :
417+ diff = ["ERROR: File entries '" + from_word + "' and '" + to_word + "' in line " + str (i_line + 1 ) + ", word " + str (i_word + 1 ) + " differ." ]
418+ passed = False
419+ break
420+
329421 except OSError :
330422 print ("OS error, most likely from missing reference file:" , fromfile )
331423 print ("Current working directory contents:" )
@@ -335,10 +427,6 @@ def run_filediff(self):
335427 print ("Current working directory contents:" )
336428 print (os .listdir ("." ))
337429
338-
339-
340-
341-
342430 if (diff == []):
343431 passed = True
344432 else :
@@ -349,8 +437,21 @@ def run_filediff(self):
349437 else :
350438 passed = False
351439
352- print ('CPU architecture=%s' % self .cpu_arch )
353- print ('test duration: %.2f min' % (running_time / 60.0 ))
440+ # Report results
441+ diff_time_stop = datetime .datetime .now ()
442+ diff_time = (diff_time_stop - diff_time_start ).microseconds
443+
444+ print ('CPU architecture: %s' % self .cpu_arch )
445+ print ('Test duration: %.2f min' % (running_time / 60.0 ))
446+ print ('Diff duration: %.2f sec' % (diff_time / 1e6 ))
447+ print ('Specified tolerance: ' + str (self .tol_file_percent ) + '%' )
448+ print ('Specified threshold: ' + str (self .comp_threshold ))
449+
450+ if self .tol_file_percent != 0.0 :
451+ print ('Compared entries: ' + str (compare_counter ))
452+ print ('Ignored entries: ' + str (ignore_counter ))
453+ print ('Maximum difference: ' + str (max_delta ) + '%' )
454+
354455 print ('==================== End Test: %s ====================\n ' % self .tag )
355456
356457 sys .stdout .flush ()
@@ -654,7 +755,7 @@ def run_def(self):
654755 except AttributeError : # popen.kill apparently fails on some versions of subprocess... the killall command should take care of things!
655756 pass
656757 timed_out = True
657- passed = False
758+ passed = False
658759
659760 # Examine the output
660761 f = open (logfilename ,'r' )
@@ -688,7 +789,7 @@ def run_def(self):
688789 delta_vals .append ( abs (float (data [j ])- self .test_vals [j ]) )
689790 if delta_vals [j ] > self .tol :
690791 exceed_tol = True
691- passed = False
792+ passed = False
692793 break
693794 else :
694795 iter_missing = True
0 commit comments