From 65927f5ce127afc6b181a0303366172c99f13385 Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Mon, 14 Sep 2020 20:00:40 +0800 Subject: [PATCH 01/12] Refactor stdin-test.sh to stdin_test() --- tests/bash_tests/testcases.py | 61 +++++++++++++++++++++++++++++++++++ tests/bash_tests/utils.py | 14 +++++++- tests/requirements.txt | 1 + 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tests/requirements.txt diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index 8362a294..f9161670 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -947,3 +947,64 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.reportTest('preview-test', out) + + def stdin_test(self): + # Test driver for stdin + out = BT.Output() + a = 'exiv2-bug1229.jpg' # jpg with 2 APP1/xap segments + b = 'girl.jpg' + BT.copyTestFile(a) + + def get_xmpData(img): + e = BT.Executer('exiv2 -pX {img}', vars(), decode_output=False) + return e.stdout.replace(b'\n', b'\r\n', 16) # Ignore the difference in newline + + BT.copyTestFile(a, b) + out += BT.Executer('exiv2 -pS {b}', vars()) + out += BT.Executer('exiv2 -dX {b}', vars()) # remove first + out += BT.Executer('exiv2 -pS {b}', vars()) + + e = BT.Executer('exiv2 -pX {a}', vars(), decode_output=False) + with open('out2', 'wb') as f: + f.write(e.stdout) + + out += BT.Executer('exiv2 -iXX- {b}', vars(), stdin=get_xmpData(a)) + out += BT.Executer('exiv2 -pS {b}', vars()) + + BT.copyTestFile(a, b) + out += BT.Executer('exiv2 -dX {b}', vars()) + out += BT.Executer('exiv2 -dX {b}', vars()) + out += BT.Executer('exiv2 -pS {b}', vars()) + out += BT.Executer('exiv2 -iXX- {b}', vars(), stdin=get_xmpData(a)) + out += BT.Executer('exiv2 -pS {b}', vars()) + + for f in ['Reagan.jpg', 'Reagan.tiff', 'ReaganSmallPng.png']: + BT.copyTestFile(f) + out += BT.Executer('exiv2 -iXX- {f}', vars(), stdin=get_xmpData(a)) + e = BT.Executer('exiv2 -pX {f}', vars()) + out += """ + + +{} + +""".strip('\n').format(BT.pretty_xml(e.stdout)) + + for f in ['Reagan.jpg', 'ReaganSmallPng.png']: + BT.copyTestFile(f) + BT.copyTestFile(a, b) + out += BT.Executer('exiv2 -pS {b}', vars()) + e = BT.Executer('exiv2 -ea- {f}', vars(), decode_output=False) + out += BT.Executer('exiv2 -ia- {b}', vars(), stdin=e.stdout) + out += BT.Executer('exiv2 -pS {b}', vars()) + + BT.copyTestFile('Reagan.tiff') # 1272 ReaganLargeTiff.tiff + for f in ['Reagan.jpg', 'ReaganSmallPng.png', 'exiv2-bug1199.webp']: + BT.copyTestFile(f) + e = BT.Executer('exiv2 -eC- Reagan.tiff', decode_output=False) + out += BT.Executer('exiv2 -iC- {f}', vars(), stdin=e.stdout) + out += BT.Executer('exiv2 -pS {f}', vars()) + if f == 'Reagan.jpg': + with open('out2', 'wb') as f: + f.write(e.stdout) + + BT.reportTest('stdin-test', out) diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index 6a3005a1..4a5e213d 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -249,6 +249,18 @@ def md5sum(filename): return hashlib.md5(f.read()).hexdigest() +def pretty_xml(text, encoding=None): + """ + Add indent to the XML text + Required installation: pip install lxml + """ + from lxml import etree + encoding = encoding or Config.encoding + root = etree.fromstring(text) + etree.indent(root) + return etree.tostring(root).decode(encoding) + + class Log: def __init__(self): @@ -353,7 +365,7 @@ def simply_diff(file1, file2, encoding=None): class Executer: """ - Execute a command in the shell, return a decorated `Subprocess.Popen` object. + Execute a command in the shell, return a `Executer` object. - If a binary of Exiv2 is executed, the absolute path is automatically added. - `adjust_output`: whether to filter path delimiters, whitespace characters in output - `decode_output`: whether to decode output from bytes to str diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 00000000..64d4f9d6 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1 @@ +lxml==4.5.2 From c121fbeb3873d02e88fbf8bbc3f03e8211c991eb Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Mon, 14 Sep 2020 20:03:00 +0800 Subject: [PATCH 02/12] Refactor stringto-test.sh to stringto_test() --- tests/bash_tests/testcases.py | 12 ++++++++++-- tests/requirements.txt | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index f9161670..a3e2abc3 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -957,13 +957,13 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 def get_xmpData(img): e = BT.Executer('exiv2 -pX {img}', vars(), decode_output=False) - return e.stdout.replace(b'\n', b'\r\n', 16) # Ignore the difference in newline + return e.stdout.replace(b'\n', b'\r\n', 16) # Ignore the difference in newline BT.copyTestFile(a, b) out += BT.Executer('exiv2 -pS {b}', vars()) out += BT.Executer('exiv2 -dX {b}', vars()) # remove first out += BT.Executer('exiv2 -pS {b}', vars()) - + e = BT.Executer('exiv2 -pX {a}', vars(), decode_output=False) with open('out2', 'wb') as f: f.write(e.stdout) @@ -1008,3 +1008,11 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 f.write(e.stdout) BT.reportTest('stdin-test', out) + + + def stringto_test(self): + # Test driver for tests of stringToLong/Float/Rational + out = BT.Output() + out += BT.Executer('stringto-test') + BT.reportTest('stringto-test', out) + diff --git a/tests/requirements.txt b/tests/requirements.txt index 64d4f9d6..ab90481d 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1 +1 @@ -lxml==4.5.2 +lxml From ae1d95d4fa9c22e8e1da6aeaefb5ff8c7f101ea1 Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Wed, 16 Sep 2020 22:22:08 +0800 Subject: [PATCH 03/12] Refactor tiff-test.sh to tiff_test() --- tests/bash_tests/testcases.py | 80 +++++++++++++++++++++++++++++++++++ tests/bash_tests/utils.py | 25 ++++++----- 2 files changed, 95 insertions(+), 10 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index a3e2abc3..8c4240e4 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -1016,3 +1016,83 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += BT.Executer('stringto-test') BT.reportTest('stringto-test', out) + + def tiff_test(self): + # TIFF parser test driver + + def exifprobe(img): + out = BT.Output() + + # Convert each line from that format: + # Exif.Image.NewSubfileType Long 1 Primary image + # to that format: + # NewSubfileType Long 1 "Primary image" + tags = [] + typs = [] + lens = [] + vals = [] + e = BT.Executer('exiv2 -pa {img}', vars(), redirect_stderr_to_stdout=False) + for line in e.stdout.split('\n'): + fields = re.findall(r'^(\S*)\s*(\S*)\s*(\d*)\s*(.*)$', line)[0] + tags += [fields[0].split('.')[2]] # tag + typs += [fields[1]] # type + lens += [fields[2]] # length + vals += [fields[3]] # value + + out += 'exiv2 -pa output' + for i in range(len(tags)): + out += ' \t '.join([tags[i], typs[i], lens[i], '"{}"'.format(vals[i])]) + + # Parse -pS output: + # address | tag | type | count | offset | value + # 254 | 0x00fe NewSubfileType | LONG | 1 | 0 | 0 + TAGS = [] + TYPS = [] + LENS = [] + VALS = [] + e = BT.Executer('exiv2 -pS {img}', vars(), redirect_stderr_to_stdout=False) + for line in e.stdout.split('\n')[2:-1]: + fields = [i.strip(' ') for i in line.split('|')] + TAGS += [fields[1].split(' ')[1]] + TYPS += [fields[2]] + LENS += [fields[3]] + VALS += [fields[5]] + + out += '\nexiv2 -pS output' + for i in range(len(TAGS)): + out += ' \t '.join([TAGS[i], TYPS[i], LENS[i], '"{}"'.format(VALS[i])]) + + out += '\nAnalysis' + out += 'count = {} COUNT = {}'.format(len(tags), len(TAGS)) + + # Make them have the same number of lines + max_lines = max(len(TAGS), len(tags)) + for _list in [tags, typs, lens, vals, TAGS, TYPS, LENS, VALS]: + _list += [''] * (max_lines - len(_list)) + + # Compare the main fields of each line + for i in range(max_lines): + if TAGS[i] != tags[i]: + out += 'TAG {} {} mismatch'.format(TAGS[i], tags[i]).replace(' ', ' ') + + TYPS[i] = TYPS[i].upper() + typs[i] = typs[i].upper() + if TYPS[i] != typs[i]: + out += 'TYPE {} {} mismatch'.format(TYPS[i], typs[i]).replace(' ', ' ') + + if LENS[i] != lens[i]: + out += 'Length {} {} mismatch'.format(LENS[i], lens[i]).replace(' ', ' ') + + if typs[i] == 'ASCII' and VALS[i] != vals[i]: + out += 'Value {} {} mismatch'.format(VALS[i], vals[i]).replace(' ', ' ') + + return str(out) + + test_file = 'mini9.tif' + BT.copyTestFile(test_file) + out = BT.Output() + out += exifprobe(test_file) + out += BT.Executer('tiff-test {test_file}', vars()) + out += exifprobe(test_file) + BT.reportTest('tiff-test', out) + diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index 4a5e213d..ea7d3738 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -343,17 +343,22 @@ def diffCheck(file1, file2, in_bytes=False, encoding=None): 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') - if list1 == list2: + encoding = encoding or Config.encoding + list1 = cat(file1, encoding=encoding).split('\n') + list2 = cat(file2, encoding=encoding).split('\n') + if list1 == list2: return - report = [] - report += ['{}: {} lines'.format(file1, len(list1))] - report += ['{}: {} lines'.format(file2, len(list2))] - max_lines = max(len(list1), len(list2)) - for i in [list1, list2]: - i += [''] * (max_lines - len(i)) # Make them have the same number of lines + + report = [] + report += ['{}: {} lines'.format(file1, len(list1))] + report += ['{}: {} lines'.format(file2, len(list2))] + + # Make them have the same number of lines + max_lines = max(len(list1), len(list2)) + for _list in [list1, list2]: + _list += [''] * (max_lines - len(_list)) + + # Compare each line for i in range(max_lines): if list1[i] != list2[i]: report += ['The first mismatch is in line {}:'.format(i + 1)] From 2d72d9aac5c54b7c55ea1a179f9444f9c9d0a0dd Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Wed, 16 Sep 2020 22:41:01 +0800 Subject: [PATCH 04/12] Add description for the module lxml --- tests/README-TESTS.md | 1 + tests/bash_tests/testcases.py | 7 +++++++ tests/bash_tests/utils.py | 1 - 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/README-TESTS.md b/tests/README-TESTS.md index a7324377..408ae3ec 100644 --- a/tests/README-TESTS.md +++ b/tests/README-TESTS.md @@ -39,6 +39,7 @@ for Python 2). Then navigate to the `tests/` subdirectory and run: ``` shell +python3 -m pip install -r requirements.txt python3 runner.py ``` diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index 8c4240e4..5ce65eb5 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -950,6 +950,13 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 def stdin_test(self): # Test driver for stdin + try: + import lxml + except ModuleNotFoundError: + print('ignored') + print('Missing module lxml, please install: `pip install lxml`') + return + out = BT.Output() a = 'exiv2-bug1229.jpg' # jpg with 2 APP1/xap segments b = 'girl.jpg' diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index ea7d3738..e85ba6dd 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -252,7 +252,6 @@ def md5sum(filename): def pretty_xml(text, encoding=None): """ Add indent to the XML text - Required installation: pip install lxml """ from lxml import etree encoding = encoding or Config.encoding From 069cfc6c66d3bfaa788985342aab070d501b5ee4 Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Fri, 18 Sep 2020 21:32:49 +0800 Subject: [PATCH 05/12] Refactor version_test.sh to version_test() --- tests/bash_tests/testcases.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index 5ce65eb5..cb093063 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -1071,7 +1071,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += '\nAnalysis' out += 'count = {} COUNT = {}'.format(len(tags), len(TAGS)) - + # Make them have the same number of lines max_lines = max(len(TAGS), len(tags)) for _list in [tags, typs, lens, vals, TAGS, TYPS, LENS, VALS]: @@ -1103,3 +1103,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += exifprobe(test_file) BT.reportTest('tiff-test', out) + + def version_test(self): + # Test driver for exiv2 --verbose --version + out = BT.Output() + out += BT.Executer('exiv2 --verbose --version') From 03ba77ddfd2a4387188364ce359eaa6182789efb Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Fri, 18 Sep 2020 21:34:37 +0800 Subject: [PATCH 06/12] Refactor webp-test.sh to webp_test() --- tests/bash_tests/testcases.py | 81 +++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index cb093063..a353a2de 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -1108,3 +1108,84 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 # Test driver for exiv2 --verbose --version out = BT.Output() out += BT.Executer('exiv2 --verbose --version') + + + def webp_test(self): + # Test driver for webp + webp = 'exiv2-bug1199.webp' # http://dev.exiv2.org/attachments/download/1033/Stonehenge-with-icc.webp + icc = 'exiv2-bug1199.icc' + exv = 'exiv2-bug1199.exv' + xmp = 'exiv2-bug1199.xmp' + tiff = 'Reagan.tiff' + out = BT.Output() + + # Extract the XMP + BT.copyTestFile(webp) + out += BT.Executer('exiv2 -pS {webp}', vars()) + e = BT.Executer('exiv2 -pX {webp}', vars()) + out += """ + + +{} + +""".strip('\n').format(BT.pretty_xml(e.stdout)) + + # Test deleting metadata + for option in ['-dC', '-de', '-dx', '-dCe', '-dCx', '-dCxe']: + BT.copyTestFile(webp) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 {option} {webp}', vars()) + out += BT.Executer('exiv2 -pS {webp}', vars()) + + # Extract the icc + BT.copyTestFile(webp) + BT.copyTestFile(tiff) + out += BT.Executer('exiv2 -pS {webp}', vars()) + BT.save(BT.Executer( 'exiv2 -pC {tiff}', vars(), decode_output=False).stdout, icc) + out += BT.Executer('exiv2 -iC {webp}', vars()) + out += BT.Executer('exiv2 -pS {webp}', vars()) + + # Copy the XMP from the test file + BT.copyTestFile(webp) + BT.save(BT.Executer( 'exiv2 -pX {tiff}', vars(), decode_output=False).stdout, xmp) + out += BT.Executer('exiv2 -ea --force {webp}', vars()) + + BT.copyTestFile(webp) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 -iXX {webp}', vars()) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 -ix {webp}', vars()) + + # Copy the XMP from Reagan.tiff to test file + BT.copyTestFile(tiff) + BT.save(BT.Executer( 'exiv2 -pX {tiff}', vars(), decode_output=False).stdout, xmp) + out += BT.Executer('exiv2 -ea --force {tiff}', vars()) + BT.mv('Reagan.exv', exv) + + BT.copyTestFile(webp) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 -iXX {webp}', vars()) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 -ix {webp}', vars()) + + # Copy the XMP from exiv2-bug922.jpg to test file + BT.copyTestFile('exiv2-bug922.jpg') + BT.save(BT.Executer( 'exiv2 -pX exiv2-bug922.jpg', decode_output=False).stdout, xmp) + BT.Executer( 'exiv2 -ea --force exiv2-bug922.jpg') + BT.mv('exiv2-bug922.exv', exv) + + BT.copyTestFile(webp) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 -ix {webp}', vars()) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 -iXX {webp}', vars()) + out += BT.Executer('exiv2 -pS {webp}', vars()) + + BT.copyTestFile('exiv2-bug922.jpg', webp) + out += BT.Executer('exiv2 --force -ea {webp}', vars()) + BT.copyTestFile(webp) + out += BT.Executer('exiv2 -pS {webp}', vars()) + out += BT.Executer('exiv2 -ie {webp}', vars()) + out += BT.Executer('exiv2 -pS {webp}', vars()) + + BT.reportTest('webp-test', out) From 7c45ce4dec5715c25155015175ca596185ba929b Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Sat, 19 Sep 2020 14:47:19 +0800 Subject: [PATCH 07/12] Optimize diff() --- tests/bash_tests/testcases.py | 19 ++++++++++--------- tests/bash_tests/utils.py | 17 +++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index a353a2de..b055c36d 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -374,18 +374,18 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += BT.Executer('exiv2 -u -v print {images_2_str}', vars(), assert_returncode=[253]) out += '' out += BT.Executer('exiv2 -u -v -b -pt print {images_2_str}', vars()) - e = BT.Executer('exiv2 -u -v -b -pt print {images_2_str}', vars(), redirect_stderr_to_stdout=False) + e = BT.Executer('exiv2 -u -v -b -pt print {images_2_str}', vars(), redirect_stderr_to_stdout=False, decode_output=False) BT.save(e.stdout, 'iii') - out += e.stderr + out += e.stderr.decode() out += '\nExtract Exif data --------------------------------------------------------' out += BT.Executer('exiv2 -u -vf extract {images_2_str}', vars()) out += '\nExtract Thumbnail --------------------------------------------------------' out += BT.Executer('exiv2 -u -vf -et extract {images_2_str}', vars(), assert_returncode=[253]) - e = BT.Executer('exiv2 -u -v -b -pt print {images_3_str}', vars(), redirect_stderr_to_stdout=False) + e = BT.Executer('exiv2 -u -v -b -pt print {images_3_str}', vars(), redirect_stderr_to_stdout=False, decode_output=False) BT.save(e.stdout, 'jjj') - out += e.stderr + out += e.stderr.decode() out += '\nCompare image data and extracted data ------------------------------------' out += BT.diff('iii', 'jjj') @@ -400,9 +400,9 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += '\nInsert Exif data ---------------------------------------------------------' out += BT.Executer('exiv2 -u -v insert {images_2_str}', vars()) - e = BT.Executer('exiv2 -u -v -b -pt print {images_3_str}', vars(), redirect_stderr_to_stdout=False) + e = BT.Executer('exiv2 -u -v -b -pt print {images_3_str}', vars(), redirect_stderr_to_stdout=False, decode_output=False) BT.save(e.stdout, 'kkk') - out += e.stderr + out += e.stderr.decode() out += '\nCompare original and inserted image data ---------------------------------' out += BT.diff('iii', 'kkk') @@ -472,7 +472,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.copyTestFile(i) out += BT.Executer('exiv2 -pS {img}', vars()) - e = BT.Executer('exiv2 -pC {img}', vars(), adjust_output=False, decode_output=False) + e = BT.Executer('exiv2 -pC {img}', vars(), compatible_output=False, decode_output=False) BT.save(e.stdout, stub + '_1.icc') out += BT.Executer('exiv2 -eC --force {img}', vars()) BT.mv(iccname, stub + '_2.icc') @@ -480,7 +480,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.copyTestFile('large.icc', iccname) out += BT.Executer('exiv2 -iC {img}', vars()) - e = BT.Executer('exiv2 -pC {img}', vars(), adjust_output=False, decode_output=False) + e = BT.Executer('exiv2 -pC {img}', vars(), compatible_output=False, decode_output=False) BT.save(e.stdout, stub + '_large_1.icc') out += BT.Executer('exiv2 -pS {img}', vars()) out += BT.Executer('exiv2 -eC --force {img}', vars()) @@ -489,7 +489,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.copyTestFile('small.icc', iccname) out += BT.Executer('exiv2 -iC {img}', vars()) - e = BT.Executer('exiv2 -pC {img}', vars(), adjust_output=False, decode_output=False) + e = BT.Executer('exiv2 -pC {img}', vars(), compatible_output=False, decode_output=False) BT.save(e.stdout, stub + '_small_1.icc') out += BT.Executer('exiv2 -pS {img}', vars()) out += BT.Executer('exiv2 -eC --force {img}', vars()) @@ -1189,3 +1189,4 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += BT.Executer('exiv2 -pS {webp}', vars()) BT.reportTest('webp-test', out) + diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index e85ba6dd..77ba2227 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -158,7 +158,7 @@ def diff(file1, file2, encoding=None): output = [] new_part = True num = 0 - for line in difflib.unified_diff(text1, text2, fromfile=file1, tofile=file2, lineterm=''): + for line in difflib.unified_diff(text1, text2, fromfile=file1, tofile=file2, n=0, lineterm=''): num += 1 if num < 3: # line = line.replace('--- ', '<<< ') @@ -207,7 +207,7 @@ def diff_bytes(file1, file2, return_str=False): new_part = True num = 0 for line in difflib.diff_bytes(difflib.unified_diff, text1, text2, - fromfile=file1.encode(), tofile=file2.encode(), lineterm=b''): + fromfile=file1.encode(), tofile=file2.encode(), n=0, lineterm=b''): num += 1 if num < 3: line = line.decode() @@ -371,8 +371,8 @@ class Executer: """ Execute a command in the shell, return a `Executer` object. - If a binary of Exiv2 is executed, the absolute path is automatically added. - - `adjust_output`: whether to filter path delimiters, whitespace characters in output - - `decode_output`: whether to decode output from bytes to str + - `compatible_output=True`: filter out path delimiters, whitespace characters in output + - `decode_output=True`: decode output from bytes to str Sample: >>> Executer('echo Hello').stdout @@ -386,7 +386,7 @@ class Executer: stdin: (str, bytes) = None, redirect_stderr_to_stdout=True, assert_returncode=[0], - adjust_output=True, + compatible_output=True, decode_output=True): self.cmd = cmd.format(**vars_dict) self.cwd = cwd or Config.tmp_dir @@ -397,8 +397,8 @@ class Executer: self.redirect_stderr_to_stdout = redirect_stderr_to_stdout self.assert_returncode = assert_returncode # self.returncode = 0 - self.adjust_output = adjust_output - self.decode_output = decode_output + self.compatible_output = compatible_output + self.decode_output = decode_output # Generate the args for subprocess.Popen args = self.cmd.split(' ', maxsplit=1) @@ -438,7 +438,7 @@ class Executer: output = [i.rstrip(b'\r\n').rstrip(b'\n') for i in output] # Remove the last line break of the output # Extract stdout and stderr - if self.adjust_output: + if self.compatible_output: 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 self.decode_output: @@ -608,3 +608,4 @@ def extendedTest(filename): e = Executer('iptcprint {tmp}', vars(), decode_output=False) save(e.stdout + b'\n', test_file) return diffCheck(good_file, test_file, in_bytes=True) + From 184af474d07d2c703ec8674e3b1cd7db916cfe1c Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Sat, 19 Sep 2020 14:54:36 +0800 Subject: [PATCH 08/12] Refactor write-test.sh to write_test() --- tests/bash_tests/testcases.py | 52 ++++++++++++++++++++++++++++++++--- tests/bash_tests/utils.py | 23 ++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index b055c36d..60f1c45d 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -231,12 +231,12 @@ class TestCases(unittest.TestCase): out += BT.Executer('exiv2 -M"del Xmp.mwg-rs.Regions" DSC_3079.jpg') out += BT.Executer('exiv2 -px DSC_3079.jpg') - # Ignore the output differences on Windows + # Ignore output differences on Windows for pair in [ - ('charset="Jis"', 'charset=Jis'), + ('charset="Jis"' , 'charset=Jis'), ('charset="Unicode"', 'charset=Unicode'), - (' 9 Rocknroll', "11 Rock'n'roll"), - ('Rocknroll', "Rock'n'roll") + (' 9 Rocknroll' , "11 Rock'n'roll"), + ('Rocknroll' , "Rock'n'roll") ]: out = str(out).replace(pair[0], pair[1]) @@ -1190,3 +1190,47 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.reportTest('webp-test', out) + + def write_test(self): + # Test driver for the write unit tests + images = [ + 'exiv2-canon-powershot-s40.jpg' + ,'exiv2-kodak-dc210.jpg' + ,'exiv2-fujifilm-finepix-s2pro.jpg' + ,'exiv2-sigma-d10.jpg' + ,'exiv2-nikon-e990.jpg' + ,'exiv2-nikon-d70.jpg' + ,'exiv2-nikon-e950.jpg' + ] + for i in images: + BT.copyTestFile(i) + + out = BT.Output() + out += BT.runTestCase( 1, 'exiv2-canon-powershot-s40.jpg') + out += BT.runTestCase( 2, 'exiv2-canon-powershot-s40.jpg') + out += BT.runTestCase( 3, 'exiv2-kodak-dc210.jpg') + out += BT.runTestCase( 4, 'exiv2-canon-powershot-s40.jpg') + out += BT.runTestCase( 5, 'exiv2-canon-powershot-s40.jpg') + out += BT.runTestCase( 6, 'exiv2-kodak-dc210.jpg') + out += BT.runTestCase( 7, 'exiv2-fujifilm-finepix-s2pro.jpg') + out += BT.runTestCase( 8, 'exiv2-sigma-d10.jpg') + out += BT.runTestCase( 9, 'exiv2-nikon-e990.jpg') + out += BT.runTestCase(10, 'exiv2-nikon-e950.jpg') + out += BT.runTestCase(11, 'exiv2-nikon-d70.jpg') + + out = str(out) + # Adjust the output to be compatible with the reference output + for img in images: + out = out.replace('Reading file ' + img, 'Reading file ./' + img) + + # Ignore output differences between BT.diff() and GNU dIff + for pair in [ + ('24,2c24,2', '24,25c24,25'), + ('29,2c29,2', '29,30c29,30'), + ('27,2c27,2', '27,28c27,28'), + ('28,2c28,2', '28,29c28,29'), + ]: + out = out.replace(pair[0], pair[1]) + + BT.reportTest('write-test', out) + diff --git a/tests/bash_tests/utils.py b/tests/bash_tests/utils.py index 77ba2227..1f48d68b 100644 --- a/tests/bash_tests/utils.py +++ b/tests/bash_tests/utils.py @@ -609,3 +609,26 @@ def extendedTest(filename): save(e.stdout + b'\n', test_file) return diffCheck(good_file, test_file, in_bytes=True) + +def runTestCase(num, img): + """ Run the requested test case number with the given image """ + out_img = 'test{}.jpg'.format(num) + thumb_jpg = 'thumb{}.jpg'.format(num) + thumb_tif = 'thumb{}.tif'.format(num) + rm(out_img, thumb_jpg, thumb_tif) + rm('iii', 'ttt') + cp(img, out_img) + out = Output() + out += '------------------------------------------------------------' + + e = Executer('exifprint {img}', vars(), redirect_stderr_to_stdout=False, decode_output=False) + out += e.stderr.decode() if e.stderr else None + save(e.stdout, 'iii') + + e = Executer('write-test {img} {num}', vars(), redirect_stderr_to_stdout=False, decode_output=False) + out += e.stderr.decode() if e.stderr else None + save(e.stdout, 'ttt') + + out += diff('iii', 'ttt') + return str(out) + From 88671a6da73ad4f2c21d9de959a5211edff2f152 Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Sat, 19 Sep 2020 14:57:18 +0800 Subject: [PATCH 09/12] Refactor write2-test.sh to write2_test() --- tests/bash_tests/testcases.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index 60f1c45d..08c9eeb0 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -1234,3 +1234,12 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.reportTest('write-test', out) + + def write2_test(self): + # Test driver for write unit tests to build Exif metadata from scratch + img = 'exiv2-empty.jpg' + BT.copyTestFile(img) + out = BT.Output() + out += BT.Executer('write2-test {img}', vars()) + BT.reportTest('write2-test', out) + From eb4bc191fca247c83fd1aeaa3a137f43f3f3adce Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Sat, 19 Sep 2020 15:54:25 +0800 Subject: [PATCH 10/12] Refactor xmpparser-test.sh to xmpparser_test() --- tests/bash_tests/testcases.py | 52 ++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index 08c9eeb0..d2859835 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -1218,8 +1218,8 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += BT.runTestCase(10, 'exiv2-nikon-e950.jpg') out += BT.runTestCase(11, 'exiv2-nikon-d70.jpg') - out = str(out) # Adjust the output to be compatible with the reference output + out = str(out) for img in images: out = out.replace('Reading file ' + img, 'Reading file ./' + img) @@ -1243,3 +1243,53 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += BT.Executer('write2-test {img}', vars()) BT.reportTest('write2-test', out) + + def xmpparser_test(self): + # XMP parser test driver + images = ['BlueSquare.xmp', 'StaffPhotographer-Example.xmp', 'xmpsdk.xmp'] + out = BT.Output() + + for img in images: + BT.copyTestFile(img) + out += BT.Executer('xmpparser-test {img}', vars()) + out += BT.diff(img, img + '-new') + + xmp = 'xmpsdk.xmp' + BT.save(BT.Executer('xmpparse {xmp}' , vars()).stdout, 't1') + BT.save(BT.Executer('xmpparse {xmp}-new', vars()).stdout, 't2') + out += BT.diff('t1', 't2') + + out += BT.Executer('xmpsample') + for img in ['exiv2-empty.jpg', 'cmdxmp.txt']: + BT.copyTestFile(img) + out += BT.Executer('exiv2 -v -m cmdxmp.txt exiv2-empty.jpg', assert_returncode=[0, 1]) + out += BT.Executer('exiv2 -v -px exiv2-empty.jpg') + + # Ignore output differences between BT.diff() and GNU dIff + out = str(out) + out = out.replace(""" +34,0c35 +--- +> Blue Square Test File - .jpg +36c36,0 +< Blue Square Test File - .jpg +67,21c67,21 +""".strip('\n'), +""" +35d34 +< Blue Square Test File - .jpg +36a36 +> Blue Square Test File - .jpg +67,87c67,87 +""".strip('\n')) + for pair in [ + ('46,0c47\n---' , '46a47'), + ('160,32c161' , '160,191c161'), + ('1,49c1,65' , '1,48c1,65'), + ('< \n< ' , '< '), + ('> \n' , '> \n/ No newline at end of file'), + ]: + out = out.replace(pair[0], pair[1]) + + BT.reportTest('xmpparser-test', out) + From c7c1fcee59fa09a99d454b3d65c3812a43ac62a2 Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Mon, 28 Sep 2020 22:03:25 +0800 Subject: [PATCH 11/12] Ignore the difference in the path separator for stdin_test --- tests/bash_tests/testcases.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index d2859835..f30c2046 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -1005,12 +1005,27 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 out += BT.Executer('exiv2 -pS {b}', vars()) BT.copyTestFile('Reagan.tiff') # 1272 ReaganLargeTiff.tiff - for f in ['Reagan.jpg', 'ReaganSmallPng.png', 'exiv2-bug1199.webp']: - BT.copyTestFile(f) + for img in ['Reagan.jpg', 'ReaganSmallPng.png', 'exiv2-bug1199.webp']: + BT.copyTestFile(img) e = BT.Executer('exiv2 -eC- Reagan.tiff', decode_output=False) - out += BT.Executer('exiv2 -iC- {f}', vars(), stdin=e.stdout) - out += BT.Executer('exiv2 -pS {f}', vars()) - if f == 'Reagan.jpg': + + # Ignore the difference in the path separator + stdout = e.stdout + for pair in [ + (b'\x03/\x9e', b'\x03\\\x9e'), + (b'\x0c/\x0c', b'\x0c\\\x0c'), + (b'V/V' , b'V\\V' ), + (b'\xe5/5' , b'\xe5\\5' ), + (b'5/\x86' , b'5\\\x86' ), + (b'\x86/\xd6', b'\x86\\\xd6'), + (b'\xac/\xac', b'\xac\\\xac'), + (b'\xd7/\xd7', b'\xd7\\\xd7'), + ]: + stdout = stdout.replace(pair[0], pair[1]) + + out += BT.Executer('exiv2 -iC- {img}', vars(), stdin=stdout) + out += BT.Executer('exiv2 -pS {img}', vars()) + if img == 'ReaganSmallPng.png': with open('out2', 'wb') as f: f.write(e.stdout) From 0d7425014f23b0c674f850f3e7df07b5f0f93bcb Mon Sep 17 00:00:00 2001 From: LeoHsiao Date: Wed, 30 Sep 2020 21:50:07 +0800 Subject: [PATCH 12/12] Fix webp_test: correct a test file name --- tests/bash_tests/testcases.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/bash_tests/testcases.py b/tests/bash_tests/testcases.py index f30c2046..b9172f00 100644 --- a/tests/bash_tests/testcases.py +++ b/tests/bash_tests/testcases.py @@ -1156,13 +1156,13 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 BT.copyTestFile(webp) BT.copyTestFile(tiff) out += BT.Executer('exiv2 -pS {webp}', vars()) - BT.save(BT.Executer( 'exiv2 -pC {tiff}', vars(), decode_output=False).stdout, icc) + BT.save( BT.Executer('exiv2 -pC {tiff}', vars(), decode_output=False).stdout, icc) out += BT.Executer('exiv2 -iC {webp}', vars()) out += BT.Executer('exiv2 -pS {webp}', vars()) # Copy the XMP from the test file BT.copyTestFile(webp) - BT.save(BT.Executer( 'exiv2 -pX {tiff}', vars(), decode_output=False).stdout, xmp) + BT.save( BT.Executer('exiv2 -pX {webp}', vars(), decode_output=False).stdout, xmp) out += BT.Executer('exiv2 -ea --force {webp}', vars()) BT.copyTestFile(webp) @@ -1173,7 +1173,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 # Copy the XMP from Reagan.tiff to test file BT.copyTestFile(tiff) - BT.save(BT.Executer( 'exiv2 -pX {tiff}', vars(), decode_output=False).stdout, xmp) + BT.save( BT.Executer('exiv2 -pX {tiff}', vars(), decode_output=False).stdout, xmp) out += BT.Executer('exiv2 -ea --force {tiff}', vars()) BT.mv('Reagan.exv', exv) @@ -1185,7 +1185,7 @@ set Exif.Photo.DateTimeDigitized 2020:05:26 07:31:42 # Copy the XMP from exiv2-bug922.jpg to test file BT.copyTestFile('exiv2-bug922.jpg') - BT.save(BT.Executer( 'exiv2 -pX exiv2-bug922.jpg', decode_output=False).stdout, xmp) + BT.save( BT.Executer('exiv2 -pX exiv2-bug922.jpg', decode_output=False).stdout, xmp) BT.Executer( 'exiv2 -ea --force exiv2-bug922.jpg') BT.mv('exiv2-bug922.exv', exv)