mirror of
https://github.com/steredbits/pelagia.git
synced 2026-10-18 02:01:28 +02:00
119 lines
4.9 KiB
C++
119 lines
4.9 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Copyright (C) 2026 steredbits and Pelagia contributors
|
|
// Complete walk through the interface, in English then in French, against the fake server ("demo" catalog)
|
|
// with pelagia-capture: sign-in, home, grid, page, series, player
|
|
// (loading, playback, seek, pause), stop then page re-read. Checks
|
|
// that each screen is reached, that the PNGs are readable 1920x1080
|
|
// images and that the server received the playback stop report.
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <string>
|
|
|
|
#include "fake_server.h"
|
|
#include "test_framework.h"
|
|
#include "ui/image_codec.h"
|
|
|
|
namespace {
|
|
|
|
const char* const kShots[] = {
|
|
"01-sign-in", "02-virtual-keyboard", "03-home", "04-movie-grid",
|
|
"04b-movie-grid-scrolled", "05-movie-page", "06-series-episodes", "07-episode-page",
|
|
"08-options", "08b-about", "08c-language", "09-player-loading", "10-player", "11-player-seeking",
|
|
"12-player-paused", "13-page-after-playback", "14-home-after-playback"};
|
|
|
|
// "tracks" scenario: page with tracks, lists, "1917" page.
|
|
const char* const kTrackShots[] = {"15-movie-tracks", "16-audio-menu",
|
|
"17-subtitle-menu", "18-tracks-burned-in",
|
|
"19-player-tracks", "20-player-options",
|
|
"21-player-audio-list", "22-player-track-change",
|
|
"23-page-after-track-change", "24-player-subtitles"};
|
|
|
|
const char kCrazy[] = "de300000000000000000000000000101";
|
|
|
|
// Whole walkthrough in one interface language; the fake server serves its demo
|
|
// content in the same language.
|
|
int run_language(const std::string& media, const std::string& language) {
|
|
testnet::FakeServer server;
|
|
// No duration threshold: the test pattern position (40 s) is recorded.
|
|
const std::string token = "capture0token0secret0123456789ab";
|
|
if (!server.start(media, {"--catalog", "demo", "--language", language, "--min-resume-duration",
|
|
"0", "--token", token})) {
|
|
return 1;
|
|
}
|
|
const std::string work = testnet::workdir() + "/capture-" + language;
|
|
const std::string out = work + "/png";
|
|
const std::string prepare = "rm -rf '" + work + "' && mkdir -p '" + out + "'";
|
|
CHECK(std::system(prepare.c_str()) == 0);
|
|
|
|
const std::string log = work + "/capture.log";
|
|
const int code = testnet::run_process(
|
|
{PELAGIA_CAPTURE_BIN, "--server", server.base_url(), "--work-dir", work + "/state",
|
|
"--out", out, "--language", language},
|
|
log, 90000);
|
|
CHECK_EQ(code, 0);
|
|
if (code != 0) {
|
|
std::fprintf(stderr, "%s\n", testnet::read_file(log).c_str());
|
|
}
|
|
for (const char* name : kShots) {
|
|
const std::string png = testnet::read_file(out + "/" + name + ".png");
|
|
ui::Image img;
|
|
const bool ok = ui::decode_image(png, 0, 0, &img) && img.w == 1920 && img.h == 1080;
|
|
if (!ok) std::fprintf(stderr, "missing or invalid capture : %s\n", name);
|
|
CHECK(ok);
|
|
CHECK(png.size() < 400u * 1024); // readable on GitHub
|
|
}
|
|
// The token appears in no output of the tool (logs masked).
|
|
CHECK(testnet::read_file(log).find(token) == std::string::npos);
|
|
testnet::ServerState state;
|
|
CHECK(testnet::parse_state(server.state(), &state));
|
|
bool stopped = false;
|
|
for (size_t i = 0; i < state.report_kinds.size(); ++i) {
|
|
if (state.report_kinds[i] == "stopped" &&
|
|
state.report_bodies[i].find(kCrazy) != std::string::npos) {
|
|
stopped = true;
|
|
}
|
|
}
|
|
CHECK(stopped); // stop report of "Crazy Kung-Fu" received
|
|
CHECK(state.active_jobs == 0); // no transcoding left on the server
|
|
|
|
// Tracks scenario: "tracks" catalog.
|
|
server.stop();
|
|
if (!server.start(media, {"--catalog", "tracks", "--language", language, "--min-resume-duration",
|
|
"0", "--token", token})) {
|
|
return 1;
|
|
}
|
|
const std::string tracks_log = work + "/capture-tracks.log";
|
|
const int tracks_code = testnet::run_process(
|
|
{PELAGIA_CAPTURE_BIN, "--server", server.base_url(), "--work-dir", work + "/state-tracks",
|
|
"--out", out, "--scenario", "tracks", "--language", language},
|
|
tracks_log, 90000);
|
|
CHECK_EQ(tracks_code, 0);
|
|
if (tracks_code != 0) {
|
|
std::fprintf(stderr, "%s\n", testnet::read_file(tracks_log).c_str());
|
|
}
|
|
for (const char* name : kTrackShots) {
|
|
const std::string png = testnet::read_file(out + "/" + name + ".png");
|
|
ui::Image img;
|
|
const bool ok = ui::decode_image(png, 0, 0, &img) && img.w == 1920 && img.h == 1080;
|
|
if (!ok) std::fprintf(stderr, "missing or invalid capture : %s\n", name);
|
|
CHECK(ok);
|
|
CHECK(png.size() < 400u * 1024);
|
|
}
|
|
CHECK(testnet::read_file(tracks_log).find(token) == std::string::npos);
|
|
return 0;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
int main() {
|
|
std::string media;
|
|
if (!testnet::ensure_test_media(&media)) {
|
|
std::fprintf(stderr, "python3/ffmpeg unavailable: test skipped\n");
|
|
return testnet::kSkip;
|
|
}
|
|
CHECK_EQ(run_language(media, "en"), 0);
|
|
CHECK_EQ(run_language(media, "fr"), 0);
|
|
return testfw::test_failures();
|
|
}
|