File: base.py

package info (click to toggle)
pngtools 1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 928 kB
  • sloc: ansic: 871; sh: 684; python: 558; makefile: 32
file content (105 lines) | stat: -rw-r--r-- 3,071 bytes parent folder | download
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
"""Base test case for pngtools tests."""

import os
import subprocess
import types

import fixtures
import testtools


# Project root is the parent of the tests/ directory
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(
    __file__)))

# Paths to the sample images shipped in the repository
SAMPLE_DIR = PROJECT_ROOT

# Path to generated test images
TESTDATA_DIR = os.path.join(PROJECT_ROOT, 'testdata')


def _ensure_test_images():
    """Generate test images if they don't exist yet."""
    marker = os.path.join(TESTDATA_DIR, 'with_text.png')
    if not os.path.exists(marker):
        script = os.path.join(
            PROJECT_ROOT, 'tests', 'generate_test_images.py'
        )
        subprocess.run(
            ['python3', script],
            check=True,
            capture_output=True
        )


class PngtoolsTestCase(testtools.TestCase):
    """Base test case with helpers for running pngtools binaries."""

    def setUp(self):
        super().setUp()
        self.tmpdir = self.useFixture(fixtures.TempDir())

        # Verify binaries are built
        for binary in ['pnginfo', 'pngchunks', 'pngchunkdesc',
                       'pngcp']:
            path = os.path.join(PROJECT_ROOT, binary)
            if not os.path.exists(path):
                self.skipTest(
                    f'{binary} not built; run make first'
                )

        # Ensure generated test images exist
        _ensure_test_images()

        # Create an invalid (non-PNG) file for error tests
        self.invalid_file = os.path.join(
            self.tmpdir.path, 'invalid.txt'
        )
        with open(self.invalid_file, 'w') as f:
            f.write('this is not a png file')

    def run_tool(self, name, args=None, stdin_data=None):
        """Run a pngtools binary and return the result.

        Returns a SimpleNamespace with .stdout, .stderr,
        and .returncode.
        """
        if args is None:
            args = []

        binary = os.path.join(PROJECT_ROOT, name)
        cmd = [binary] + args

        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            input=stdin_data,
            cwd=PROJECT_ROOT,
            timeout=30
        )

        return types.SimpleNamespace(
            stdout=result.stdout,
            stderr=result.stderr,
            returncode=result.returncode
        )

    def run_pnginfo(self, filename, flags=None):
        """Convenience wrapper for running pnginfo."""
        if flags is None:
            flags = []
        return self.run_tool('pnginfo', flags + [filename])

    def sample_path(self, filename):
        """Return the full path to a sample PNG in the repo."""
        return os.path.join(SAMPLE_DIR, filename)

    def generated_path(self, filename):
        """Return the full path to a generated test PNG."""
        return os.path.join(TESTDATA_DIR, filename)

    def tmp_path(self, filename):
        """Return a path in the temp directory for output."""
        return os.path.join(self.tmpdir.path, filename)