1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
# coding=utf-8
import os, sys
import pytest
from image_extract import ExtractImage
from inkex.tester import ComparisonMixin, InkscapeExtensionTestMixin, TestCase
from inkex.tester.mock import Capture, MockCommandMixin
import inkex
class ExtractImageBasicTest(ComparisonMixin, InkscapeExtensionTestMixin, TestCase):
"""Comparison tests of ExtractImage"""
stderr_protect = False
effect_class = ExtractImage
compare_file = "svg/images.svg"
compare_file_extension = "png"
comparisons = [
("--selectedonly=False",),
("--selectedonly=True", "--id=embeded_image01"),
]
def test_all_comparisons(self):
"""Images are extracted to a file directory"""
for args in self.comparisons:
args += (f"--filepath={self.tempdir}/",)
self.assertCompare(self.compare_file, None, args, "embeded_image01.png")
class ExtractImageComponentTests(TestCase, MockCommandMixin):
"""Test some functions of ExtractImage"""
mocks = [(sys, "exit", lambda status: None)] # type:ignore
def test_extract_multiple(self):
"""test extraction in a multi-image file"""
args = [
self.data_file("svg", "images_multiple.svg"),
f"--directory={self.tempdir}/",
f"--output={self.tempdir}/out.svg",
"--selectedonly=True",
"--id=embedded_image01",
"--id=embedded_image02",
"--basename=image.jpg", # test that bad file extensions are corrected
"--linkextracted=false",
]
ext = ExtractImage()
def run_test(outexists):
with Capture("stderr") as stderr:
ext.run(args)
# There should be two images saved to the tempdir
self.assertListEqual(
sorted(os.listdir(self.tempdir)),
["image_1.png", "image_2.png"] + (["out.svg"] if outexists else []),
)
self.assertEqual(len(stderr.getvalue().split("extracted")), 3)
self.assertEqual(ext.errcount, 0)
# the out file only exists if it was changed, in this case, no change should
# be made
run_test(False)
for file in os.scandir(self.tempdir):
os.remove(file.path)
# We can do the same test again, because of linkextracted=False, the file is
# unchaged when running it on the output file.
args[-1] = "--linkextracted=true"
run_test(True)
# Now save all images again from the temp file, two images will raise an error
# because they are already embedded
# we also test that that relative target directories are interpreted relative to
# the input file stored in DOCUMENT_PATH (and not the actual input file name)
args[0] = f"{self.tempdir}/out.svg"
args[3] = "--selectedonly=False"
os.environ["DOCUMENT_PATH"] = os.path.abspath("images_multiple.svg")
args[1] = "--directory=" + os.path.relpath(self.tempdir, "images_multiple.svg")
with Capture("stderr") as stderr:
ext.run(args)
# There should be three images saved to the tempdir
self.assertListEqual(
sorted(os.listdir(self.tempdir)),
["image_1.png", "image_2.png", "image_3.png", "out.svg"],
)
self.assertEqual(len(stderr.getvalue().split("extracted")), 2)
self.assertEqual(len(stderr.getvalue().split("Unable")), 4)
self.assertEqual(ext.errcount, 3)
def test_extract_single_contextmenu(self):
"""test extraction in a multi-image file, called from the extensions menu,
but with only one selected image"""
args = [
self.data_file("svg", "images_multiple.svg"),
f"--directory={self.tempdir}/",
"--selectedonly=True",
"--id=embedded_image01",
"--basename=image",
]
ext = ExtractImage()
with Capture("stderr") as stderr:
ext.run(args)
self.assertListEqual(sorted(os.listdir(self.tempdir)), ["image.png"])
self.assertEqual(len(stderr.getvalue().split("extracted")), 2)
self.assertEqual(ext.errcount, 0)
@pytest.mark.skipif(sys.platform == "win32", reason="all directories writeable")
def test_extract_badpath(self):
"""Test writing to an unwriteable directory"""
args = [
self.data_file("svg", "images_multiple.svg"),
"--directory=/proc",
"--id=embedded_image01",
"--basename=image",
]
with Capture("stderr") as stderr:
ext = ExtractImage()
ext.run(args)
self.assertIn("Unable to write to", stderr.getvalue())
self.assertEqual(ext.errcount, 1)
args = [
self.data_file("svg", "images_multiple.svg"),
"--directory=/proc/test",
"--id=embedded_image01",
"--basename=image",
]
ext = ExtractImage()
with Capture("stderr") as stderr:
# The extension aborts
ext.run(args)
self.assertIn("Unable to create", stderr.getvalue())
def test_extract_badfilename(self):
"""Test writing to an unwriteable directory"""
if sys.platform == "win32":
filename = "<"
else:
filename = "a\x00" # null bytes are invalid
args = [
self.data_file("svg", "images_multiple.svg"),
"--directory=" + self.tempdir,
"--id=embedded_image01",
"--basename=" + filename,
]
with Capture("stderr") as stderr:
ext = ExtractImage()
if sys.version_info > (3, 8, 0) or filename == "<":
ext.run(args)
self.assertIn("Unable to write to", stderr.getvalue())
self.assertEqual(ext.errcount, 1)
else:
with self.assertRaises(ValueError) as __:
ext.run(args)
def test_extract_bad_data(self):
"""Extract bad data"""
svg = inkex.load_svg(self.data_file("svg", "images_multiple.svg")).getroot()
svg.getElementById("embedded_image01").set("xlink:href", "data:svg+xml;base64,")
svg.getElementById("embedded_image02").set(
"xlink:href", "data:image/abc;base32,"
)
temppath = os.path.join(self.tempdir, "temp.svg")
with open(temppath, "wb") as f:
f.write(svg.tostring())
args = [
self.data_file("svg", temppath),
"--directory=" + self.tempdir,
"--id=embedded_image01",
"--id=embedded_image02",
"--basename=badimage",
]
ext = ExtractImage()
with Capture("stderr") as stderr:
ext.run(args)
self.assertIn("Invalid image format", stderr.getvalue())
self.assertIn("encoding", stderr.getvalue())
self.assertEqual(ext.errcount, 2)
|