From 44570561572931e86568d7a2c439ab04525a5f6c Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Sun, 30 Aug 2020 22:15:11 +0800 Subject: [PATCH] Mainly optimize utils.py: - Correct the function name excute() to execute(), and add the stdin parameter to it - Add logs to class 'HttpServer' - Adjust the code order in utils.py --- tests/bash_tests/testcases.py | 352 +++++++++++++++++----------------- tests/bash_tests/utils.py | 291 ++++++++++++++++------------ 2 files changed, 339 insertions(+), 304 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index eff0217b..94743795 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -21,8 +21,8 @@ class TestCases(unittest.TestCase): jpg = 'exiv2-empty.jpg' BT.copyTestFile(jpg) out = BT.Output() - out += BT.excute('addmoddel {jpg}', vars()) - out += BT.excute('exiv2 -pv {jpg}', vars()) + out += BT.execute('addmoddel {jpg}', vars()) + out += BT.execute('exiv2 -pv {jpg}', vars()) BT.reportTest('addmoddel', out) @@ -35,12 +35,12 @@ class TestCases(unittest.TestCase): out += 'Testcase 1' out += '==========' # 9 equal signs BT.copyTestFile(jpg, 'h.jpg') - out += BT.excute("exiv2 -M'set Exif.Image.ImageDescription The Exif image description' h.jpg") + out += BT.execute("exiv2 -M'set Exif.Image.ImageDescription The Exif image description' h.jpg") BT.rm('h.xmp') - out += BT.excute('exiv2 -eX h.jpg') - out += BT.excute('exiv2 -px h.xmp') - out += BT.excute('exiv2 -PEkycv h.xmp') - out += BT.excute('exiv2 -pi h.xmp') + out += BT.execute('exiv2 -eX h.jpg') + out += BT.execute('exiv2 -px h.xmp') + out += BT.execute('exiv2 -PEkycv h.xmp') + out += BT.execute('exiv2 -pi h.xmp') BT.log.info('#2 Convert XMP x-default langAlt value back to Exif ImageDescription') out += '' @@ -48,10 +48,10 @@ class TestCases(unittest.TestCase): out += '==========' BT.copyTestFile(jpg, 'i.jpg') BT.cp('h.xmp', 'i.xmp') - out += BT.excute('exiv2 -iX i.jpg') - out += BT.excute('exiv2 -px i.jpg') - out += BT.excute('exiv2 -PEkycv i.jpg') - out += BT.excute('exiv2 -pi i.jpg') + out += BT.execute('exiv2 -iX i.jpg') + out += BT.execute('exiv2 -px i.jpg') + out += BT.execute('exiv2 -PEkycv i.jpg') + out += BT.execute('exiv2 -pi i.jpg') BT.log.info('#3 Convert XMP single non-x-default langAlt value to Exif ImageDescription') out += '' @@ -59,10 +59,10 @@ class TestCases(unittest.TestCase): out += '==========' BT.save(BT.cat('i.xmp').replace('x-default', 'de-DE'), 'j.xmp') BT.copyTestFile(jpg, 'j.jpg') - out += BT.excute('exiv2 -iX j.jpg') - out += BT.excute('exiv2 -px j.jpg') - out += BT.excute('exiv2 -PEkycv j.jpg') - out += BT.excute('exiv2 -pi j.jpg') + out += BT.execute('exiv2 -iX j.jpg') + out += BT.execute('exiv2 -px j.jpg') + out += BT.execute('exiv2 -PEkycv j.jpg') + out += BT.execute('exiv2 -pi j.jpg') BT.log.info("#4 This shouldn't work: No x-default, more than one language") out += '' @@ -72,36 +72,36 @@ class TestCases(unittest.TestCase): 'The Exif image descriptionCiao bella'), 'k.xmp') BT.copyTestFile(jpg, 'k.jpg') - out += BT.excute('exiv2 -iX k.jpg') - out += BT.excute('exiv2 -px k.jpg') - out += BT.excute('exiv2 -v -PEkycv k.jpg') - out += BT.excute('exiv2 -v -pi k.jpg') + out += BT.execute('exiv2 -iX k.jpg') + out += BT.execute('exiv2 -px k.jpg') + out += BT.execute('exiv2 -v -PEkycv k.jpg') + out += BT.execute('exiv2 -v -pi k.jpg') BT.log.info('#5 Add a default language to the XMP file and convert to Exif and IPTC') out += '' out += 'Testcase 5' out += '==========' BT.cp('k.xmp', 'l.xmp') - out += BT.excute('''exiv2 -M'set Xmp.dc.description lang="x-default" How to fix this mess' l.xmp''') + out += BT.execute('''exiv2 -M'set Xmp.dc.description lang="x-default" How to fix this mess' l.xmp''') out += BT.grep('x-default', 'l.xmp') BT.copyTestFile(jpg, 'l.jpg') - out += BT.excute('exiv2 -iX l.jpg') - out += BT.excute('exiv2 -px -b l.jpg') - out += BT.excute('exiv2 -PEkycv l.jpg') - out += BT.excute('exiv2 -pi l.jpg') + out += BT.execute('exiv2 -iX l.jpg') + out += BT.execute('exiv2 -px -b l.jpg') + out += BT.execute('exiv2 -PEkycv l.jpg') + out += BT.execute('exiv2 -pi l.jpg') BT.log.info('#6 Convert an Exif user comment to XMP') out += '' out += 'Testcase 6' out += '==========' BT.copyTestFile(jpg, 'm.jpg') - out += BT.excute("exiv2 -M'set Exif.Photo.UserComment charset=Jis This is a JIS encoded Exif user comment. Or was it?' m.jpg") - out += BT.excute('exiv2 -PEkycv m.jpg') + out += BT.execute("exiv2 -M'set Exif.Photo.UserComment charset=Jis This is a JIS encoded Exif user comment. Or was it?' m.jpg") + out += BT.execute('exiv2 -PEkycv m.jpg') BT.rm('m.xmp') - out += BT.excute('exiv2 -eX m.jpg') - out += BT.excute('exiv2 -px m.xmp') - out += BT.excute('exiv2 -PEkycv m.xmp') - out += BT.excute('exiv2 -v -pi m.xmp') + out += BT.execute('exiv2 -eX m.jpg') + out += BT.execute('exiv2 -px m.xmp') + out += BT.execute('exiv2 -PEkycv m.xmp') + out += BT.execute('exiv2 -v -pi m.xmp') BT.log.info('#7 And back to Exif') out += '' @@ -109,25 +109,25 @@ class TestCases(unittest.TestCase): out += '==========' BT.copyTestFile(jpg, 'n.jpg') BT.cp('m.xmp', 'n.xmp') - out += BT.excute('exiv2 -iX n.jpg') - out += BT.excute('exiv2 -px n.jpg') - out += BT.excute('exiv2 -PEkycv n.jpg') - out += BT.excute('exiv2 -v -pi n.jpg') + out += BT.execute('exiv2 -iX n.jpg') + out += BT.execute('exiv2 -px n.jpg') + out += BT.execute('exiv2 -PEkycv n.jpg') + out += BT.execute('exiv2 -v -pi n.jpg') BT.log.info('#8 Convert IPTC keywords to XMP') out += '' out += 'Testcase 8' out += '==========' BT.copyTestFile(jpg, 'o.jpg') - out += BT.excute('''exiv2 -M'add Iptc.Application2.Keywords Sex' o.jpg''') - out += BT.excute('''exiv2 -M'add Iptc.Application2.Keywords Drugs' o.jpg''') - out += BT.excute('''exiv2 -M"add Iptc.Application2.Keywords Rock'n'roll" o.jpg''') - out += BT.excute('''exiv2 -pi o.jpg''') + out += BT.execute('''exiv2 -M'add Iptc.Application2.Keywords Sex' o.jpg''') + out += BT.execute('''exiv2 -M'add Iptc.Application2.Keywords Drugs' o.jpg''') + out += BT.execute('''exiv2 -M"add Iptc.Application2.Keywords Rock'n'roll" o.jpg''') + out += BT.execute('''exiv2 -pi o.jpg''') BT.rm('o.xmp') - out += BT.excute('exiv2 -eX o.jpg') - out += BT.excute('exiv2 -px o.xmp') - out += BT.excute('exiv2 -v -PEkycv o.xmp') - out += BT.excute('exiv2 -pi o.xmp') + out += BT.execute('exiv2 -eX o.jpg') + out += BT.execute('exiv2 -px o.xmp') + out += BT.execute('exiv2 -v -PEkycv o.xmp') + out += BT.execute('exiv2 -pi o.xmp') BT.log.info('#9 And back to IPTC') out += '' @@ -135,23 +135,23 @@ class TestCases(unittest.TestCase): out += '==========' BT.copyTestFile(jpg, 'p.jpg') BT.cp('o.xmp', 'p.xmp') - out += BT.excute('exiv2 -iX p.jpg') - out += BT.excute('exiv2 -px p.jpg') - out += BT.excute('exiv2 -v -PEkycv p.jpg') - out += BT.excute('exiv2 -pi p.jpg') + out += BT.execute('exiv2 -iX p.jpg') + out += BT.execute('exiv2 -px p.jpg') + out += BT.execute('exiv2 -v -PEkycv p.jpg') + out += BT.execute('exiv2 -pi p.jpg') BT.log.info('#10 Convert an Exif tag to an XMP text value') out += '' out += 'Testcase 10' out += '===========' # 10 equal signs BT.copyTestFile(jpg, 'q.jpg') - out += BT.excute("exiv2 -M'set Exif.Image.Software Exiv2' q.jpg") - out += BT.excute("exiv2 -PEkycv q.jpg") + out += BT.execute("exiv2 -M'set Exif.Image.Software Exiv2' q.jpg") + out += BT.execute("exiv2 -PEkycv q.jpg") BT.rm('q.xmp') - out += BT.excute('exiv2 -eX q.jpg') - out += BT.excute('exiv2 -px q.xmp') - out += BT.excute('exiv2 -PEkycv q.xmp') - out += BT.excute('exiv2 -v -pi q.xmp') + out += BT.execute('exiv2 -eX q.jpg') + out += BT.execute('exiv2 -px q.xmp') + out += BT.execute('exiv2 -PEkycv q.xmp') + out += BT.execute('exiv2 -v -pi q.xmp') BT.log.info('#11 And back to Exif') out += '' @@ -159,23 +159,23 @@ class TestCases(unittest.TestCase): out += '===========' BT.copyTestFile(jpg, 'r.jpg') BT.cp('q.xmp', 'r.xmp') - out += BT.excute('exiv2 -iX r.jpg') - out += BT.excute('exiv2 -px r.jpg') - out += BT.excute('exiv2 -PEkycv r.jpg') - out += BT.excute('exiv2 -v -pi r.jpg') + out += BT.execute('exiv2 -iX r.jpg') + out += BT.execute('exiv2 -px r.jpg') + out += BT.execute('exiv2 -PEkycv r.jpg') + out += BT.execute('exiv2 -v -pi r.jpg') BT.log.info('#12 Convert an IPTC dataset to an XMP text value') out += '' out += 'Testcase 12' out += '===========' BT.copyTestFile(jpg, 's.jpg') - out += BT.excute("exiv2 -M'set Iptc.Application2.SubLocation Kuala Lumpur' s.jpg") - out += BT.excute("exiv2 -pi s.jpg") + out += BT.execute("exiv2 -M'set Iptc.Application2.SubLocation Kuala Lumpur' s.jpg") + out += BT.execute("exiv2 -pi s.jpg") BT.rm('s.xmp') - out += BT.excute('exiv2 -eX s.jpg') - out += BT.excute('exiv2 -px s.xmp') - out += BT.excute('exiv2 -v -PEkycv s.xmp') - out += BT.excute('exiv2 -pi s.xmp') + out += BT.execute('exiv2 -eX s.jpg') + out += BT.execute('exiv2 -px s.xmp') + out += BT.execute('exiv2 -v -PEkycv s.xmp') + out += BT.execute('exiv2 -pi s.xmp') BT.log.info('#13 And back to IPTC') out += '' @@ -183,32 +183,32 @@ class TestCases(unittest.TestCase): out += '===========' BT.copyTestFile(jpg, 't.jpg') BT.cp('s.xmp', 't.xmp') - out += BT.excute('exiv2 -iX t.jpg') - out += BT.excute('exiv2 -px t.jpg') - out += BT.excute('exiv2 -v -PEkycv t.jpg') - out += BT.excute('exiv2 -pi t.jpg') + out += BT.execute('exiv2 -iX t.jpg') + out += BT.execute('exiv2 -px t.jpg') + out += BT.execute('exiv2 -v -PEkycv t.jpg') + out += BT.execute('exiv2 -pi t.jpg') BT.log.info('#14 Convert a few other tags of interest from Exif/IPTC to XMP') out += '' out += 'Testcase 14' out += '===========' BT.copyTestFile(jpg, 'u.jpg') - out += BT.excute("exiv2 -M'set Exif.Photo.DateTimeOriginal 2003:12:14 12:01:44' u.jpg") - out += BT.excute("exiv2 -M'set Exif.Photo.SubSecTimeOriginal 999999999' u.jpg") - out += BT.excute("exiv2 -M'set Exif.Photo.ExifVersion 48 50 50 49' u.jpg") - out += BT.excute("exiv2 -M'set Exif.Photo.ComponentsConfiguration 1 2 3 0' u.jpg") - out += BT.excute("exiv2 -M'set Exif.Photo.Flash 73' u.jpg") - out += BT.excute("exiv2 -M'set Exif.GPSInfo.GPSLatitude 3/1 8/1 29734512/1000000' u.jpg") - out += BT.excute("exiv2 -M'set Exif.GPSInfo.GPSLatitudeRef N' u.jpg") - out += BT.excute("exiv2 -M'set Exif.GPSInfo.GPSVersionID 2 2 0 1' u.jpg") - out += BT.excute("exiv2 -M'set Exif.GPSInfo.GPSTimeStamp 1/1 2/1 999999999/1000000000' u.jpg") - out += BT.excute('exiv2 -PEkycv u.jpg') - out += BT.excute('exiv2 -pi u.jpg') + out += BT.execute("exiv2 -M'set Exif.Photo.DateTimeOriginal 2003:12:14 12:01:44' u.jpg") + out += BT.execute("exiv2 -M'set Exif.Photo.SubSecTimeOriginal 999999999' u.jpg") + out += BT.execute("exiv2 -M'set Exif.Photo.ExifVersion 48 50 50 49' u.jpg") + out += BT.execute("exiv2 -M'set Exif.Photo.ComponentsConfiguration 1 2 3 0' u.jpg") + out += BT.execute("exiv2 -M'set Exif.Photo.Flash 73' u.jpg") + out += BT.execute("exiv2 -M'set Exif.GPSInfo.GPSLatitude 3/1 8/1 29734512/1000000' u.jpg") + out += BT.execute("exiv2 -M'set Exif.GPSInfo.GPSLatitudeRef N' u.jpg") + out += BT.execute("exiv2 -M'set Exif.GPSInfo.GPSVersionID 2 2 0 1' u.jpg") + out += BT.execute("exiv2 -M'set Exif.GPSInfo.GPSTimeStamp 1/1 2/1 999999999/1000000000' u.jpg") + out += BT.execute('exiv2 -PEkycv u.jpg') + out += BT.execute('exiv2 -pi u.jpg') BT.rm('u.xmp') - out += BT.excute('exiv2 -eX u.jpg') - out += BT.excute('exiv2 -px u.xmp') - out += BT.excute('exiv2 -PEkycv u.xmp') - out += BT.excute('exiv2 -pi u.xmp') + out += BT.execute('exiv2 -eX u.jpg') + out += BT.execute('exiv2 -px u.xmp') + out += BT.execute('exiv2 -PEkycv u.xmp') + out += BT.execute('exiv2 -pi u.xmp') BT.log.info('#15 And back to Exif/IPTC') out += '' @@ -216,20 +216,20 @@ class TestCases(unittest.TestCase): out += '===========' BT.copyTestFile(jpg, 'v.jpg') BT.cp('u.xmp', 'v.xmp') - out += BT.excute("exiv2 -M'set Xmp.xmp.ModifyDate 2015-04-17T18:10:22Z' v.xmp") - out += BT.excute('exiv2 -iX v.jpg') # need TZ=GMT-8 - out += BT.excute('exiv2 -px v.jpg') - out += BT.excute('exiv2 -PEkycv v.jpg').replace('17 19:10:22', '18 02:10:22') # evade this test on MSVC builds (Issue #485) - out += BT.excute('exiv2 -pi v.jpg') + out += BT.execute("exiv2 -M'set Xmp.xmp.ModifyDate 2015-04-17T18:10:22Z' v.xmp") + out += BT.execute('exiv2 -iX v.jpg') # need TZ=GMT-8 + out += BT.execute('exiv2 -px v.jpg') + out += BT.execute('exiv2 -PEkycv v.jpg').replace('17 19:10:22', '18 02:10:22') # evade this test on MSVC builds (Issue #485) + out += BT.execute('exiv2 -pi v.jpg') BT.log.info('#16 https://github.com/Exiv2/exiv2/issues/521') out += '' out += 'Testcase 16' out += '===========' BT.copyTestFile('DSC_3079.jpg') - out += BT.excute('exiv2 -px DSC_3079.jpg') - out += BT.excute('exiv2 -M"del Xmp.mwg-rs.Regions" DSC_3079.jpg') - out += BT.excute('exiv2 -px DSC_3079.jpg') + out += BT.execute('exiv2 -px DSC_3079.jpg') + out += BT.execute('exiv2 -M"del Xmp.mwg-rs.Regions" DSC_3079.jpg') + out += BT.execute('exiv2 -px DSC_3079.jpg') BT.reportTest('conversions', out) @@ -252,15 +252,15 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' BT.save(cmds, cmdfile) BT.copyTestFile(crwfile) out = BT.Output() - out += BT.excute('exiv2 -v -pt {crwfile}', vars()) - out += BT.excute('exiv2 -v -m{cmdfile} {crwfile}', vars()) - out += BT.excute('exiv2 -v -pt {crwfile}', vars()) + out += BT.execute('exiv2 -v -pt {crwfile}', vars()) + out += BT.execute('exiv2 -v -m{cmdfile} {crwfile}', vars()) + out += BT.execute('exiv2 -v -pt {crwfile}', vars()) BT.log.info('#2 Delete tags') BT.copyTestFile(crwfile) - out += BT.excute("exiv2 -v -pt {crwfile}", vars()) - out += BT.excute("exiv2 -v -M'del Exif.Canon.OwnerName' {crwfile}", vars()) - out += BT.excute("exiv2 -v -pt {crwfile}", vars()) + out += BT.execute("exiv2 -v -pt {crwfile}", vars()) + out += BT.execute("exiv2 -v -M'del Exif.Canon.OwnerName' {crwfile}", vars()) + out += BT.execute("exiv2 -v -pt {crwfile}", vars()) # sed evades TZ issue on MSVC builds #1221 out = str(out).replace('23 19:54', '23 18:54').replace('24 01:54', '23 18:54') @@ -273,7 +273,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' out = BT.Output() for jpg in ['exiv2-gc.jpg', 'exiv2-canon-powershot-s40.jpg', 'exiv2-nikon-d70.jpg']: BT.copyTestFile(jpg) - out += BT.excute('exifdata-test {jpg}', vars()) + out += BT.execute('exifdata-test {jpg}', vars()) BT.reportTest('exifdata-test', out) @@ -342,68 +342,55 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' out = BT.Output() out += 'Exiv2 test directory -----------------------------------------------------' out += 'tmp/' - out += '' - out += 'Exiv2 version ------------------------------------------------------------' + out += '\nExiv2 version ------------------------------------------------------------' # Tweak this to avoid a maintenance headache with test/data/exiv2-test.out - out += re.sub(r'exiv2.*', 'exiv2 0.27.0.0 (__ bit build)', BT.excute('exiv2 -u -V')) - out += '' + out += re.sub(r'exiv2.*', 'exiv2 0.27.0.0 (__ bit build)', BT.execute('exiv2 -u -V')) - out += 'Exiv2 help ---------------------------------------------------------------' - out += BT.excute('exiv2 -u -h') - out += '' - out += '' + out += '\nExiv2 help ---------------------------------------------------------------' + out += BT.execute('exiv2 -u -h') - out += 'Adjust -------------------------------------------------------------------' - out += BT.excute('exiv2 -u -v -a-12:01:01 adjust {images_1_str}', vars(), expected_returncodes=[253]) - out += '' + out += '\n\nAdjust -------------------------------------------------------------------' + out += BT.execute('exiv2 -u -v -a-12:01:01 adjust {images_1_str}', vars(), expected_returncodes=[253]) - out += 'Rename -------------------------------------------------------------------' - out += BT.excute('exiv2 -u -vf rename {images_1_str}', vars(), expected_returncodes=[253]) - out += '' + out += '\nRename -------------------------------------------------------------------' + out += BT.execute('exiv2 -u -vf rename {images_1_str}', vars(), expected_returncodes=[253]) - out += 'Print --------------------------------------------------------------------' - out += BT.excute('exiv2 -u -v print {images_2_str}', vars(), expected_returncodes=[253]) + out += '\nPrint --------------------------------------------------------------------' + out += BT.execute('exiv2 -u -v print {images_2_str}', vars(), expected_returncodes=[253]) out += '' - out += BT.excute('exiv2 -u -v -b -pt print {images_2_str}', vars()) - stdout, stderr = BT.excute('exiv2 -u -v -b -pt print {images_2_str}', vars(), mix_stdout_and_stderr=False) + 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) BT.save(stdout, 'iii') out += stderr - out += '' - out += 'Extract Exif data --------------------------------------------------------' - out += BT.excute('exiv2 -u -vf extract {images_2_str}', vars()) - out += '' + out += '\nExtract Exif data --------------------------------------------------------' + out += BT.execute('exiv2 -u -vf extract {images_2_str}', vars()) - out += 'Extract Thumbnail --------------------------------------------------------' - out += BT.excute('exiv2 -u -vf -et extract {images_2_str}', vars(), expected_returncodes=[253]) - stdout, stderr = BT.excute('exiv2 -u -v -b -pt print {images_3_str}', vars(), mix_stdout_and_stderr=False) + 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) BT.save(stdout, 'jjj') out += stderr - out += '' - out += 'Compare image data and extracted data ------------------------------------' + out += '\nCompare image data and extracted data ------------------------------------' out += BT.diff('iii', 'jjj') - out += '' - out += 'Delete Thumbnail ---------------------------------------------------------' - out += BT.excute('exiv2 -u -v -dt delete {images_2_str}', vars()) - out += BT.excute('exiv2 -u -vf -et extract {images_2_str}', vars(), expected_returncodes=[253]) - out += '' + out += '\nDelete Thumbnail ---------------------------------------------------------' + out += BT.execute('exiv2 -u -v -dt delete {images_2_str}', vars()) + out += BT.execute('exiv2 -u -vf -et extract {images_2_str}', vars(), expected_returncodes=[253]) - out += 'Delete Exif data ---------------------------------------------------------' - out += BT.excute('exiv2 -u -v delete {images_2_str}', vars()) - out += BT.excute('exiv2 -u -v print {images_2_str}', vars(), expected_returncodes=[253]) - out += '' + out += '\nDelete Exif data ---------------------------------------------------------' + out += BT.execute('exiv2 -u -v delete {images_2_str}', vars()) + out += BT.execute('exiv2 -u -v print {images_2_str}', vars(), expected_returncodes=[253]) - out += 'Insert Exif data ---------------------------------------------------------' - out += BT.excute('exiv2 -u -v insert {images_2_str}', vars()) - stdout, stderr = BT.excute('exiv2 -u -v -b -pt print {images_3_str}', vars(), mix_stdout_and_stderr=False) + 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) BT.save(stdout, 'kkk') out += stderr - out += '' - out += 'Compare original and inserted image data ---------------------------------' + out += '\nCompare original and inserted image data ---------------------------------' out += BT.diff('iii', 'kkk') BT.reportTest('exiv2-test', out) @@ -418,21 +405,21 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' out = BT.Output() out += '--- show GPSInfo tags ---' - out += BT.excute('exiv2 -pa --grep GPSInfo {jpg}', vars()) + out += BT.execute('exiv2 -pa --grep GPSInfo {jpg}', vars()) out += '--- deleting the GPSInfo tags' - for tag in BT.excute('exiv2 -Pk --grep GPSInfo {jpg}', vars()).split('\n'): + for tag in BT.execute('exiv2 -Pk --grep GPSInfo {jpg}', vars()).split('\n'): tag = tag.rstrip(' ') - out += BT.excute('exiv2 -M"del {tag}" {jpg}', vars()) - out += BT.excute('exiv2 -pa --grep GPS {jpg}', vars(), expected_returncodes=[0, 1]) + out += BT.execute('exiv2 -M"del {tag}" {jpg}', vars()) + out += BT.execute('exiv2 -pa --grep GPS {jpg}', vars(), expected_returncodes=[0, 1]) out += '--- run geotag ---' - geotag_out = BT.excute('geotag -ascii -tz -8:00 {jpg} {gpx}', vars()) + geotag_out = BT.execute('geotag -ascii -tz -8:00 {jpg} {gpx}', vars()) geotag_out = geotag_out.split('\n')[0].split(' ')[1:] out += ' '.join(geotag_out) out += '--- show GPSInfo tags ---' - out += BT.excute('exiv2 -pa --grep GPSInfo {jpg}', vars()) + out += BT.execute('exiv2 -pa --grep GPSInfo {jpg}', vars()) BT.reportTest('geotag-test', out) @@ -446,15 +433,15 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' if img == 'Reagan2.jp2': return if img == 'exiv2-bug1199.webp': - out += BT.excute('exiv2 --comment abcdefg {img}', vars(), expected_returncodes=[0,1]) - out += BT.excute('exiv2 -pS {img}', vars()) + out += BT.execute('exiv2 --comment abcdefg {img}', vars(), expected_returncodes=[0,1]) + out += BT.execute('exiv2 -pS {img}', vars()) out += '' else: - out += BT.excute('exiv2 --comment abcdefg {img}', vars()) - out += BT.excute('exiv2 -pS {img}', vars()) - out += BT.excute('exiv2 -pc {img}', vars()) - out += BT.excute('exiv2 -dc {img}', vars()) - out += BT.excute('exiv2 -pS {img}', vars()) + out += BT.execute('exiv2 --comment abcdefg {img}', vars()) + out += BT.execute('exiv2 -pS {img}', vars()) + out += BT.execute('exiv2 -pc {img}', vars()) + out += BT.execute('exiv2 -dc {img}', vars()) + out += BT.execute('exiv2 -pS {img}', vars()) return str(out) or None # num = 1074 # ICC Profile Support @@ -470,28 +457,28 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' for i in ['large.icc', 'small.icc', img]: BT.copyTestFile(i) - out += BT.excute('exiv2 -pS {img}', vars()) - BT.save(BT.excute('exiv2 -pC {img}', vars(), return_in_bytes=True), + out += BT.execute('exiv2 -pS {img}', vars()) + BT.save(BT.execute('exiv2 -pC {img}', vars(), return_in_bytes=True), stub + '_1.icc') - out += BT.excute('exiv2 -eC --force {img}', vars()) + out += BT.execute('exiv2 -eC --force {img}', vars()) BT.mv(iccname, stub + '_2.icc') out += test1120(img) BT.copyTestFile('large.icc', iccname) - out += BT.excute('exiv2 -iC {img}', vars()) - BT.save(BT.excute('exiv2 -pC {img}', vars(), return_in_bytes=True), + out += BT.execute('exiv2 -iC {img}', vars()) + BT.save(BT.execute('exiv2 -pC {img}', vars(), return_in_bytes=True), stub + '_large_1.icc') - out += BT.excute('exiv2 -pS {img}', vars()) - out += BT.excute('exiv2 -eC --force {img}', vars()) + out += BT.execute('exiv2 -pS {img}', vars()) + out += BT.execute('exiv2 -eC --force {img}', vars()) BT.mv(iccname, stub + '_large_2.icc') out += test1120(img) BT.copyTestFile('small.icc', iccname) - out += BT.excute('exiv2 -iC {img}', vars()) - BT.save(BT.excute('exiv2 -pC {img}', vars(), return_in_bytes=True), + out += BT.execute('exiv2 -iC {img}', vars()) + BT.save(BT.execute('exiv2 -pC {img}', vars(), return_in_bytes=True), stub + '_small_1.icc') - out += BT.excute('exiv2 -pS {img}', vars()) - out += BT.excute('exiv2 -eC --force {img}', vars()) + out += BT.execute('exiv2 -pS {img}', vars()) + out += BT.execute('exiv2 -eC --force {img}', vars()) BT.mv(iccname, stub + '_small_2.icc') out += test1120(img) @@ -527,8 +514,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' pass_count = 0 fail_count = 0 out = BT.Output() - out += '' - out += 'Erase all tests' + + out += '\n--- Erase all tests ---' for i in test_files + erase_test_files: if BT.eraseTest(i): pass_count += 1 @@ -536,8 +523,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' fail_count += 1 out += 'Failed: ' + i - out += '' - out += 'Copy all tests' + out += '\n--- Copy all tests ---' for num, src in enumerate(test_files, 1): for dst in test_files: if BT.copyTest(num, src, dst): @@ -546,8 +532,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' fail_count += 1 out += 'Failed: {}'.format((num, src, dst)) - out += '' - out += 'Copy iptc tests' + out += '\n--- Copy iptc tests ---' for num, src in enumerate(test_files, 1): for dst in test_files: if BT.iptcTest(num, src, dst): @@ -556,11 +541,10 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' fail_count += 1 out += 'Failed: {}'.format((num, src, dst)) - out += '' - out += '{} passed, {} failed'.format(pass_count, fail_count) + out += '\n--------------------\n' + out += '{} passed, {} failed\n'.format(pass_count, fail_count) if fail_count: - raise RuntimeError('\n' + str(out)) - # BT.reportTest('imagetest', out) + raise RuntimeError(str(out) + '\n' + BT.log.to_str()) def io_test(self): @@ -576,26 +560,32 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42''' result += [BT.md5sum(i) for i in files] return ' '.join(result) - server_url = 'http://{}:{}'.format(BT.Config.http_server_bind, - BT.Config.http_server_port) - server = BT.HttpServer(bind=BT.Config.http_server_bind, - port=BT.Config.http_server_port, - work_dir=os.path.join(BT.Config.data_dir)) + server_url = 'http://{}:{}'.format(BT.Config.exiv2_http, + BT.Config.exiv2_port) + server = BT.HttpServer(bind=BT.Config.exiv2_http, + port=BT.Config.exiv2_port, + work_dir=BT.Config.data_dir) try: server.start() out = BT.Output() for img in ['table.jpg', 'Reagan.tiff', 'exiv2-bug922a.jpg']: files = ['s0', 's1', 's2', '{}/{}'.format(server_url, img)] - out += BT.excute('iotest ' + ' '.join(files)) + out += BT.execute('iotest ' + ' '.join(files)) for f in files: - out += BT.excute('exiv2 -g City -g DateTime {f}', vars()) + out += BT.execute('exiv2 -g City -g DateTime {f}', vars()) for num in ['0', '10', '1000']: - out += BT.excute('iotest s0 s1 s2 {server_url}/table.jpg {num}', vars()) + out += BT.execute('iotest s0 s1 s2 {server_url}/table.jpg {num}', vars()) out += sniff('s0', 's1', 's2', os.path.join(BT.Config.data_dir, 'table.jpg')) + + except Exception as e: + BT.log.error(e) + raise RuntimeError('\n' + BT.log.to_str()) + finally: - server.stop() - # print('keep the server running...') + server.stop() # While you're debugging, you can comment this line to keep the server running + pass BT.reportTest('iotest', out) + diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index 617bc16f..d974ef77 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -7,9 +7,16 @@ import re import shlex import shutil import subprocess +import time from http import server +from urllib import request +""" +Part 1: +Here is the configuration part of test cases. +""" + 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. @@ -24,72 +31,17 @@ class Config: """ Init test environments and variables """ os.makedirs(cls.tmp_dir, exist_ok=True) os.chdir(cls.tmp_dir) - log.buffer = [] - cls.bin_files = [i.split('.')[0] for i in os.listdir(cls.bin_dir)] - cls.encoding = 'utf-8' - cls.http_server_bind = '127.0.0.1' - cls.http_server_port = 12760 + log.buffer = [] + cls.bin_files = [i.split('.')[0] for i in os.listdir(cls.bin_dir)] + cls.encoding = 'utf-8' + cls.exiv2_http = '127.0.0.1' + cls.exiv2_port = 12760 -class Log: - - def __init__(self): - self.buffer = [] - - def to_str(self): - return '\n'.join(self.buffer) - - def add(self, msg): - self.buffer.append(msg) - - def info(self, msg, index=None): - self.add('[INFO] {}'.format(msg)) - - def warn(self, msg): - self.add('[WARN] {}'.format(msg)) - - def error(self, msg): - self.add('[ERROR] {}'.format(msg)) - - -log = Log() - - -class Output: - """ - Simulate the stdout buffer. - You can use `out+=x` to simulate `print(x)` - - Sample: - >>> out = Output() - >>> out - >>> str(out) - >>> out += 'Hello' - >>> out += 1 - >>> out += ['Hi' , 2] - >>> out += None # no effect - >>> str(out) - """ - def __init__(self): - self.lines = [] - self.newline = '\n' - - def __str__(self): - return self.newline.join(self.lines) - - # def __repr__(self): - # return str(self) - - def __add__(self, other): - if other or other == '': - self.lines.append(str(other)) - return self - - def __radd__(self, other): - if other or other == '': - self.lines.append(str(other)) - return self - +""" +Part 2: +Here are some common functions that are poorly coupled with test cases. +""" def cp(src, dest): """ It is used to copy one file, cannot handle directories """ @@ -155,19 +107,21 @@ def diff(file1, file2, encoding=None): encoding = encoding or Config.encoding texts = [] for f in [file1, file2]: - text = cat(f, encoding=encoding) - # Ignore whitespace characters - for i in '\t\r\v\f': - text = text.replace(i, ' ') + with open(f, encoding=encoding) as f: + text = f.read() + text = text.replace('\r\n', '\n') # Ignore line breaks for Windows texts += [text.split('\n')] text1, text2 = texts output = [] new_part = True - i = 0 + num = 0 for line in difflib.unified_diff(text1, text2, fromfile=file1, tofile=file2, lineterm=''): - i += 1 - if i < 3: + num += 1 + if num < 3: + # line = line.replace('--- ', '<<< ') + # line = line.replace('+++ ', '>>> ') + # output += [line] continue flag = line[0] @@ -179,7 +133,8 @@ def diff(file1, file2, encoding=None): new_part = False output += ['---'] elif flag == ' ': # line common to both sequences - new_flag = ' ' + # new_flag = ' ' + continue elif flag == '?': # line not present in either input sequence new_flag = '? ' elif flag == '@': @@ -193,7 +148,116 @@ def diff(file1, file2, encoding=None): return '\n'.join(output) +def md5sum(filename): + """ Calculate the MD5 value of the file """ + with open(filename, "rb") as f: + return hashlib.md5(f.read()).hexdigest() + + +class Log: + + def __init__(self): + self.buffer = [] + + def to_str(self): + return '\n'.join(self.buffer) + + def add(self, msg): + self.buffer.append(str(msg)) + + def info(self, msg, index=None): + self.add('[INFO] {}'.format(msg)) + + def warn(self, msg): + self.add('[WARN] {}'.format(msg)) + + def error(self, msg): + self.add('[ERROR] {}'.format(msg)) + + +log = Log() + + +class Output: + """ + Simulate the stdout buffer. + You can use `out+=x` to simulate `print(x)` + + Sample: + >>> out = Output() + >>> out + >>> str(out) + >>> out += 'Hello' + >>> out += 1 + >>> out += ['Hi' , 2] + >>> out += None # no effect + >>> str(out) + """ + def __init__(self): + self.lines = [] + self.newline = '\n' + + def __str__(self): + return self.newline.join(self.lines) + + # def __repr__(self): + # return str(self) + + def __add__(self, other): + if other or other == '': + self.lines.append(str(other)) + return self + + def __radd__(self, other): + if other or other == '': + self.lines.append(str(other)) + return self + + +class HttpServer: + def __init__(self, bind='127.0.0.1', port=80, work_dir='.'): + self.bind = bind + self.port = port + self.work_dir = work_dir + + def _start(self): + os.chdir(self.work_dir) + server.test(HandlerClass=server.SimpleHTTPRequestHandler, bind=self.bind, port=self.port) + log.error('The HTTP server exits without calling stop()') + print(log.to_str()) + + def start(self): + log.info('Starting HTTP server ...') + self.proc = multiprocessing.Process(target=self._start, name=str(self)) + self.proc.start() + time.sleep(1) + try: + with request.urlopen('http://127.0.0.1:{}'.format(self.port), timeout=3) as f: + if f.status != 200: + raise RuntimeError() + except: + raise RuntimeError('Failed to run the HTTP server') + log.info('The HTTP server started') + + def stop(self): + self.proc.terminate() + + +""" +Part 3: +Here are some functions that are highly coupled to test cases. +""" + +def copyTestFile(src, dest=''): + """ Copy one test file from data_dir to tmp_dir """ + if not dest: + dest = src + shutil.copy(os.path.join(Config.data_dir, src), + os.path.join(Config.tmp_dir, dest)) + + def simply_diff(file1, file2, encoding=None): + """ Find the first different line of the two text files """ encoding = encoding or Config.encoding list1 = cat(file1, encoding=encoding).split('\n') list2 = cat(file2, encoding=encoding).split('\n') @@ -214,50 +278,56 @@ def simply_diff(file1, file2, encoding=None): return '\n'.join(report) -def copyTestFile(src, dest=''): - """ Copy one test file from data_dir to tmp_dir """ - if not dest: - dest = src - shutil.copy(os.path.join(Config.data_dir, src), - os.path.join(Config.tmp_dir, dest)) - - -def excute(cmd: str, vars_dict=dict(), - expected_returncodes=[0], - mix_stdout_and_stderr=True, - encoding=None, - return_in_bytes=False): +def execute(cmd: str, + vars_dict=dict(), + stdin: (str, bytes) = None, + encoding=None, + expected_returncodes=[0], + return_in_bytes=False, + mix_stdout_and_stderr=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_in_bytes is true. Otherwise, the output is decoded to a str and returned. Sample: - >>> excute('echo Hello') - >>> excute('exiv2 --help') + >>> 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]) + + encoding = encoding or Config.encoding + if stdin: + if not isinstance(stdin, bytes): + stdin = str(stdin).encode(encoding) + if mix_stdout_and_stderr: stderr_to = subprocess.STDOUT else: stderr_to = subprocess.PIPE - p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=stderr_to, cwd=Config.tmp_dir) - output = p.communicate() # Assign (stdout, stderr) to output + + 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() output = [i or b'' for i in output] output = [i.rstrip(b'\n') for i in output] - encoding = encoding or Config.encoding if not return_in_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 p.returncode not in expected_returncodes: - log.error('Failed to excute: {}'.format(' '.join(args))) - log.error('The expected return code is {}, but get {}'.format(str(expected_returncodes), p.returncode)) + + if expected_returncodes and proc.returncode not in expected_returncodes: + log.error('Failed to execute: {}'.format(' '.join(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: return output[0] + output[1] or None else: @@ -276,48 +346,24 @@ def reportTest(testname, output: str, encoding=None): output_file = os.path.join(Config.tmp_dir, '{}.out'.format(testname)) save(output, output_file, encoding=encoding) log.info('The output has been saved to file {}'.format(output_file)) - log.info('diff:\n' + str(simply_diff(reference_file, output_file, encoding=encoding))) + log.info('simply_diff:\n' + str(simply_diff(reference_file, output_file, encoding=encoding))) raise RuntimeError('\n' + log.to_str()) -def md5sum(filename): - """ Calculate the MD5 value of the file """ - with open(filename, "rb") as f: - return hashlib.md5(f.read()).hexdigest() - - def ioTest(filename): src = os.path.join(Config.data_dir, filename) out1 = os.path.join(Config.tmp_dir, '{}.1'.format(filename)) out2 = os.path.join(Config.tmp_dir, '{}.2'.format(filename)) - excute('iotest {src} {out1} {out2}', vars()) + execute('iotest {src} {out1} {out2}', vars()) assert md5sum(src) == md5sum(out1), 'The output file is different' assert md5sum(src) == md5sum(out2), 'The output file is different' -class HttpServer: - def __init__(self, bind='127.0.0.1', port=12760, work_dir='.'): - self.bind = bind - self.port = port - self.work_dir = work_dir - - def _start(self): - os.chdir(self.work_dir) - server.test(HandlerClass=server.SimpleHTTPRequestHandler, bind=self.bind, port=self.port) - - def start(self): - self.process = multiprocessing.Process(target=self._start) - self.process.start() - - def stop(self): - self.process.terminate() - - def eraseTest(filename): test_file = filename + '.etst' good_file = os.path.join(Config.data_dir, filename + '.egd') copyTestFile(filename, test_file) - excute('metacopy {test_file} {test_file}', vars()) + execute('metacopy {test_file} {test_file}', vars()) return md5sum(test_file) == md5sum(good_file) @@ -326,7 +372,7 @@ def copyTest(num, src, dst): good_src = os.path.join(Config.data_dir, src) good_dst = os.path.join(Config.data_dir, '{}.c{}gd'.format(dst, num)) copyTestFile(dst, test_file) - excute('metacopy -a {good_src} {test_file}', vars()) + execute('metacopy -a {good_src} {test_file}', vars()) return md5sum(test_file) == md5sum(good_dst) @@ -335,6 +381,5 @@ def iptcTest(num, src, dst): good_src = os.path.join(Config.data_dir, src) good_dst = os.path.join(Config.data_dir, '{}.i{}gd'.format(dst, num)) copyTestFile(dst, test_file) - excute('metacopy -ip {good_src} {test_file}', vars()) + execute('metacopy -ip {good_src} {test_file}', vars()) return md5sum(test_file) == md5sum(good_dst) -