From 39b7151b2e3c302458b917215d5b40e40e06cb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= Date: Tue, 5 Jun 2018 00:24:35 +0200 Subject: [PATCH 1/2] [testsuite] Port redmine issues 831 to 937 to the new testsuite --- .../issue_922_exiv2_pX_bug922_jpg_output | 9 + tests/bugfixes/redmine/test_issue_831.py | 49 +++ tests/bugfixes/redmine/test_issue_836.py | 48 +++ tests/bugfixes/redmine/test_issue_841.py | 20 + tests/bugfixes/redmine/test_issue_855.py | 65 +++ tests/bugfixes/redmine/test_issue_876.py | 19 + tests/bugfixes/redmine/test_issue_884.py | 28 ++ tests/bugfixes/redmine/test_issue_922.py | 228 ++++++++++ tests/bugfixes/redmine/test_issue_935.py | 81 ++++ tests/bugfixes/redmine/test_issue_937.py | 407 ++++++++++++++++++ 10 files changed, 954 insertions(+) create mode 100644 tests/bugfixes/redmine/issue_922_exiv2_pX_bug922_jpg_output create mode 100644 tests/bugfixes/redmine/test_issue_831.py create mode 100644 tests/bugfixes/redmine/test_issue_836.py create mode 100644 tests/bugfixes/redmine/test_issue_841.py create mode 100644 tests/bugfixes/redmine/test_issue_855.py create mode 100644 tests/bugfixes/redmine/test_issue_876.py create mode 100644 tests/bugfixes/redmine/test_issue_884.py create mode 100644 tests/bugfixes/redmine/test_issue_922.py create mode 100644 tests/bugfixes/redmine/test_issue_935.py create mode 100644 tests/bugfixes/redmine/test_issue_937.py diff --git a/tests/bugfixes/redmine/issue_922_exiv2_pX_bug922_jpg_output b/tests/bugfixes/redmine/issue_922_exiv2_pX_bug922_jpg_output new file mode 100644 index 00000000..2d8b9e2f --- /dev/null +++ b/tests/bugfixes/redmine/issue_922_exiv2_pX_bug922_jpg_output @@ -0,0 +1,9 @@ + + + + + diff --git a/tests/bugfixes/redmine/test_issue_831.py b/tests/bugfixes/redmine/test_issue_831.py new file mode 100644 index 00000000..3369869b --- /dev/null +++ b/tests/bugfixes/redmine/test_issue_831.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, CopyFiles, path + + +@CopyFiles("$data_path/mini9.tif") +class UseNonIntrusiveWriting(metaclass=CaseMeta): + + url = "http://dev.exiv2.org/issues/831" + + filename = path("$data_path/mini9_copy.tif") + + commands = [ + """$exiv2 -v -Qd -M"set Exif.Image.ImageDescription Just GIMP" $filename""", + "$exiv2 -v -pa $filename" + ] + + stdout = [ + """File 1/1: $filename +Set Exif.Image.ImageDescription "Just GIMP" (Ascii) +""", + """File 1/1: $filename +Exif.Image.NewSubfileType Long 1 Primary image +Exif.Image.ImageWidth Short 1 9 +Exif.Image.ImageLength Short 1 9 +Exif.Image.BitsPerSample Short 3 8 8 8 +Exif.Image.Compression Short 1 Uncompressed +Exif.Image.PhotometricInterpretation Short 1 RGB +Exif.Image.DocumentName Ascii 24 /home/ahuggel/mini9.tif +Exif.Image.ImageDescription Ascii 10 Just GIMP +Exif.Image.StripOffsets Long 1 8 +Exif.Image.Orientation Short 1 top, left +Exif.Image.SamplesPerPixel Short 1 3 +Exif.Image.RowsPerStrip Short 1 64 +Exif.Image.StripByteCounts Long 1 243 +Exif.Image.XResolution Rational 1 72 +Exif.Image.YResolution Rational 1 72 +Exif.Image.PlanarConfiguration Short 1 1 +Exif.Image.ResolutionUnit Short 1 inch +""" + ] + stderr = [ + """Info: Write strategy: Non-intrusive +""", + """$filename: No IPTC data found in the file +$filename: No XMP data found in the file +""" + ] + retval = [0] * 2 diff --git a/tests/bugfixes/redmine/test_issue_836.py b/tests/bugfixes/redmine/test_issue_836.py new file mode 100644 index 00000000..dd4d6488 --- /dev/null +++ b/tests/bugfixes/redmine/test_issue_836.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +import unittest +import os.path +import shutil + +import system_tests + + +RESOURCE_FORK_EXISTS = os.path.exists( + os.path.join(system_tests.data_path, "exiv2-bug836.eps/..namedfork/rsrc") +) + + +@unittest.skipUnless(RESOURCE_FORK_EXISTS, + "File system does not support resource forks") +@system_tests.CopyFiles("$data_path/exiv2-bug836.eps") +class WriteMetadataDestroysResourceForkOnMacOSXForBigFiles( + metaclass=system_tests.CaseMeta): + + url = "http://dev.exiv2.org/issues/836" + + filename = "$data_path/exiv2-bug836_copy.eps" + filename_orig = "$data_path/exiv2-bug836.eps" + + commands = [ + "$exiv2 -M'set Exif.Photo.UserComment Test' $filename", + ] + + def setUp(self): + """ Copy the rsrc file into the the resource fork """ + shutil.copyfile( + self.filename_orig + ".rsrc", self.filename + "/..namedfork/rsrc" + ) + + def post_tests_hook(self): + """ Check that the resource fork didn't change """ + with open(self.filename_orig + ".rsrc", "rb") as rsrc_orig: + expected_resource_fork = rsrc_orig.read(-1) + + with open(self.filename + "/..namedfork/rsrc", "rb") as rsrc_f: + got_resource_fork = rsrc_f.read(-1) + + self.assertEqual(expected_resource_fork, got_resource_fork) + + stdout = [""] + stderr = [""] + retval = [0] diff --git a/tests/bugfixes/redmine/test_issue_841.py b/tests/bugfixes/redmine/test_issue_841.py new file mode 100644 index 00000000..492098d7 --- /dev/null +++ b/tests/bugfixes/redmine/test_issue_841.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path + + +class ThrowOnInput(metaclass=CaseMeta): + + url = "http://dev.exiv2.org/issues/841" + + filename = path("$data_path/exiv2-bug841.png") + + commands = ["$exiv2 $filename"] + + stdout = [""] + stderr = [ + """$exiv2_exception_message $filename: +$kerFailedToReadImageData +""" + ] + retval = [1] diff --git a/tests/bugfixes/redmine/test_issue_855.py b/tests/bugfixes/redmine/test_issue_855.py new file mode 100644 index 00000000..7e399122 --- /dev/null +++ b/tests/bugfixes/redmine/test_issue_855.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path + + +class DontSegfaultWhenAccessingFocalLength(metaclass=CaseMeta): + + url = "http://dev.exiv2.org/issues/855" + + filename = path("$data_path/exiv2-bug855.jpg") + + commands = ["$exiv2 -pa $filename"] + + stdout = ["""Exif.Image.NewSubfileType Long 1 Thumbnail/Preview image +Exif.Image.Make Ascii 20 PENTAX +Exif.Image.Model Ascii 20 PENTAX K-x +Exif.Image.Orientation Short 1 top, left +Exif.Image.Software Ascii 16 darktable 0.9.3 +Exif.Image.DateTime Ascii 20 2012:01:22 01:54:26 +Exif.Image.Artist Ascii 17 SEBASTIAN WAGNER +Exif.Image.Rating SLong 1 1 +Exif.Image.RatingPercent SLong 1 20 +Exif.Image.Copyright Ascii 33 CREATIVECOMMONS ATTRIBUTION CCBY +Exif.Image.ExifTag Long 1 666 +Exif.Photo.ExposureTime Rational 1 1/20 s +Exif.Photo.FNumber Rational 1 F5.6 +Exif.Photo.ExposureProgram Short 1 Landscape mode +Exif.Photo.ISOSpeedRatings Short 1 2500 +Exif.Photo.DateTimeOriginal Ascii 20 2012:01:22 01:54:26 +Exif.Photo.DateTimeDigitized Ascii 20 2012:01:22 01:54:26 +Exif.Photo.ExposureBiasValue SRational 1 0 EV +Exif.Photo.MeteringMode Short 1 Multi-segment +Exif.Photo.Flash Short 1 No, compulsory +Exif.Photo.FocalLength Rational 0 +Exif.Photo.ColorSpace Short 1 sRGB +Exif.Photo.SensingMethod Short 1 One-chip color area +Exif.Photo.CustomRendered Short 1 Normal process +Exif.Photo.ExposureMode Short 1 Auto +Exif.Photo.WhiteBalance Short 1 Auto +Exif.Photo.FocalLengthIn35mmFilm Short 1 82.0 mm +Exif.Photo.SceneCaptureType Short 1 Landscape +Exif.Photo.Contrast Short 1 Hard +Exif.Photo.Saturation Short 1 Normal +Exif.Photo.Sharpness Short 1 Hard +Exif.Photo.SubjectDistanceRange Short 1 Macro +Exif.Image.DNGVersion Byte 4 1 1 0 0 +Exif.Image.DNGBackwardVersion Byte 4 1 1 0 0 +Exif.Image.UniqueCameraModel Ascii 11 PENTAX K-x +Exif.Image.ColorMatrix1 SRational 9 71147/65536 -36788/65536 223/65536 -28867/65536 69463/65536 28977/65536 -1276/65536 2064/65536 45215/65536 +Exif.Image.ColorMatrix2 SRational 9 68429/65536 -21793/65536 -7522/65536 -36512/65536 89125/65536 14083/65536 -7905/65536 11496/65536 48817/65536 +Exif.Image.AnalogBalance Rational 3 1/1 1/1 1/1 +Exif.Image.AsShotNeutral Rational 3 256/352 256/264 256/762 +Exif.Image.BaselineExposure SRational 1 -31775/65536 +Exif.Image.BaselineNoise Rational 1 1/1 +Exif.Image.BaselineSharpness Rational 1 1/1 +Exif.Image.LinearResponseLimit Rational 1 1/1 +Exif.Image.CalibrationIlluminant1 Short 1 17 +Exif.Image.CalibrationIlluminant2 Short 1 21 +""" + ] + stderr = [ + """Error: Upper boundary of data for directory Photo, entry 0x920a is out of bounds: Offset = 0x000003dc, size = 8, exceeds buffer size by 6 Bytes; truncating the entry +""" + ] + retval = [0] diff --git a/tests/bugfixes/redmine/test_issue_876.py b/tests/bugfixes/redmine/test_issue_876.py new file mode 100644 index 00000000..e48d63a5 --- /dev/null +++ b/tests/bugfixes/redmine/test_issue_876.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path + + +class Canon_EF_35mm_f_slash_2_IS_USM_Lens(metaclass=CaseMeta): + + url = "http://dev.exiv2.org/issues/876" + + filename = path("$data_path/exiv2-bug876.jpg") + + commands = ["$exiv2 -pt --grep Model $filename"] + + stdout = ["""Exif.Image.Model Ascii 13 Canon EOS 6D +Exif.Canon.ModelID Long 1 EOS 6D +Exif.Canon.LensModel Ascii 74 EF35mm f/2 IS USM +"""] + stderr = [""] + retval = [0] diff --git a/tests/bugfixes/redmine/test_issue_884.py b/tests/bugfixes/redmine/test_issue_884.py new file mode 100644 index 00000000..9c6c4350 --- /dev/null +++ b/tests/bugfixes/redmine/test_issue_884.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, path + + +class NewTamronAndPentaxLenses(metaclass=CaseMeta): + + url = "http://dev.exiv2.org/issues/884" + + filenames = [ + path("$data_path/exiv2-bug884{:s}.jpg".format(char)) + for char in ["a", "b", "c"] + ] + + commands = [ + "$exiv2 -pt --grep LensType " + fname for fname in filenames + ] + + stdout = [ + """Exif.Pentax.LensType Byte 2 Tamron SP AF 17-50mm F2.8 XR Di II +""", + """Exif.Pentax.LensType Byte 2 smc PENTAX-F 35-70mm F3.5-4.5 +""", + """Exif.Pentax.LensType Byte 2 PENTAX-F 28-80mm F3.5-4.5 +""" + ] + stderr = [""] * len(commands) + retval = [0] * len(commands) diff --git a/tests/bugfixes/redmine/test_issue_922.py b/tests/bugfixes/redmine/test_issue_922.py new file mode 100644 index 00000000..ac4799c0 --- /dev/null +++ b/tests/bugfixes/redmine/test_issue_922.py @@ -0,0 +1,228 @@ +# -*- coding: utf-8 -*- + +import itertools +import os.path + +from system_tests import CaseMeta, path + + +def read_file(filename): + with open(filename, 'r') as f: + return f.read() + + +class AddMinusPSOption(metaclass=CaseMeta): + + cls_location = os.path.dirname(__file__) + + url = "http://dev.exiv2.org/issues/922" + + bug_jpg_file = path("$data_path/exiv2-bug922.jpg") + IPTC_file = path("$data_path/iptc-psAPP13-wIPTCempty-psAPP13-wIPTC.jpg") + files = [ + path("$data_path/{!s}".format(img)) + for img in "exiv2-bug922.png exiv2-bug922.tif exiv2-bug922a.jpg".split() + ] + + png_bug_file = files[0] + tif_bug_file = files[1] + jpg_bug_file = files[2] + + commands = [ + "$exiv2 -pX $bug_jpg_file", + "$exiv2 -pX $IPTC_file", + ] + list( + itertools.chain.from_iterable([ + "$exiv2 -pX " + fname, + "$exiv2 -pS " + fname + ] for fname in files) + ) + + stdout = [ + read_file( + os.path.join(cls_location, "issue_922_exiv2_pX_bug922_jpg_output") + ), + """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""", + """ + + + + + + this is the title + + + + + + + + + + + + + + + + + + + + + + + + + + +""", + """STRUCTURE OF PNG FILE: $png_bug_file + address | chunk | length | data | checksum + 8 | IHDR | 13 | ...@........ | 0x7f775da4 + 33 | zTXt | 8769 | Raw profile type exif..x...[r. | 0x4a89d860 + 8814 | zTXt | 270 | Raw profile type iptc..x.=QKn. | 0x29f9e2d3 + 9096 | iTXt | 2524 | XML:com.adobe.xmp.......]....UKqD2s.(.q....=x.l.\ | 0xc177fe83 + 54182 | IDAT | 8192 | .i.{!!B0...C!4.p..`D g`....... | 0x0e276268 + 62386 | IDAT | 8192 | .*.].4..Q..}(9...S0&.......T.9 | 0x297bb2db + 70590 | IDAT | 8192 | ..k...6....g.1..}.].&.H....... | 0x05f6f4ef + 78794 | IDAT | 8192 | .j..S.........z..!U.G0*.m%..09 | 0xe0946eb5 + 86998 | IDAT | 8192 | .....t.>!.....6^.<..;..?.$I..M | 0x843ecce0 + 95202 | IDAT | 8192 | W.&5.5J........FW`....3.N.9Pk; | 0x3a3dfeee + 103406 | IDAT | 8192 | .....d.z".`...v=g-..-.c8...Z.5 | 0x65d6df49 + 111610 | IDAT | 8192 | .."...o<&."....1M....1&. ..5.. | 0x700b8cde + 119814 | IDAT | 8192 | k........!..B*.....\*.(!..0.s. | 0x9b33b5b7 + 128018 | IDAT | 3346 | .Y.L@I$M.Z[.0A ...K#.t.0+.G(.j | 0x18044b20 + 131376 | IEND | 0 | | 0xae426082 +""", + """ + + + + + + this is a title + + + + + + + + + + + + + + + + + + + + + + + + + + +""", + """STRUCTURE OF TIFF FILE (MM): $tif_bug_file + address | tag | type | count | offset | value + 10 | 0x0100 ImageWidth | SHORT | 1 | | 40 + 22 | 0x0101 ImageLength | SHORT | 1 | | 470 + 34 | 0x0102 BitsPerSample | SHORT | 3 | 182 | 8 8 8 + 46 | 0x0103 Compression | SHORT | 1 | | 5 + 58 | 0x0106 PhotometricInterpretation | SHORT | 1 | | 2 + 70 | 0x0111 StripOffsets | LONG | 1 | | 2694 + 82 | 0x0112 Orientation | SHORT | 1 | | 6 + 94 | 0x0115 SamplesPerPixel | SHORT | 1 | | 3 + 106 | 0x0116 RowsPerStrip | SHORT | 1 | | 1092 + 118 | 0x0117 StripByteCounts | LONG | 1 | | 5086 + 130 | 0x011c PlanarConfiguration | SHORT | 1 | | 1 + 142 | 0x013d Predictor | SHORT | 1 | | 2 + 154 | 0x0153 SampleFormat | SHORT | 3 | 188 | 1 1 1 + 166 | 0x02bc XMLPacket | BYTE | 2500 | 194 | the rest drink soda the Brits are in the bar the Germans like beer """, + """STRUCTURE OF JPEG FILE: $jpg_bug_file + address | marker | length | data + 0 | 0xffd8 SOI + 2 | 0xffe1 APP1 | 14862 | Exif..II*...................... + 14866 | 0xffe1 APP1 | 2720 | http://ns.adobe.com/xap/1.0/. Date: Tue, 5 Jun 2018 09:42:31 +0200 Subject: [PATCH 2/2] [testsuite] Change the calling order of setUp & tearDown in decorator The FileDecoratorBase injects a new setUp & tearDown function. These new functions would call the old setUp & tearDown in an inconvenient order: e.g. the child class CopyFiles would at first call the user provided setUp and then copy the files. This makes it impossible to perform some action on the file copy in setUp. => This commit changes the call order, so that setUp & tearDown always "see" the finished environment after file copies are in place and before any cleanup took place. --- tests/system_tests.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/system_tests.py b/tests/system_tests.py index e6d61f9c..cf812f25 100644 --- a/tests/system_tests.py +++ b/tests/system_tests.py @@ -193,7 +193,6 @@ class FileDecoratorBase(object): tearDown() functions of the type it is called on with custom ones. The new setUp() function performs the following steps: - - call the old setUp() - create a file list in the decorated class with the name stored in FILE_LIST_NAME (defaults to _files) - iterate over all files, performing: @@ -201,6 +200,7 @@ class FileDecoratorBase(object): of the decorated class) - call self.setUp_file_action(expanded file name) - append the result to the file list in the decorated class + - call the old setUp() The function self.setUp_file_action is provided by this class and is intended to be overridden by child classes to provide some @@ -208,9 +208,9 @@ class FileDecoratorBase(object): The new tearDown() function performs the following steps: + - call the old tearDown() function - iterate over all files in the file list: - call self.tearDown_file_action(filename) - - call the old tearDown() function The function self.tearDown_file_action can be overridden by child classes. The default version provided by this class simply deletes @@ -252,17 +252,17 @@ class FileDecoratorBase(object): the constructor of the decorator, passes them to expand_variables and then to setUp_file_action: >>> M.setUp() - calling MockCase.setUp() setUp_file_action with one_file setUp_file_action with two_file setUp_file_action with three_file + calling MockCase.setUp() The tearDown() function works accordingly: >>> M.tearDown() + calling MockCase.tearDown() tearDown_file_action with One_file tearDown_file_action with Two_file tearDown_file_action with Three_file - calling MockCase.tearDown() Please note the capitalized "file" names (this is due to setUp_file_action returning f.capitalized()) and that the old @@ -321,7 +321,6 @@ class FileDecoratorBase(object): """ def setUp(other): - old_setUp(other) if hasattr(other, self.FILE_LIST_NAME): raise TypeError( "{!s} already has an attribute with the name {!s} which " @@ -334,6 +333,7 @@ class FileDecoratorBase(object): getattr(other, self.FILE_LIST_NAME).append( self.setUp_file_action(expanded_fname) ) + old_setUp(other) return setUp def setUp_file_action(self, expanded_file_name): @@ -368,9 +368,9 @@ class FileDecoratorBase(object): """ def tearDown(other): + old_tearDown(other) for f in getattr(other, self.FILE_LIST_NAME): self.tearDown_file_action(f) - old_tearDown(other) return tearDown @@ -436,7 +436,7 @@ class CopyFiles(FileDecoratorBase): self._files and then calls the original tearDown method. This function will also complain if it is called without arguments or - without paranthesis, which is valid decorator syntax but is obviously a bug + without parenthesis, which is valid decorator syntax but is obviously a bug in this case as it can result in tests not being run without a warning. """