#! /n/local_linux/epd/bin/python2.7 # # This script will not run with /usr/local/bin/python -> python3.2 # for linux /n/local_linux/python2.5.1/bin/python # # default is now vers 3 in /usr/bin/python # for linux /n/local_linux/python2.5.1/bin/python # for mac /usr/bin/env python # for lanl machines /usr/bin/env python # for sgi /usr/lanl/bin/python # ------------------------------------------------------------------------------ # Name: check_test.py # Usage: check_test.py (all dirs) or check_test.py dir1 (list dirs) # Last Modified: Jan 2008 by TAM # # writes differences to diffout_$OS.txt # and copies file to directory result_files # # Uses difflib.py providing diffs in four formats: # Current version uses unified # # ndiff: lists every line and highlights interline changes. # context: highlights clusters of changes in a before/after format. # unified: highlights clusters of changes in an inline format. # html: generates side by side comparison with change highlights. # # ------------------------------------------------------------------------------ import fileinput, array, string, os, difflib, sys, datetime, time, copy from typing import List from .logger import log __all__ = ["fail", "rstrip", "diff_chunk", "Check"] class WFileProp(object): """ In the original LaGriT diff, there was explicit file writing. This is a dummy class to mimic file writing while retaining the benefits of not having to modify any existing syntax. """ def __init__(self): pass def write(self, *args): log.info(' '.join([str(x) for x in args])) def remove_junk_from_filestream( lines, banner="-----oOo-----", comment_chars=["#", "!", "*"] ): """ Removes comments, headers, and whitespace from a list of strings, parsed from a lagrit.out file. """ newlines = [] in_banner = False for line in lines: stripped = line.strip() if stripped == "": continue elif stripped[0] in comment_chars: continue elif banner in stripped: in_banner = not in_banner elif "log file: " in stripped: continue if not in_banner: newlines.append(stripped) return newlines[1:] # ------------------------------------------------------------------------------ def rstrip(line, JUNK="\n \t "): i = len(line) while i > 0 and line[i - 1] in JUNK: i -= 1 return line[:i] # ------------------------------------------------------------------------------ # compare using additional checks to diff def diff_chunk(rlines, tlines, rcnt, tcnt, wfile): # need large epsilon to compare numbers 1.73469E+02 to 1.734693909E+02 epsval = 0.001 tmp = [] tmp1 = [] tmp2 = [] ibad = 0 ifa = 0 ico = 0 iju = 0 count = 0 debug = 0 # -Loop over each pair of lines 0 to tcnt count = max(tcnt, rcnt) for idx in range(count): rcount = 0 tmp1 = "-" if idx < rcnt: rwords = rlines[idx].split(None) rcount = len(rwords) tmp = "-" + rlines[idx] tmp1 = tmp.rstrip() tcount = 0 tmp2 = "+" if idx < tcnt: twords = tlines[idx].split(None) tcount = len(twords) tmp = "+" + tlines[idx] tmp2 = tmp.rstrip() # for lines with same number of words, compare values word by word if tcount == rcount and tcount > 0: ibad = 0 # check to see if these are lines to skip if twords[0].find("*") > -1: ico = ico + 1 if debug: print("comment line " + repr(idx) + tlines[idx]) elif twords[0].find("#") > -1: ico = ico + 1 if debug: print("comment line " + repr(idx) + tlines[idx]) elif len(twords) < 2: iju = iju + 1 if debug: print("junk line " + repr(idx) + tlines[idx]) else: # Loop through word by word if debug: print("epsilon compare: %16.9f \n" % epsval) for i in range(len(rwords)): if rwords[i].isalpha() and twords[i].isalpha(): if rwords[i] == twords[i]: if debug: print("alpha same " + rwords[i] + " and " + twords[i]) else: if debug: print("alpha differ " + rwords[i] + " and " + twords[i]) ibad = 1 elif rwords[i].isdigit() and twords[i].isdigit(): xval = abs(float(rwords[i]) - float(twords[i])) if xval > epsval: ibad = 1 if debug: print( "digits differ by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif debug: print( "digits same by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif rwords[i].find("E+") > 0 and twords[i].find("E+") > 0: xval = abs(float(rwords[i]) - float(twords[i])) if xval > epsval: ibad = 1 if debug: print( "numbers E+ differ by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif debug: print( "numbers E+ same by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif rwords[i].find("E-") > 0 and twords[i].find("E-") > 0: xval = abs(float(rwords[i]) - float(twords[i])) if xval > epsval: ibad = 1 if debug: print( "numbers E- differ by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif debug: print( "numbers E- same by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif rwords[i].find("e+") > 0 and twords[i].find("e+") > 0: xval = abs(float(rwords[i]) - float(twords[i])) if xval > epsval: ibad = 1 if debug: print( "numbers e+ differ by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif debug: print( "numbers e+ same by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif rwords[i].find("e-") > 0 and twords[i].find("e-") > 0: xval = abs(float(rwords[i]) - float(twords[i])) if xval > epsval: ibad = 1 if debug: print( "numbers e- differ by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) elif debug: print( "numbers e- same by %16.9f , %s %s " % (xval, rwords[i], twords[i]) ) else: if rwords[i] != twords[i]: if debug: print("words differ " + rwords[i] + " and " + twords[i]) # check for -0 and 0 ibad = 1 else: if debug: print("words same " + rwords[i] + " and " + twords[i]) # Done Loop through word by word # for lines with different number of words, assume difference elif tcount != rcount and tcount > 0: if twords[0].find("*") > -1 or twords[0].find("#") > -1: ico = ico + 1 if debug: print("Comment lines differs in length") else: if debug: print("Lines differ in length") ibad = 1 # compare for test and reference pair done ifa = ifa + ibad if debug or ibad: print(tmp1 + "\n" + tmp2 + "\n") wfile.write(tmp1 + "\n" + tmp2 + "\n") if debug: print("end routine tcnt,ico,iju,ifa: ", tcnt, ico, iju, ifa) # -Done Loop over each pair of lines 0 to max(rcnt, tcnt) return ifa, ico, iju def diff(output_test: str, output_reference: str): """Computes diff between files. Args: output_test (List[str]): Output file to be tested. output_reference (List[str]): Reference output file. """ wfile = WFileProp() fromfile = output_reference tofile = output_test fromlines = tolines = None with open(fromfile, 'r', newline=None) as f: fromlines = f.readlines() with open(tofile, 'r', newline=None) as f: tolines = f.readlines() fromdate = time.ctime(os.stat(fromfile).st_mtime) todate = time.ctime(os.stat(tofile).st_mtime) # Remove comments + banner fromlines = remove_junk_from_filestream(fromlines) tolines = remove_junk_from_filestream(tolines) icomment = 0 ijunk = 0 ifail = 0 iprintatt = 0 debug = 0 JUNK = "\n \t" errList = [] errmess = [] rlines = [] tlines = [] nlines = 1 rmspace = 0 ierr = 0 ifail = 0 nfail = 0 ndirs = 0 result_dir = 0 diffcopy = "" nlines = 0 diff = difflib.unified_diff( fromlines, tolines, fromfile, tofile, fromdate, todate, nlines ) diffcopy = difflib.unified_diff( fromlines, tolines, fromfile, tofile, fromdate, todate, nlines ) # -------- # Loop through lines in diff result # write full result to diffout_*.txt, summary to screen # Check the chunk from diff formatted result # start with line @@ -lineno,chunksize +lineno,chunksize @@ # followed by chunksize number of lines # later versions of diff allow a single number # ' 'for common line -in reference file +in test file chunk = 0 for line in diff: words = line.split(None) # check to see if this is a new set of lines # if chunksize are equal, compare line pairs # otherwise print the whole chunk if words[0].find("@") > -1: oldlins = words[1].split(",") newlins = words[2].split(",") tlineno = int(newlins[0][1:]) # versions of python greater than 2.5 allow single value instead of pairs # avoid indexing number that may not exist if len(newlins) > 1: tnum = int(newlins[1]) else: tnum = 0 if len(oldlins) > 1: rnum = int(oldlins[1]) else: rnum = 0 if tnum == rnum: chdr = ( "\n" + "Test has " + repr(tnum) + " diffs at line " + repr(tlineno) + " >>" ) elif tnum > rnum: ifail = ifail + (tnum - rnum) chdr = ( "\n" + "Test has " + repr(tnum) + " diffs at line " + repr(tlineno) + " >>" ) chdr = ( chdr + "\n" + "Test has " + repr(tnum - rnum) + " extra lines in this chunk." ) elif rnum > tnum: ifail = ifail + (rnum - tnum) chdr = ( "\n" + "Test has " + repr(tnum) + " diffs at line " + repr(tlineno) + " >>" ) chdr = ( chdr + "\n" + "Test has " + repr(rnum - tnum) + " missing lines in this chunk." ) chunk = 1 nread = tnum + rnum iread = 0 rcnt = 0 tcnt = 0 if chunk == 1: # compare a chunk of line pairs output from diff # tlines are from test, rlines are from reference if line[0] == "-": rlines.append(line[1:]) rcnt = rcnt + 1 iread = iread + 1 elif line[0] == "+": tlines.append(line[1:]) tcnt = tcnt + 1 iread = iread + 1 else: if iread > 0: tmp = line.rstrip() wfile.write(tmp + "\n") # chunk has been read if chunk == 1 and iread == nread: if debug: print( "Compare chunk ===============================================" ) wfile.write(chdr + "\n") ifa, ico, iju = diff_chunk( rlines, tlines, rcnt, tcnt, wfile ) ifail = ifail + ifa icomment = icomment + ico ijunk = ijunk + iju rlines = [] tlines = [] chunk = 0 count_1 = abs(int(repr(tcnt - ifa))) count_2 = abs(int(repr(tnum))) buff = "Lines Essentially the Same: {0} out of {1}".format( min(count_1, count_2), max(count_1, count_2) ) wfile.write(buff + "\n") # -------- # Done with loop through lines in diff result if icomment: buff = repr(icomment) + " comment lines." wfile.write(buff + "\n") if ijunk: buff = repr(ijunk) + " junk lines." wfile.write(buff + "\n") if ifail: buff = repr(ifail) + " lines failed." wfile.write(buff + "\n") wfile.write(repr(ifail) + " lines failed.") ierr += 1 return False else: buff = "No lines differ." wfile.write(buff + "\n") return True