mirror of
https://github.com/steredbits/pelagia.git
synced 2026-10-17 17:01:33 +02:00
139 lines
5.1 KiB
C++
139 lines
5.1 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Copyright (C) 2026 steredbits and Pelagia contributors
|
|
// Tests of the display rules: durations, episodes, item poster, server
|
|
// address, saved session (never a password, private file),
|
|
// managed libraries and display sort.
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "memory_file_store.h"
|
|
#include "test_framework.h"
|
|
#include "ui/backend.h"
|
|
#include "ui/format.h"
|
|
#include "ui/session_store.h"
|
|
|
|
static api::MediaItem item(const std::string& name, const std::string& sort_name = "") {
|
|
api::MediaItem m;
|
|
m.id = name;
|
|
m.name = name;
|
|
m.sort_name = sort_name;
|
|
return m;
|
|
}
|
|
|
|
static void test_clock_and_runtime() {
|
|
CHECK(ui::format_clock(0) == "0:00");
|
|
CHECK(ui::format_clock(-5) == "0:00");
|
|
CHECK(ui::format_clock(123000) == "2:03");
|
|
CHECK(ui::format_clock(3723000) == "1:02:03");
|
|
CHECK(ui::format_clock(36000000) == "10:00:00");
|
|
CHECK(ui::format_runtime(20000) == "< 1 min");
|
|
CHECK(ui::format_runtime(42 * 60000) == "42 min");
|
|
CHECK(ui::format_runtime(102 * 60000) == "1 h 42");
|
|
CHECK(ui::format_runtime(120 * 60000) == "2 h");
|
|
CHECK(ui::format_runtime(65 * 60000) == "1 h 05");
|
|
}
|
|
|
|
static void test_items() {
|
|
api::MediaItem ep = item("\xE2\x80\x8E" "Pilote");
|
|
ep.type = "Episode";
|
|
ep.index_number = 3;
|
|
ep.parent_index_number = 1;
|
|
ep.runtime_ticks = 25LL * 60 * 10000000;
|
|
ep.playback_position_ticks = ep.runtime_ticks / 4;
|
|
CHECK(ui::episode_code(ep) == "S01E03");
|
|
CHECK(ui::display_title(ep) == "Pilote");
|
|
CHECK(ui::is_playable(ep));
|
|
CHECK_EQ(ui::resume_position_ms(ep), 375000);
|
|
CHECK(ui::progress_fraction(ep) > 0.24 && ui::progress_fraction(ep) < 0.26);
|
|
ep.played = true; // marked played: no resume
|
|
CHECK_EQ(ui::resume_position_ms(ep), 0);
|
|
CHECK(ui::progress_fraction(ep) == 0.0);
|
|
api::MediaItem series = item("Série");
|
|
series.type = "Series";
|
|
CHECK(!ui::is_playable(series));
|
|
CHECK(ui::episode_code(series).empty());
|
|
|
|
// Poster: its own, otherwise the series', otherwise none.
|
|
ep.primary_image_tag.clear();
|
|
ep.series_id = "s1";
|
|
ep.series_primary_image_tag = "stag";
|
|
ui::PosterKey k = ui::poster_key_for(ep, 240);
|
|
CHECK(k.item_id == "s1" && k.tag == "stag" && k.width == 240);
|
|
ep.primary_image_tag = "own";
|
|
k = ui::poster_key_for(ep, 240);
|
|
CHECK(k.item_id == ep.id && k.tag == "own");
|
|
CHECK(ui::poster_key_for(item("x"), 240).tag.empty());
|
|
}
|
|
|
|
static void test_server_address() {
|
|
CHECK(ui::complete_server_address("192.168.1.10:8096") == "http://192.168.1.10:8096");
|
|
CHECK(ui::complete_server_address(" https://jf.local/ ") == "https://jf.local");
|
|
CHECK(ui::complete_server_address("http://x:8096//") == "http://x:8096");
|
|
CHECK(ui::complete_server_address("").empty());
|
|
}
|
|
|
|
static void test_session_store() {
|
|
MemoryFileStore fs;
|
|
ui::SessionStore store(&fs, "/conf/pelagia");
|
|
ui::SavedSession s;
|
|
CHECK(!store.load(&s));
|
|
ui::SavedSession saved;
|
|
saved.server = "http://srv:8096";
|
|
saved.token = "tok-secret";
|
|
CHECK(store.save(saved));
|
|
const MemoryFileStore::File& f = fs.files["/conf/pelagia/session.json"];
|
|
CHECK(f.private_file); // 0600
|
|
CHECK(f.data.find("tok-secret") != std::string::npos);
|
|
CHECK(f.data.find("password") == std::string::npos);
|
|
CHECK(f.data.find("Pw") == std::string::npos);
|
|
CHECK(store.load(&s));
|
|
CHECK(s.server == saved.server && s.token == saved.token);
|
|
CHECK(store.clear());
|
|
CHECK(!store.load(&s));
|
|
// Corrupted or incomplete file: ignored.
|
|
fs.files["/conf/pelagia/session.json"].data = "{\"server\":\"http://x\"}";
|
|
CHECK(!store.load(&s));
|
|
fs.files["/conf/pelagia/session.json"].data = "pas du json";
|
|
CHECK(!store.load(&s));
|
|
ui::SavedSession parsed;
|
|
CHECK(ui::SessionStore::from_json(ui::SessionStore::to_json(saved), &parsed));
|
|
CHECK(parsed.token == "tok-secret");
|
|
}
|
|
|
|
static void test_libraries_and_sort() {
|
|
std::vector<api::Library> all(5);
|
|
all[0].name = "Films", all[0].collection_type = "movies";
|
|
all[1].name = "Musique", all[1].collection_type = "music";
|
|
all[2].name = "Séries", all[2].collection_type = "tvshows";
|
|
all[3].name = "Mixte", all[3].collection_type = "";
|
|
all[4].name = "Listes", all[4].collection_type = "playlists";
|
|
const std::vector<api::Library> kept = ui::supported_libraries(all);
|
|
CHECK_EQ(kept.size(), 3u);
|
|
CHECK(kept[0].name == "Films" && kept[1].name == "Séries" && kept[2].name == "Mixte");
|
|
CHECK(ui::item_types_for(kept[0]) == "Movie");
|
|
CHECK(ui::item_types_for(kept[1]) == "Series");
|
|
CHECK(ui::item_types_for(kept[2]) == "Movie,Series");
|
|
|
|
// Server order disturbed by U+200E and accents: sorted again.
|
|
std::vector<api::MediaItem> items = {
|
|
item("Zodiac"), item("Été 85", "été 85"),
|
|
item("\xE2\x80\x8E" "À bout de souffle", "\xE2\x80\x8E" "à bout de souffle"),
|
|
item("Batman Begins", "batman begins"), item("Œuvre", "œuvre")};
|
|
ui::sort_for_display(&items);
|
|
CHECK(items[0].name == "\xE2\x80\x8E" "À bout de souffle");
|
|
CHECK(items[1].name == "Batman Begins");
|
|
CHECK(items[2].name == "Été 85");
|
|
CHECK(items[3].name == "Œuvre");
|
|
CHECK(items[4].name == "Zodiac");
|
|
}
|
|
|
|
int main() {
|
|
test_clock_and_runtime();
|
|
test_items();
|
|
test_server_address();
|
|
test_session_store();
|
|
test_libraries_and_sort();
|
|
return testfw::test_failures();
|
|
}
|