commit
284beae36c
4 changed files with 256 additions and 3 deletions
245
testscour.py
245
testscour.py
|
|
@ -20,15 +20,19 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function # use print() as a function in Python 2 (see PEP 3105)
|
||||
from __future__ import absolute_import # use absolute imports by default in Python 2 (see PEP 328)
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import six
|
||||
from six.moves import map, range
|
||||
|
||||
from scour.scour import makeWellFormed, parse_args, scourString, scourXmlFile
|
||||
from scour.scour import makeWellFormed, parse_args, scourString, scourXmlFile, run
|
||||
from scour.svg_regex import svg_parser
|
||||
from scour import __version__
|
||||
|
||||
|
||||
SVGNS = 'http://www.w3.org/2000/svg'
|
||||
|
|
@ -385,6 +389,65 @@ class RemoveUnreferencedIDsWhenEnabled(unittest.TestCase):
|
|||
'<svg> ID not stripped')
|
||||
|
||||
|
||||
class ProtectIDs(unittest.TestCase):
|
||||
|
||||
def test_protect_none(self):
|
||||
doc = scourXmlFile('unittests/ids-protect.svg',
|
||||
parse_args(['--enable-id-stripping']))
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[0].getAttribute('id'), '',
|
||||
"ID 'text1' not stripped when none of the '--protect-ids-_' options was specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[1].getAttribute('id'), '',
|
||||
"ID 'text2' not stripped when none of the '--protect-ids-_' options was specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[2].getAttribute('id'), '',
|
||||
"ID 'text3' not stripped when none of the '--protect-ids-_' options was specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[3].getAttribute('id'), '',
|
||||
"ID 'text_custom' not stripped when none of the '--protect-ids-_' options was specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[4].getAttribute('id'), '',
|
||||
"ID 'my_text1' not stripped when none of the '--protect-ids-_' options was specified")
|
||||
|
||||
def test_protect_ids_noninkscape(self):
|
||||
doc = scourXmlFile('unittests/ids-protect.svg',
|
||||
parse_args(['--enable-id-stripping', '--protect-ids-noninkscape']))
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[0].getAttribute('id'), '',
|
||||
"ID 'text1' should have been stripped despite '--protect-ids-noninkscape' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[1].getAttribute('id'), '',
|
||||
"ID 'text2' should have been stripped despite '--protect-ids-noninkscape' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[2].getAttribute('id'), '',
|
||||
"ID 'text3' should have been stripped despite '--protect-ids-noninkscape' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[3].getAttribute('id'), 'text_custom',
|
||||
"ID 'text_custom' should NOT have been stripped because of '--protect-ids-noninkscape'")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[4].getAttribute('id'), '',
|
||||
"ID 'my_text1' should have been stripped despite '--protect-ids-noninkscape' being specified")
|
||||
|
||||
def test_protect_ids_list(self):
|
||||
doc = scourXmlFile('unittests/ids-protect.svg',
|
||||
parse_args(['--enable-id-stripping', '--protect-ids-list=text2,text3']))
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[0].getAttribute('id'), '',
|
||||
"ID 'text1' should have been stripped despite '--protect-ids-list' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[1].getAttribute('id'), 'text2',
|
||||
"ID 'text2' should NOT have been stripped because of '--protect-ids-list'")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[2].getAttribute('id'), 'text3',
|
||||
"ID 'text3' should NOT have been stripped because of '--protect-ids-list'")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[3].getAttribute('id'), '',
|
||||
"ID 'text_custom' should have been stripped despite '--protect-ids-list' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[4].getAttribute('id'), '',
|
||||
"ID 'my_text1' should have been stripped despite '--protect-ids-list' being specified")
|
||||
|
||||
def test_protect_ids_prefix(self):
|
||||
doc = scourXmlFile('unittests/ids-protect.svg',
|
||||
parse_args(['--enable-id-stripping', '--protect-ids-prefix=my']))
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[0].getAttribute('id'), '',
|
||||
"ID 'text1' should have been stripped despite '--protect-ids-prefix' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[1].getAttribute('id'), '',
|
||||
"ID 'text2' should have been stripped despite '--protect-ids-prefix' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[2].getAttribute('id'), '',
|
||||
"ID 'text3' should have been stripped despite '--protect-ids-prefix' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[3].getAttribute('id'), '',
|
||||
"ID 'text_custom' should have been stripped despite '--protect-ids-prefix' being specified")
|
||||
self.assertEqual(doc.getElementsByTagNameNS(SVGNS, 'text')[4].getAttribute('id'), 'my_text1',
|
||||
"ID 'my_text1' should NOT have been stripped because of '--protect-ids-prefix'")
|
||||
|
||||
|
||||
class RemoveUselessNestedGroups(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
|
|
@ -2100,7 +2163,183 @@ class ParseStyleAttribute(unittest.TestCase):
|
|||
doc = scourXmlFile('unittests/style.svg')
|
||||
self.assertEqual(doc.documentElement.getAttribute('style'),
|
||||
'property1:value1;property2:value2;property3:value3',
|
||||
'Style attribute not properly parsed and/or serialized')
|
||||
"Style attribute not properly parsed and/or serialized")
|
||||
|
||||
|
||||
class StripXmlSpaceAttribute(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
doc = scourXmlFile('unittests/xml-space.svg',
|
||||
parse_args(['--strip-xml-space']))
|
||||
self.assertEqual(doc.documentElement.getAttribute('xml:space'), '',
|
||||
"'xml:space' attribute not removed from root SVG element"
|
||||
"when '--strip-xml-space' was specified")
|
||||
self.assertNotEqual(doc.getElementById('text1').getAttribute('xml:space'), '',
|
||||
"'xml:space' attribute removed from a child element "
|
||||
"when '--strip-xml-space' was specified (should only operate on root SVG element)")
|
||||
|
||||
|
||||
class DoNotStripXmlSpaceAttribute(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
doc = scourXmlFile('unittests/xml-space.svg')
|
||||
self.assertNotEqual(doc.documentElement.getAttribute('xml:space'), '',
|
||||
"'xml:space' attribute removed from root SVG element"
|
||||
"when '--strip-xml-space' was NOT specified")
|
||||
self.assertNotEqual(doc.getElementById('text1').getAttribute('xml:space'), '',
|
||||
"'xml:space' attribute removed from a child element "
|
||||
"when '--strip-xml-space' was NOT specified (should never be removed!)")
|
||||
|
||||
|
||||
class CommandLineUsage(unittest.TestCase):
|
||||
|
||||
USAGE_STRING = "Usage: scour [INPUT.SVG [OUTPUT.SVG]] [OPTIONS]"
|
||||
MINIMAL_SVG = '<?xml version="1.0" encoding="UTF-8"?>\n' \
|
||||
'<svg xmlns="http://www.w3.org/2000/svg"/>\n'
|
||||
TEMP_SVG_FILE = 'testscour_temp.svg'
|
||||
|
||||
# wrapper function for scour.run() to emulate command line usage
|
||||
#
|
||||
# returns an object with the following attributes:
|
||||
# status: the exit status
|
||||
# stdout: a string representing the combined output to 'stdout'
|
||||
# stderr: a string representing the combined output to 'stderr'
|
||||
def _run_scour(self):
|
||||
class Result(object):
|
||||
pass
|
||||
|
||||
result = Result()
|
||||
try:
|
||||
run()
|
||||
result.status = 0
|
||||
except SystemExit as exception: # catch any calls to sys.exit()
|
||||
result.status = exception.code
|
||||
result.stdout = self.temp_stdout.getvalue()
|
||||
result.stderr = self.temp_stderr.getvalue()
|
||||
|
||||
return result
|
||||
|
||||
def setUp(self):
|
||||
# store current values of 'argv', 'stdin', 'stdout' and 'stderr'
|
||||
self.argv = sys.argv
|
||||
self.stdin = sys.stdin
|
||||
self.stdout = sys.stdout
|
||||
self.stderr = sys.stderr
|
||||
|
||||
# start with a fresh 'argv'
|
||||
sys.argv = ['scour'] # TODO: Do we need a (more) valid 'argv[0]' for anything?
|
||||
|
||||
# create 'stdin', 'stdout' and 'stderr' with behavior close to the original
|
||||
# TODO: can we create file objects that behave *exactly* like the original?
|
||||
# this is a mess since we have to ensure compatibility across Python 2 and 3 and it seems impossible
|
||||
# to replicate all the details of 'stdin', 'stdout' and 'stderr'
|
||||
class InOutBuffer(six.StringIO, object):
|
||||
def write(self, string):
|
||||
try:
|
||||
return super(InOutBuffer, self).write(string)
|
||||
except TypeError:
|
||||
return super(InOutBuffer, self).write(string.decode())
|
||||
|
||||
sys.stdin = self.temp_stdin = InOutBuffer()
|
||||
sys.stdout = self.temp_stdout = InOutBuffer()
|
||||
sys.stderr = self.temp_stderr = InOutBuffer()
|
||||
|
||||
self.temp_stdin.name = '<stdin>' # Scour wants to print the name of the input file...
|
||||
|
||||
def tearDown(self):
|
||||
# restore previous values of 'argv', 'stdin', 'stdout' and 'stderr'
|
||||
sys.argv = self.argv
|
||||
sys.stdin = self.stdin
|
||||
sys.stdout = self.stdout
|
||||
sys.stderr = self.stderr
|
||||
|
||||
# clean up
|
||||
self.temp_stdin.close()
|
||||
self.temp_stdout.close()
|
||||
self.temp_stderr.close()
|
||||
|
||||
def test_no_arguments(self):
|
||||
# we have to pretend that our input stream is a TTY, otherwise Scour waits for input from stdin
|
||||
self.temp_stdin.isatty = lambda: True
|
||||
|
||||
result = self._run_scour()
|
||||
|
||||
self.assertEqual(result.status, 2, "Execution of 'scour' without any arguments should exit with status '2'")
|
||||
self.assertTrue(self.USAGE_STRING in result.stderr,
|
||||
"Usage information not displayed when calling 'scour' without any arguments")
|
||||
|
||||
def test_version(self):
|
||||
sys.argv.append('--version')
|
||||
|
||||
result = self._run_scour()
|
||||
|
||||
self.assertEqual(result.status, 0, "Execution of 'scour --version' erorred'")
|
||||
self.assertEqual(__version__ + "\n", result.stdout, "Unexpected output of 'scour --version'")
|
||||
|
||||
def test_help(self):
|
||||
sys.argv.append('--help')
|
||||
|
||||
result = self._run_scour()
|
||||
|
||||
self.assertEqual(result.status, 0, "Execution of 'scour --help' erorred'")
|
||||
self.assertTrue(self.USAGE_STRING in result.stdout and 'Options:' in result.stdout,
|
||||
"Unexpected output of 'scour --help'")
|
||||
|
||||
def test_stdin_stdout(self):
|
||||
sys.stdin.write(self.MINIMAL_SVG)
|
||||
sys.stdin.seek(0)
|
||||
|
||||
result = self._run_scour()
|
||||
|
||||
self.assertEqual(result.status, 0, "Usage of Scour via 'stdin' / 'stdout' erorred'")
|
||||
self.assertEqual(result.stdout, self.MINIMAL_SVG, "Unexpected SVG output via 'stdout'")
|
||||
|
||||
def test_filein_fileout_named(self):
|
||||
sys.argv.extend(['-i', 'unittests/minimal.svg', '-o', self.TEMP_SVG_FILE])
|
||||
|
||||
result = self._run_scour()
|
||||
|
||||
self.assertEqual(result.status, 0, "Usage of Scour with filenames specified as named parameters errored'")
|
||||
with open(self.TEMP_SVG_FILE) as file:
|
||||
file_content = file.read()
|
||||
self.assertEqual(file_content, self.MINIMAL_SVG, "Unexpected SVG output in generated file")
|
||||
os.remove(self.TEMP_SVG_FILE)
|
||||
|
||||
def test_filein_fileout_positional(self):
|
||||
sys.argv.extend(['unittests/minimal.svg', self.TEMP_SVG_FILE])
|
||||
|
||||
result = self._run_scour()
|
||||
|
||||
self.assertEqual(result.status, 0, "Usage of Scour with filenames specified as positional parameters errored'")
|
||||
with open(self.TEMP_SVG_FILE) as file:
|
||||
file_content = file.read()
|
||||
self.assertEqual(file_content, self.MINIMAL_SVG, "Unexpected SVG output in generated file")
|
||||
os.remove(self.TEMP_SVG_FILE)
|
||||
|
||||
def test_quiet(self):
|
||||
sys.argv.append('-q')
|
||||
sys.argv.extend(['-i', 'unittests/minimal.svg', '-o', self.TEMP_SVG_FILE])
|
||||
|
||||
result = self._run_scour()
|
||||
os.remove(self.TEMP_SVG_FILE)
|
||||
|
||||
self.assertEqual(result.status, 0, "Execution of 'scour -q ...' erorred'")
|
||||
self.assertEqual(result.stdout, '', "Output writtent to 'stdout' when '--quiet' options was used")
|
||||
self.assertEqual(result.stderr, '', "Output writtent to 'stderr' when '--quiet' options was used")
|
||||
|
||||
def test_verbose(self):
|
||||
sys.argv.append('-v')
|
||||
sys.argv.extend(['-i', 'unittests/minimal.svg', '-o', self.TEMP_SVG_FILE])
|
||||
|
||||
result = self._run_scour()
|
||||
os.remove(self.TEMP_SVG_FILE)
|
||||
|
||||
self.assertEqual(result.status, 0, "Execution of 'scour -v ...' erorred'")
|
||||
self.assertEqual(result.stdout.count('Number'), 14,
|
||||
"Statistics output not as expected when '--verbose' option was used")
|
||||
self.assertEqual(result.stdout.count(': 0'), 14,
|
||||
"Statistics output not as expected when '--verbose' option was used")
|
||||
|
||||
|
||||
# TODO: write tests for --enable-viewboxing
|
||||
# TODO; write a test for embedding rasters
|
||||
|
|
|
|||
8
unittests/ids-protect.svg
Normal file
8
unittests/ids-protect.svg
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="110" width="100">
|
||||
<text id="text1" x="10" y="20">Text 1</text>
|
||||
<text id="text2" x="10" y="40">Text 2</text>
|
||||
<text id="text3" x="10" y="60">Text 3</text>
|
||||
<text id="text_custom" x="10" y="80">Text custom</text>
|
||||
<text id="my_text1" x="10" y="100">My text</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 358 B |
2
unittests/minimal.svg
Normal file
2
unittests/minimal.svg
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg"/>
|
||||
|
After Width: | Height: | Size: 81 B |
4
unittests/xml-space.svg
Normal file
4
unittests/xml-space.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="50" xml:space="preserve">
|
||||
<text id="text1" x="5" y="20" xml:space="preserve">Some random text.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 210 B |
Loading…
Add table
Add a link
Reference in a new issue