SeekquarrySeekquarry - Yioop Repo - Seekquarry

/ tests / AVToolTest.php⤓
<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2026  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * END LICENSE
 *
 * @author Chris Pollett chris@pollett.org
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2026
 * @filesource
 */
namespace seekquarry\yioop\tests;

use seekquarry\yioop\configs as C;
use seekquarry\yioop\library\UnitTest;

/**
 * Tests the command line tool for audio and video: that it writes a
 * thumbnail where it is told to, at the width asked for, that it can
 * describe a file without decoding it, and that it says what is wrong
 * rather than stopping without a word.
 *
 * The tool is run as a person runs it, in its own process, since that is
 * the only way its reading of a command line and what it prints are both
 * checked.
 *
 * @author Chris Pollett
 */
class AVToolTest extends UnitTest
{
    /**
     * The video file the cases run the tool over.
     * @var string
     */
    public $video = "";
    /**
     * Where the tool is asked to write its picture.
     * @var string
     */
    public $written = "";
    /**
     * Writes the video out of the base64 it is kept in.
     */
    public function setUp()
    {
        $held = file_get_contents(C\PARENT_DIR .
            "/tests/test_files/video_white_mp4.txt");
        $this->video = C\TEST_DIR . "/test_files/av_tool" . getmypid() .
            ".mp4";
        file_put_contents($this->video, base64_decode($held));
        $this->written = C\TEST_DIR . "/test_files/av_tool" . getmypid() .
            ".webp";
    }
    /**
     * Removes what the cases wrote.
     */
    public function tearDown()
    {
        foreach ([$this->video, $this->written] as $path) {
            if ($path !== "" && file_exists($path)) {
                unlink($path);
            }
        }
    }
    /**
     * runTool runs AVTool's avToolMain in this process, as the command
     * line would with the arguments given, and gives back what it wrote.
     *
     * @param string ...$arguments what follows the tool's name on the
     *      command line, one argument each
     * @return string everything the tool wrote, output and errors both
     */
    public function runTool(...$arguments)
    {
        require_once C\BASE_DIR . "/executables/AVTool.php";
        $written = fopen("php://memory", "w+");
        \seekquarry\yioop\executables\avToolMain(array_merge(
            ["AVTool.php"], $arguments), $written, $written);
        rewind($written);
        $said = stream_get_contents($written);
        fclose($written);
        return $said;
    }
    /**
     * Asked for help, the tool says what it does and what its options
     * are, so somebody who runs it with nothing is not left guessing.
     */
    public function askedForHelpItSaysWhatItDoesTestCase()
    {
        $said = $this->runTool("--help");
        $this->assertTrue(strpos($said, "picture from a video") !== false,
            "the help says the tool makes a picture from a video");
        $this->assertTrue(strpos($said, "convert a recording") !== false,
            "and that it converts a recording");
        $this->assertTrue(strpos($said, "--probe") !== false,
            "and lists the option that describes a file");
        $this->assertTrue(strpos($said, "--width") !== false,
            "and the option that sets the width");
    }
    /**
     * The tool writes a picture where it is told to, at the width asked
     * for, and says what it wrote.
     */
    public function itWritesAThumbnailWhereToldTestCase()
    {
        $said = $this->runTool($this->video, "-o",
            $this->written, "-w", "200");
        $this->assertTrue(file_exists($this->written),
            "a picture is written where the tool was told to write it");
        $size = getimagesize($this->written);
        $this->assertEqual(200, $size[0] ?? 0,
            "it is as wide as was asked for");
        $this->assertEqual(150, $size[1] ?? 0,
            "and its height keeps the shape of the frame");
        $this->assertTrue(strpos($said, "200x150") !== false,
            "and the tool says what it wrote");
    }
    /**
     * Asked to describe a file, the tool says what it holds without
     * decoding a frame, which is what a site wants when it only needs to
     * know how long a video runs.
     */
    public function itDescribesAFileWithoutDecodingTestCase()
    {
        $said = $this->runTool($this->video, "--probe");
        $held = json_decode($said, true);
        $this->assertTrue(is_array($held),
            "what it prints reads back as a description");
        $this->assertEqual("MP4", $held['container'] ?? "",
            "it names the kind of file");
        $this->assertEqual(320, $held['width'] ?? 0,
            "how wide the video is");
        $this->assertEqual(10, round($held['duration'] ?? 0),
            "and how long it runs");
    }
    /**
     * Handed a file that is not a video, the tool says so and stops,
     * rather than writing a broken picture or saying nothing.
     */
    public function handedSomethingElseItSaysSoTestCase()
    {
        $not_a_video = C\TEST_DIR . "/test_files/av_tool_words" .
            getmypid() . ".txt";
        file_put_contents($not_a_video, "these are only words");
        $said = $this->runTool($not_a_video);
        $this->assertTrue(strpos($said, "unrecognized container") !== false,
            "it says the file is not a kind it knows");
        $this->assertTrue(!file_exists($this->written),
            "and writes no picture");
        if (file_exists($not_a_video)) {
            unlink($not_a_video);
        }
    }
}