From c7bf5dd12a79c7e8db737b6fd3f7f28097838841 Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Wed, 2 Sep 2020 22:58:49 +0800 Subject: [PATCH] Adjust line breaks, binary extension on Windows --- tests/bash_tests/testcases.py | 47 ++++++++++++----------- tests/bash_tests/utils.py | 72 +++++++++++++++++++---------------- tests/system_tests.py | 9 ++++- 3 files changed, 72 insertions(+), 56 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index 1dce0ed5..71fc6676 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -69,8 +69,8 @@ class TestCases(unittest.TestCase): out += 'Testcase 4' out += '==========' BT.save(BT.cat('j.xmp').replace('The Exif image description', - 'The Exif image descriptionCiao bella'), - 'k.xmp') + 'The Exif image descriptionCiao bella') + ,'k.xmp') BT.copyTestFile(jpg, 'k.jpg') out += BT.execute('exiv2 -iX k.jpg') out += BT.execute('exiv2 -px k.jpg') @@ -298,7 +298,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 ,'exiv2-sony-dsc-w7.jpg' ,'exiv2-canon-eos-20d.jpg' ,'exiv2-canon-eos-d30.jpg' - ,'exiv2-canon-powershot-a520.jpg'] + ,'exiv2-canon-powershot-a520.jpg' + ] images_2 = [ 'exiv2-empty.jpg' @@ -315,7 +316,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 ,'20050527_051833.jpg' ,'20060802_095200.jpg' ,'20001004_015404.jpg' - ,'20060127_225027.jpg'] + ,'20060127_225027.jpg' + ] images_3 = [ 'exiv2-empty.exv' @@ -332,7 +334,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 ,'20050527_051833.exv' ,'20060802_095200.exv' ,'20001004_015404.exv' - ,'20060127_225027.exv'] + ,'20060127_225027.exv' + ] images_1_str = ' '.join(images_1) images_2_str = ' '.join(images_2) @@ -362,7 +365,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += BT.execute('exiv2 -u -v print {images_2_str}', vars(), expected_returncodes=[253]) out += '' out += BT.execute('exiv2 -u -v -b -pt print {images_2_str}', vars()) - stdout, stderr = BT.execute('exiv2 -u -v -b -pt print {images_2_str}', vars(), mix_stdout_and_stderr=False) + stdout, stderr = BT.execute('exiv2 -u -v -b -pt print {images_2_str}', vars(), redirect_stderr_to_stdout=False) BT.save(stdout, 'iii') out += stderr @@ -371,7 +374,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += '\nExtract Thumbnail --------------------------------------------------------' out += BT.execute('exiv2 -u -vf -et extract {images_2_str}', vars(), expected_returncodes=[253]) - stdout, stderr = BT.execute('exiv2 -u -v -b -pt print {images_3_str}', vars(), mix_stdout_and_stderr=False) + stdout, stderr = BT.execute('exiv2 -u -v -b -pt print {images_3_str}', vars(), redirect_stderr_to_stdout=False) BT.save(stdout, 'jjj') out += stderr @@ -388,7 +391,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += '\nInsert Exif data ---------------------------------------------------------' out += BT.execute('exiv2 -u -v insert {images_2_str}', vars()) - stdout, stderr = BT.execute('exiv2 -u -v -b -pt print {images_3_str}', vars(), mix_stdout_and_stderr=False) + stdout, stderr = BT.execute('exiv2 -u -v -b -pt print {images_3_str}', vars(), redirect_stderr_to_stdout=False) BT.save(stdout, 'kkk') out += stderr @@ -448,11 +451,12 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 # num = 1074 # ICC Profile Support out = BT.Output() - for img in ['Reagan.jpg', - 'exiv2-bug1199.webp', - 'ReaganLargePng.png', - 'ReaganLargeJpg.jpg', - 'Reagan2.jp2']: # 1272 ReaganLargeTiff.tiff + for img in ['Reagan.jpg' + ,'exiv2-bug1199.webp' + ,'ReaganLargePng.png' + ,'ReaganLargeJpg.jpg' + ,'Reagan2.jp2' # 1272 ReaganLargeTiff.tiff + ]: stub = img.split('.')[0] iccname = stub + '.icc' @@ -460,7 +464,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.copyTestFile(i) out += BT.execute('exiv2 -pS {img}', vars()) - BT.save(BT.execute('exiv2 -pC {img}', vars(), return_bytes=True), + BT.save(BT.execute('exiv2 -pC {img}', vars(), return_raw=True, return_bytes=True), stub + '_1.icc') out += BT.execute('exiv2 -eC --force {img}', vars()) BT.mv(iccname, stub + '_2.icc') @@ -468,7 +472,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.copyTestFile('large.icc', iccname) out += BT.execute('exiv2 -iC {img}', vars()) - BT.save(BT.execute('exiv2 -pC {img}', vars(), return_bytes=True), + BT.save(BT.execute('exiv2 -pC {img}', vars(), return_raw=True, return_bytes=True), stub + '_large_1.icc') out += BT.execute('exiv2 -pS {img}', vars()) out += BT.execute('exiv2 -eC --force {img}', vars()) @@ -477,7 +481,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.copyTestFile('small.icc', iccname) out += BT.execute('exiv2 -iC {img}', vars()) - BT.save(BT.execute('exiv2 -pC {img}', vars(), return_bytes=True), + BT.save(BT.execute('exiv2 -pC {img}', vars(), return_raw=True, return_bytes=True), stub + '_small_1.icc') out += BT.execute('exiv2 -pS {img}', vars()) out += BT.execute('exiv2 -eC --force {img}', vars()) @@ -492,10 +496,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 def image_test(self): - test_files = [ - 'table.jpg' - ,'smiley1.jpg' - ,'smiley2.jpg'] + test_files = ['table.jpg', 'smiley1.jpg', 'smiley2.jpg'] erase_test_files = [ 'glider.exv' ,'iptc-noAPP13.jpg' @@ -511,7 +512,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 ,'iptc-psAPP13-wIPTCend.jpg' ,'iptc-psAPP13-wIPTCmid1-wIPTCempty-wIPTCmid2.jpg' ,'iptc-psAPP13-wIPTCmid.jpg' - ,'iptc-psAPP13-wIPTC-psAPP13-noIPTC.jpg'] + ,'iptc-psAPP13-wIPTC-psAPP13-noIPTC.jpg' + ] pass_count = 0 fail_count = 0 @@ -612,7 +614,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 ,'iptc-psAPP13-wIPTC-psAPP13-noIPTC.jpg' ,'smiley1.jpg' ,'smiley2.jpg' - ,'table.jpg'] + ,'table.jpg' + ] pass_count = 0 fail_count = 0 diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index a7232e64..f2410c7e 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -21,6 +21,7 @@ class Config: # The configuration parameters for bash test # When you run the test cases through `python3 runner.py`, the function configure_suite() in system_tests.py will override these parameters. exiv2_dir = os.path.normpath(os.path.join(os.path.abspath(__file__), '../../../')) + exiv2_ext = '' # or '.exe' bin_dir = os.path.join(exiv2_dir, 'build/bin') data_dir = os.path.join(exiv2_dir, 'test/data') tmp_dir = os.path.join(exiv2_dir, 'test/tmp') @@ -30,7 +31,7 @@ class Config: @classmethod def init(cls): - """ Init test environments and variables """ + """ Init test environments and variables that may be modified """ os.makedirs(cls.tmp_dir, exist_ok=True) os.chdir(cls.tmp_dir) log.buffer = [] @@ -253,6 +254,7 @@ class Output: def __str__(self): return self.newline.join(self.lines) + # Comment it so that log does not automatically convert to str type # def __repr__(self): # return str(self) @@ -350,52 +352,58 @@ def execute(cmd: str, stdin: (str, bytes) = None, encoding=None, expected_returncodes=[0], + return_raw=False, return_bytes=False, - mix_stdout_and_stderr=True): + redirect_stderr_to_stdout=True): """ Execute a command in the shell and return its stdout and stderr. - If the binary of Exiv2 is executed, the absolute path is automatically added. - - Returns the output bytes when return_bytes is true. Otherwise, the output is decoded to a str and returned. + - When return_raw is true, returns the raw output. Otherwise, the path separator, whitespace character in output will be filtered. + - When return_bytes is true, returns the output bytes. Otherwise, the output is decoded to a str and returned. Sample: >>> execute('echo Hello') >>> execute('exiv2 --help') """ - args = shlex.split(cmd.format(**vars_dict)) - if args[0] in Config.bin_files: - args[0] = os.path.join(Config.bin_dir, args[0]) - + # Check the input + args = shlex.split(cmd.format(**vars_dict), posix=os.name=='posix') encoding = encoding or Config.encoding + if args[0] in Config.bin_files: + args[0] = os.path.join(Config.bin_dir, args[0]) + Config.exiv2_ext if stdin: if not isinstance(stdin, bytes): stdin = str(stdin).encode(encoding) - - if mix_stdout_and_stderr: + if redirect_stderr_to_stdout: stderr_to = subprocess.STDOUT else: stderr_to = subprocess.PIPE - with subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=stderr_to, cwd=Config.tmp_dir) as proc: - try: - output = proc.communicate(stdin, timeout=10) # Assign (stdout, stderr) to output - except subprocess.TimeoutExpired: - proc.kill() - output = proc.communicate() + # Execute the command + try: + with subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=stderr_to, cwd=Config.tmp_dir) as proc: + try: + output = proc.communicate(stdin, timeout=10) # Assign (stdout, stderr) to output + except subprocess.TimeoutExpired: + proc.kill() + output = proc.communicate() + except: + raise RuntimeError('Failed to execute: {}'.format(args)) output = [i or b'' for i in output] - output = [i.rstrip(b'\n') for i in output] + output = [i.rstrip(b'\r\n').rstrip(b'\n') for i in output] # Remove the last line break of the output + # Check the output + if not return_raw: + output = [i.replace(b'\r\n', b'\n') for i in output] # Fix dos line-endings + output = [i.replace(b'\\', rb'/') for i in output] # Fix dos path separators if not return_bytes: output = [i.decode(encoding) for i in output] - output = [i.replace('\r\n', '\n') for i in output] # fix dos line-endings - output = [i.replace('\\', r'/') for i in output] # fix dos path separators - if expected_returncodes and proc.returncode not in expected_returncodes: - log.error('Failed to execute: {}'.format(' '.join(args))) + log.error('Failed to execute: {}'.format(args)) log.error('The expected return code is {}, but get {}'.format(str(expected_returncodes), proc.returncode)) log.info('OUTPUT:\n{}'.format(output[0] + output[1])) raise RuntimeError('\n' + log.to_str()) - if mix_stdout_and_stderr: + if redirect_stderr_to_stdout: return output[0] + output[1] or None else: return [i or None for i in output] @@ -434,20 +442,20 @@ def eraseTest(filename): return diffCheck(good_file, test_file, in_bytes=True) -def copyTest(num, src, dst): - test_file = '{}.c{}tst'.format(dst, num) +def copyTest(num, src, good): + test_file = '{}.c{}tst'.format(good, num) src_file = os.path.join(Config.data_dir, src) - good_file = os.path.join(Config.data_dir, '{}.c{}gd'.format(dst, num)) - copyTestFile(dst, test_file) + good_file = os.path.join(Config.data_dir, '{}.c{}gd'.format(good, num)) + copyTestFile(good, test_file) execute('metacopy -a {src_file} {test_file}', vars()) return diffCheck(good_file, test_file, in_bytes=True) -def iptcTest(num, src, dst): - test_file = '{}.i{}tst'.format(dst, num) +def iptcTest(num, src, good): + test_file = '{}.i{}tst'.format(good, num) src_file = os.path.join(Config.data_dir, src) - good_file = os.path.join(Config.data_dir, '{}.i{}gd'.format(dst, num)) - copyTestFile(dst, test_file) + good_file = os.path.join(Config.data_dir, '{}.i{}gd'.format(good, num)) + copyTestFile(good, test_file) execute('metacopy -ip {src_file} {test_file}', vars()) return diffCheck(good_file, test_file, in_bytes=True) @@ -457,7 +465,7 @@ def printTest(filename): src_file = os.path.join(Config.data_dir, filename) good_file = os.path.join(Config.data_dir, filename + '.ipgd') copyTestFile(filename, test_file) - output = execute('iptcprint {src_file}', vars(), expected_returncodes=None, return_bytes=True) + output = execute('iptcprint {src_file}', vars(), expected_returncodes=[0, 255], return_bytes=True) output = output.replace(os.path.normpath(Config.data_dir).encode(), b'../data') # Ignore the difference of data_dir save(output + b'\n', test_file) return diffCheck(good_file, test_file, in_bytes=True) @@ -478,7 +486,7 @@ r Iptc.Application2.Keywords r Iptc.Application2.CountryName """.lstrip('\n').encode() execute('iptctest {tmp}', vars(), stdin=stdin) - save(execute('iptcprint {tmp}', vars(), expected_returncodes=None, return_bytes=True) + b'\n', + save(execute('iptcprint {tmp}', vars(), expected_returncodes=[0, 255], return_bytes=True) + b'\n', test_file) return diffCheck(good_file, test_file, in_bytes=True) @@ -500,7 +508,7 @@ a Iptc.Envelope.TimeSent 14:41:0-05:00 a Iptc.Application2.RasterizedCaption 230 42 34 2 90 84 23 146 """.lstrip('\n').encode() execute('iptctest {tmp}', vars(), stdin=stdin) - save(execute('iptcprint {tmp}', vars(), expected_returncodes=None, return_bytes=True) + b'\n', + save(execute('iptcprint {tmp}', vars(), expected_returncodes=[0, 255], return_bytes=True) + b'\n', test_file) return diffCheck(good_file, test_file, in_bytes=True) diff --git a/tests/system_tests.py b/tests/system_tests.py index d2d457ae..b3de4e6a 100644 --- a/tests/system_tests.py +++ b/tests/system_tests.py @@ -10,6 +10,7 @@ import sys import shutil import string import unittest +import platform from bash_tests import utils as BT @@ -161,6 +162,8 @@ def configure_suite(config_file): else: fallback = "" config['ENV'][key] = os.getenv(config['ENV'][key]) or fallback + if platform.system() == 'Windows': + config['ENV']['binary_extension'] = config['ENV']['binary_extension'] or '.exe' if 'variables' in config: for key in config['variables']: @@ -203,10 +206,12 @@ def configure_suite(config_file): # Configure the parameters for bash tests BT.Config.bin_dir = os.path.abspath(config['ENV']['exiv2_path']) - BT.Config.data_dir = os.path.abspath(config['paths']['data_path']) - BT.Config.tmp_dir = os.path.abspath(config['paths']['tmp_path']) + BT.Config.exiv2_ext = config['ENV']['binary_extension'] BT.Config.exiv2_http = config['ENV']['exiv2_http'] BT.Config.exiv2_port = int(config['ENV']['exiv2_port']) + BT.Config.data_dir = os.path.abspath(config['paths']['data_path']) + BT.Config.tmp_dir = os.path.abspath(config['paths']['tmp_path']) + # print(dict(config['ENV'])); exit(1) # for debug class FileDecoratorBase(object):