diff --git a/testsuite/jpeg-corrupt/run.py b/testsuite/jpeg-corrupt/run.py index 12ddea92a9..bb9d53b3b4 100755 --- a/testsuite/jpeg-corrupt/run.py +++ b/testsuite/jpeg-corrupt/run.py @@ -71,16 +71,14 @@ # These files have short APP1/APP2 metadata marker payloads that used to be # read past their saved-marker buffers before being ignored. Use iconvert to # a null output to force a full input read. -command += iconvert("short-exif-app1-len4.jpg out.null", - successmessage="short-exif-app1-len4-ok") -command += iconvert("short-exif-app1-len5.jpg out.null", - successmessage="short-exif-app1-len5-ok") -command += iconvert("short-icc-app2-len11.jpg out.null", - successmessage="short-icc-app2-len11-ok") -command += iconvert("short-icc-app2-len12.jpg out.null", - successmessage="short-icc-app2-len12-ok") -command += iconvert("short-icc-app2-len13.jpg out.null", - successmessage="short-icc-app2-len13-ok") +command += run_commands( +""" +iconvert short-exif-app1-len4.jpg out.null && echo short-exif-app1-len4-ok +iconvert short-exif-app1-len5.jpg out.null && echo short-exif-app1-len5-ok +iconvert short-icc-app2-len11.jpg out.null && echo short-icc-app2-len11-ok +iconvert short-icc-app2-len12.jpg out.null && echo short-icc-app2-len12-ok +iconvert short-icc-app2-len13.jpg out.null && echo short-icc-app2-len13-ok +""") # This file had corrupted IPTC data command += oiiotool("-oiioattrib imageinput:strict 1 -info -v src/corrupt-iptc-8011.jpg") diff --git a/testsuite/oiiotool-copy/run.py b/testsuite/oiiotool-copy/run.py index a2520353f1..eb7804a735 100755 --- a/testsuite/oiiotool-copy/run.py +++ b/testsuite/oiiotool-copy/run.py @@ -14,8 +14,10 @@ redirect = " >> out.txt 2>&1 " # Create some test images we need -command += oiiotool("-pattern constant:color=.25,.5,.75 64x64 3 -d half -o rgb64.exr") -command += oiiotool("-pattern constant:color=.25,.5,.75 64x64 3 -pattern constant:color=42 64x64 1 --chnames Z --siappend -d half -o rgb-z-parts64.exr") +command += run_commands(""" + oiiotool -pattern constant:color=.25,.5,.75 64x64 3 -d half -o rgb64.exr + oiiotool -pattern constant:color=.25,.5,.75 64x64 3 -pattern constant:color=42 64x64 1 --chnames Z --siappend -d half -o rgb-z-parts64.exr + """) # Test -i to read specific channels diff --git a/testsuite/oiiotool/run.py b/testsuite/oiiotool/run.py index f182ae19d2..803ce4a694 100755 --- a/testsuite/oiiotool/run.py +++ b/testsuite/oiiotool/run.py @@ -10,10 +10,12 @@ failureok = True # Create some test images we need -command += oiiotool ("--create 320x240 3 -d uint8 -o black.tif") -command += oiiotool ("--pattern constant:color=0.5,0.5,0.5 128x128 3 -d half -o grey128.exr") -command += oiiotool ("--pattern constant:color=0.5,0.5,0.5 64x64 3 -d half -o grey64.exr") -command += oiiotool ("--create 256x256 3 --fill:color=1,.5,.5 256x256 --fill:color=0,1,0 80x80+100+100 -d uint8 -o filled.tif") +command += run_commands(""" + oiiotool --create 320x240 3 -d uint8 -o black.tif + oiiotool --pattern constant:color=0.5,0.5,0.5 128x128 3 -d half -o grey128.exr + oiiotool --pattern constant:color=0.5,0.5,0.5 64x64 3 -d half -o grey64.exr + oiiotool --create 256x256 3 --fill:color=1,.5,.5 256x256 --fill:color=0,1,0 80x80+100+100 -d uint8 -o filled.tif + """) # test --autotrim diff --git a/testsuite/runtest.py b/testsuite/runtest.py index ff1971260c..6c51551bee 100755 --- a/testsuite/runtest.py +++ b/testsuite/runtest.py @@ -47,6 +47,7 @@ tmpdir = os.path.abspath (tmpdir) redirect = " >> out.txt " wrapper_cmd = "" +oiio_app_list = ("oiiotool", "iinfo", "idiff", "maketx", "iconvert", "igrep", "testtex", "iv") def make_relpath (path: str, start: str=os.curdir) -> str: "Wrapper around os.path.relpath which always uses '/' as the separator." @@ -170,6 +171,15 @@ def newsymlink(src: str, dst: str): # Handy functions... +# Strip trailing spaces/tabs from a line, but leave its line ending (if any) +# alone. Used to make text_diff tolerant of trailing whitespace, which can +# vary by platform (e.g. cmd.exe's `echo` bakes in a trailing space that a +# Unix shell would not) without being a meaningful difference in output. +def _rstrip_line (line: str) -> str: + ending = line[len (line.rstrip ('\r\n')):] + return line.rstrip () + ending + + # Compare two text files. Returns 0 if they are equal otherwise returns # a non-zero value and writes the differences to "diff_file". # Based on the command-line interface to difflib example from the Python @@ -179,8 +189,8 @@ def text_diff (fromfile: str, tofile: str, diff_file: str=None) -> int: try: fromdate = time.ctime (os.stat (fromfile).st_mtime) todate = time.ctime (os.stat (tofile).st_mtime) - fromlines = open (fromfile, 'r').readlines() - tolines = open (tofile, 'r').readlines() + fromlines = [_rstrip_line(l) for l in open (fromfile, 'r').readlines()] + tolines = [_rstrip_line(l) for l in open (tofile, 'r').readlines()] # if replace_relative: # tolines = replace_relative(tolines) except: @@ -206,13 +216,41 @@ def text_diff (fromfile: str, tofile: str, diff_file: str=None) -> int: return 1 -def run_app(app: str, silent: bool=False, concat: bool=True) -> str: - command = app +def run_app(app: str, silent: bool=False, failureok: bool=False, + concat: bool=True) -> str: + cmd = app.strip() + # If the command starts with the name of an OIIO app, substitute the + # full path to the built app. + words = cmd.split(maxsplit=1) + if not words: + return "" + if words[0] in oiio_app_list: + cmd = oiio_app(words[0]).strip() + (" " + words[1] if len(words) > 1 else "") if not silent: - command += redirect + cmd += redirect + if failureok : + cmd += " || true " if concat: - command += " ;\n" - return command + cmd += " ;\n" + return cmd + + +# Take shell `commands`, split at newlines, adorn each with redirects, etc., +# then re-join with semicolons to make a single command. +# Note: `failureok` defaults to None, meaning "use the global `failureok` +# value at the time this is called", which a run.py may have set. +def run_commands(commands: str, silent: bool=False, + failureok=None, concat: bool=True) -> str : + if failureok is None : + failureok = globals()["failureok"] + result = "" + for line in commands.splitlines(): + cmd = line.strip() + # Skip empty lines or comments + if cmd == "" or cmd.startswith("#"): + continue + result += run_app(cmd, silent=silent, failureok=failureok, concat=concat) + return result # Construct a command that will print info for an image, appending output to @@ -230,15 +268,8 @@ def info_command (file: str, extraargs: str="", safematch: bool=False, hash: boo args += " --no-metamatch \"DateTime|Software|OriginatingProgram|ImageHistory\"" if hash : args += " --hash" - cmd = (oiio_app(info_program) + args + " " + extraargs - + " " + make_relpath(file,tmpdir)) - if not silent : - cmd += redirect - if failureok : - cmd += " || true " - if concat: - cmd += " ;\n" - return cmd + return run_app(f"{info_program} {args} {extraargs} {make_relpath(file,tmpdir)}", + silent=silent, failureok=failureok, concat=concat) # Construct a command that will compare two images, appending output to @@ -246,20 +277,12 @@ def info_command (file: str, extraargs: str="", safematch: bool=False, hash: boo # 1 LSB (8 bit) error, it's very hard to make different platforms and # compilers always match to every last floating point bit. def diff_command (fileA: str, fileB: str, extraargs: str="", silent: bool=False, concat: bool=True) -> str : - command = (oiio_app("idiff") + "-a" - + " -fail " + str(failthresh) - + " -failpercent " + str(failpercent) - + " -hardfail " + str(hardfail) - + " -allowfailures " + str(allowfailures) - + " -warn " + str(2*failthresh) - + " -warnpercent " + str(failpercent) - + " " + extraargs + " " + make_relpath(fileA,tmpdir) - + " " + make_relpath(fileB,tmpdir)) - if not silent : - command += redirect - if concat: - command += " ;\n" - return command + return run_app (f"idiff -a -fail {failthresh} -failpercent {failpercent}" + f" -hardfail {hardfail} -allowfailures {allowfailures}" + f" -warn {2*failthresh} -warnpercent {failpercent}" + f" {extraargs} {make_relpath(fileA,tmpdir)} " + f" {make_relpath(fileB,tmpdir)}", + silent=silent, concat=concat) # Construct a command that will create a texture, appending console @@ -267,14 +290,10 @@ def diff_command (fileA: str, fileB: str, extraargs: str="", silent: bool=False, def maketx_command (infile: str, outfile: str, extraargs: str="", showinfo: bool=False, showinfo_extra: str="", silent: str=False, concat: str=True) -> str : - command = (oiio_app("maketx") - + " " + make_relpath(infile,tmpdir) - + " " + extraargs - + " -o " + make_relpath(outfile,tmpdir)) - if not silent : - command += redirect - if concat: - command += " ;\n" + infile_relpath = make_relpath(infile,tmpdir) + outfile_relpath = make_relpath(outfile,tmpdir) + command = run_app(f"maketx {infile_relpath} {extraargs} -o {outfile_relpath}", + silent=silent, concat=concat) if showinfo: command += info_command (outfile, extraargs=showinfo_extra, safematch=1) return command @@ -291,62 +310,38 @@ def rw_command (dir: str, filename: str, testwrite: bool=True, use_oiiotool: boo preargs: str="", idiffextraargs: str="", output_filename: str="", safematch: bool=False, printinfo: bool=True) -> str: fn = make_relpath (dir + "/" + filename, tmpdir) + cmd = "" if printinfo : - cmd = info_command (fn, safematch=safematch) - else : - cmd = "" + cmd += info_command (fn, safematch=safematch) if output_filename == "" : output_filename = filename tool = "oiiotool" if use_oiiotool else "iconvert" if testwrite : - cmd = (cmd + oiio_app(tool) + preargs + " " + fn - + " " + extraargs + " -o " + output_filename + redirect + ";\n") - cmd = (cmd + oiio_app("idiff") + " -a " + fn - + " -fail " + str(failthresh) - + " -failpercent " + str(failpercent) - + " -hardfail " + str(hardfail) - + " -allowfailures " + str(allowfailures) - + " -warn " + str(2*failthresh) - + " " + idiffextraargs + " " + output_filename + redirect + ";\n") + cmd += run_app(f"{tool} {preargs} {fn} {extraargs} -o {output_filename}") + cmd += run_app(f"idiff -a {fn} -fail {failthresh} -failpercent {failpercent}" + + f" -hardfail {hardfail} -allowfailures {allowfailures}" + + f" -warn {2*failthresh} {idiffextraargs} {output_filename}") return cmd # Construct a command that will testtex def testtex_command (file: str, extraargs: str="", silent: bool=False, concat: bool=True) -> str: - cmd = oiio_app("testtex") + " " + file + " " + extraargs + " " - if not silent : - cmd += redirect - if concat: - cmd += " ;\n" - return cmd + return run_app(f"testtex {file} {extraargs}", + silent=silent, concat=concat) # Construct a command that will run iconvert and append its output to out.txt def iconvert (args: str, silent: bool=False, concat: bool=True, - failureok: bool=False, successmessage: str="") -> str: - cmd = (oiio_app("iconvert") + " " + args) - if successmessage: - cmd = "(" + cmd + " && echo " + successmessage + ")" - if not silent : - cmd += redirect - if failureok : - cmd += " || true " - if concat: - cmd += " ;\n" - return cmd + failureok: bool=False) -> str: + return run_app(f"iconvert {args}", + silent=silent, failureok=failureok, concat=concat) # Construct a command that will run oiiotool and append its output to out.txt def oiiotool (args: str, silent: bool=False, concat: bool=True, failureok: bool=False) -> str: - cmd = (oiio_app("oiiotool") + " " + args) - if not silent : - cmd += redirect - if failureok : - cmd += " || true " - if concat: - cmd += " ;\n" - return cmd + return run_app(f"oiiotool {args}", + silent=silent, failureok=failureok, concat=concat) @@ -422,7 +417,7 @@ def runtest (command: str, outputs: list[str], failureok: int=0) -> int : for sub_command in [c.strip() for c in command.split(';') if c.strip()]: cmdret = subprocess.call (sub_command, shell=True, env=test_environ) - if cmdret != 0 and failureok == 0 : + if cmdret != 0 and not failureok : print ("#### Error: this command failed: ", sub_command) print ("FAIL") err = 1 diff --git a/testsuite/webp/run.py b/testsuite/webp/run.py index dbd1108e20..0988cdf146 100755 --- a/testsuite/webp/run.py +++ b/testsuite/webp/run.py @@ -28,7 +28,7 @@ "short-exif-len13.webp", ] for f in short_exif_files: - command += iconvert(f + " out.null", successmessage=f + "-ok") + command += iconvert(f"{f} out.null && echo {f}-ok") # Regression test: a 76-byte WebP whose VP8X header declares a 16383x16383 # canvas inconsistent with its tiny frame. Must be rejected cleanly (libwebp's