aboutsummaryrefslogtreecommitdiff
path: root/svg-flatten/src/test/svg_tests.py
blob: a5139ec5275e8452ab96c33603177bafbbe99e34 (plain)
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
#!/usr/bin/env python3

import tempfile
import unittest
from pathlib import Path
import subprocess
import os

from PIL import Image
import numpy as np

def run_svg_flatten(input_file, output_file, **kwargs):
    if 'SVG_FLATTEN' in os.environ:
        svg_flatten = os.environ.get('SVG_FLATTEN')
    elif (Path(__file__) / '../../build/svg-flatten').is_file():
        svg_flatten = '../../build/svg-flatten'
    elif Path('./build/svg-flatten').is_file():
        svg_flatten = './build/svg-flatten'
    else:
        svg_flatten = 'svg-flatten'

    args = [ svg_flatten,
            *(arg for (key, value) in kwargs.items() for arg in (f'--{key.replace("_", "-")}', value)),
            str(input_file), str(output_file) ]

    try:
        proc = subprocess.run(args, capture_output=True, check=True)
    except:
        print('Subprocess stdout:')
        print(proc.stdout)
        print('Subprocess stderr:')
        print(proc.stderr)
        raise

class SVGRoundTripTests(unittest.TestCase):

    def compare_images(self, reference, output, test_name, mean=0.01):
        ref = np.array(Image.open(reference))
        out = np.array(Image.open(output))
        delta = np.abs(out - ref).astype(float) / 255

        #print(f'{test_name}: mean={delta.mean():.5g}')

        self.assertTrue(delta.mean() < mean,
                f'Expected mean pixel difference between images to be <{mean}, was {delta.mean():.5g}')

    def run_svg_round_trip_test(self, test_in_svg):
        with tempfile.NamedTemporaryFile(suffix='.svg') as tmp_out_svg,\
            tempfile.NamedTemporaryFile(suffix='.png') as tmp_out_png,\
            tempfile.NamedTemporaryFile(suffix='.png') as tmp_in_png:

            run_svg_flatten(test_in_svg, tmp_out_svg.name, format='svg')

            subprocess.run(['resvg', tmp_out_svg.name, tmp_out_png.name], check=True, stdout=subprocess.DEVNULL)
            subprocess.run(['resvg', test_in_svg, tmp_in_png.name], check=True, stdout=subprocess.DEVNULL)

            try:
                self.compare_images(tmp_in_png, tmp_out_png, test_in_svg.stem)
            except AssertionError as e:
                import shutil
                shutil.copyfile(tmp_in_png.name, f'/tmp/gerbolyze-fail-{test_in_svg.stem}-in.png')
                shutil.copyfile(tmp_out_png.name, f'/tmp/gerbolyze-fail-{test_in_svg.stem}-out.png')
                foo = list(e.args)
                foo[0] += '\nFailing test renderings copied to:\n'
                foo[0] += f'  /tmp/gerbolyze-fail-{test_in_svg.stem}-{{in|out}}.png\n'
                e.args = tuple(foo)
                raise e

for test_in_svg in Path('testdata/svg').glob('*.svg'):
    # We need to make sure we capture the loop variable's current value here.
    gen = lambda testcase: lambda self: self.run_svg_round_trip_test(testcase)
    setattr(SVGRoundTripTests, f'test_{test_in_svg.stem}', gen(test_in_svg))

if __name__ == '__main__':
    unittest.main()