Newer
Older
process_podcast / segment / tests / __init__.py
from datetime import timedelta
from pathlib import Path
import unittest

from segment import Segment


class SegmentSharedTestCase(unittest.TestCase):
    """Shared tests for Segment and its subclasses."""

    EXPECTED_INPUT_FILE = "file.in"
    EXPECTED_PUNCH_IN = timedelta(seconds=10)
    EXPECTED_PUNCH_OUT = timedelta(minutes=5, seconds=10)
    EXPECTED_DURATION = (EXPECTED_PUNCH_OUT - EXPECTED_PUNCH_IN).total_seconds()
    EXPECTED_INPUT_STREAM = 1
    EXPECTED_FILE_LIST = {"{f}".format(f=EXPECTED_INPUT_FILE): None}
    EXPECTED_TEMP_FILE = ""
    EXPECTED_TEMP_SUFFIX = ".mov"
    EXPECTED_TEMP_LIST = []
    EXPECTED_TYPE = ""
    EXPECTED_TRIM = ""
    EXPECTED_SETPTS = ""

    def setUp(self):
        """Set up for test."""
        # Explicitly empty the list of segment input files,
        # otherwise they hang around from previous tests.
        Segment._input_files = {}
        self.segment = Segment(
            file=self.EXPECTED_INPUT_FILE,
            punch_in=self.EXPECTED_PUNCH_IN,
            punch_out=self.EXPECTED_PUNCH_OUT,
            input_stream=self.EXPECTED_INPUT_STREAM)
        self.expected_input_options = [
            "-ss", str(self.EXPECTED_PUNCH_IN.total_seconds()),
            "-t", str(self.EXPECTED_DURATION),
            "-i", self.EXPECTED_INPUT_FILE
        ]
        self.expected_output_options = []

    def tearDown(self):
        """Clean up after test."""
        self.segment = None

    def test_init(self):
        """Test segment initialises correctly."""
        test_data = (
            (self.segment.input_file, self.EXPECTED_INPUT_FILE,
             "input file = {v}".format(v=self.EXPECTED_INPUT_FILE)),
            (self.segment.punch_in, self.EXPECTED_PUNCH_IN,
             "punch in = {v}".format(v=self.EXPECTED_PUNCH_IN)),
            (self.segment.punch_out, self.EXPECTED_PUNCH_OUT,
             "punch out = {v}".format(v=self.EXPECTED_PUNCH_OUT)),
            (self.segment.input_stream, self.EXPECTED_INPUT_STREAM,
             "input stream = {v}".format(v=self.EXPECTED_INPUT_STREAM)),
            (self.segment._temp_file, self.EXPECTED_TEMP_FILE,
             "temp file = {v}".format(v=self.EXPECTED_TEMP_FILE)),
            (self.segment._temp_suffix, self.EXPECTED_TEMP_SUFFIX,
             "temp suffix = {v}".format(v=self.EXPECTED_TEMP_SUFFIX)),
            (self.segment._temp_files_list, self.EXPECTED_TEMP_LIST,
             "temp files list = {v}".format(v=self.EXPECTED_TEMP_LIST)),
            (self.segment._TYPE, self.EXPECTED_TYPE,
             "type = {v}".format(v=self.EXPECTED_TYPE)),
            (self.segment._TRIM, self.EXPECTED_TRIM,
             "trim = {v}".format(v=self.EXPECTED_TRIM)),
            (self.segment._SETPTS, self.EXPECTED_SETPTS,
             "setpts = {v}".format(v=self.EXPECTED_SETPTS)),
        )
        for actual, expected, description in test_data:
            with self.subTest(msg=description):
                self.assertEqual(actual, expected)
    
    def test_input_options(self):
        """Test input options match expected."""
        # These are tested separately because they are initialised
        # differently by subclasses.
        self.assertEqual(
            self.segment._input_options, self.expected_input_options)

    def test_output_options(self):
        """Test output options match expected."""
        # These are tested separately because they are initialised
        # differently by subclasses.
        self.assertEqual(
            self.segment._output_options, self.expected_output_options)

    def test_segment_number_increment(self):
        """Test that the segment number increments correctly."""
        segment_1, segment_2 = Segment(), Segment()
        self.assertEqual(
            segment_1.segment_number + 1, segment_2.segment_number)
    
    def test_get_duration(self):
        """Test duration calculation."""
        self.assertEqual(self.segment.get_duration(), self.EXPECTED_DURATION)
    
    def test_generate_temp_filename(self):
        """Test generating temporary filename."""
        test_data = (
            (None, "default suffix"),
            (".bar", "specified suffix (.bar)"),
        )
        for suffix, description in test_data:
            expected_path = Path("temp_{t}_{o}_{n:03d}".format(
                t=self.segment._TYPE, o=Path("file.out").stem,
                n=self.segment.segment_number)).with_suffix(
                    suffix if suffix is not None
                           else self.segment._temp_suffix)
            with self.subTest(msg=description):
                self.assertEqual(self.segment.generate_temp_filename(
                                     "file.out", suffix=suffix),
                                 expected_path)
    
    # Testing generate_temp_file() is messy because of pexpect.

    def test_temp_file(self):
        """Test that temporary filename is correct."""
        self.assertEqual(
            self.segment.temp_file(), "", msg="temp file initially empty")
        self.segment._temp_file = self.segment.generate_temp_filename(
            "file.out", ".bar")
        expected_path = Path("temp_{t}_{o}_{n:03d}".format(
            t=self.segment._TYPE, o=Path("file.out").stem,
            n=self.segment.segment_number)).with_suffix(".bar")
        self.assertEqual(
            self.segment.temp_file(), expected_path,
            msg="specified temp file is correct")
    
    # Testing delete_temp_files() requires actual files to be created.

    def test_input_stream_specifier(self):
        """Test that input stream specifier is correctly generated."""
        expected_specifier = "[{n}:{t}]".format(
            n=tuple(Segment._input_files).index(self.segment.input_file),
            t=self.segment._TYPE[0] if self.segment._TYPE else "")
        self.assertEqual(
            self.segment.input_stream_specifier(), expected_specifier)

    def test_output_stream_specifier(self):
        """Test that output stream specifier is correctly generated."""
        expected_specifier = "[{t}{n}]".format(
            t=self.segment._TYPE[0] if self.segment._TYPE else "",
            n=self.segment.segment_number)
        self.assertEqual(
            self.segment.output_stream_specifier(), expected_specifier)
    
    def test_trim_filter(self):
        """Test that the trim filter is correctly generated."""
        expected_filter = (
            "{inspec} {trim}=start={pi}:duration={d},{setpts}=PTS-STARTPTS "
            "{outspec}".format(
                inspec=self.segment.input_stream_specifier(),
                trim=self.segment._TRIM, setpts=self.segment._SETPTS,
                pi=self.EXPECTED_PUNCH_IN.total_seconds(),
                d=self.EXPECTED_DURATION,
                outspec=self.segment.output_stream_specifier()))
        self.assertEqual(self.segment.trim_filter(), expected_filter)