Files

99 lines
3.2 KiB
C++

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2026 steredbits and Pelagia contributors
// Tests of the buffering decision (BufferingGate), without
// network or ffmpeg.
#include "player/buffering.h"
#include "test_framework.h"
using player::BufferingEvent;
using player::BufferingGate;
using player::BufferingPolicy;
static BufferingPolicy policy() {
BufferingPolicy p;
p.start_ms = 2000;
p.resume_ms = 4000;
p.low_water_ms = 250;
return p;
}
// Disabled (local file): never suspended.
static void test_disabled() {
BufferingGate gate;
gate.reset_for_start();
BufferingEvent ev;
CHECK(!gate.update(0, false, false, &ev));
CHECK(ev == BufferingEvent::None);
CHECK(!gate.buffering());
CHECK(!BufferingPolicy().enabled());
CHECK(BufferingPolicy::network().enabled());
}
// Start: wait for the start reserve, no more.
static void test_priming() {
BufferingGate gate(policy());
gate.reset_for_start();
BufferingEvent ev;
CHECK(gate.buffering() && gate.priming());
CHECK(gate.update(0, false, false, &ev));
CHECK(gate.update(1999, false, false, &ev));
CHECK(!gate.update(2000, false, false, &ev));
CHECK(ev == BufferingEvent::Finished);
CHECK(!gate.buffering());
}
// Shortage during playback, then resume with hysteresis.
static void test_rebuffering_hysteresis() {
BufferingGate gate(policy());
BufferingEvent ev;
CHECK(!gate.update(5000, false, false, &ev)); // playing
CHECK(!gate.update(250, false, false, &ev)); // at the threshold: we continue
CHECK(gate.update(249, false, false, &ev)); // below the threshold: suspension
CHECK(ev == BufferingEvent::Started);
CHECK(!gate.priming());
// The start reserve is not enough to resume after a shortage.
CHECK(gate.update(2000, false, false, &ev));
CHECK(ev == BufferingEvent::None);
CHECK(gate.update(3999, false, false, &ev));
CHECK(!gate.update(4000, false, false, &ev));
CHECK(ev == BufferingEvent::Finished);
// A drop above the low threshold does not suspend (no oscillation).
CHECK(!gate.update(300, false, false, &ev));
}
// End of the source or full queues: always ready (otherwise a block).
static void test_ready_anyway() {
BufferingGate gate(policy());
BufferingEvent ev;
gate.reset_for_start();
CHECK(!gate.update(100, true, false, &ev)); // end of stream: nothing to wait for
CHECK(ev == BufferingEvent::Finished);
CHECK(!gate.update(0, true, false, &ev)); // end of the movie: no shortage
gate.reset_for_start();
CHECK(!gate.update(500, false, true, &ev)); // queues full before the threshold
CHECK(gate.update(0, false, false, &ev)); // manque
CHECK(!gate.update(1000, false, true, &ev)); // files pleines : reprise
}
// Seek: back to the start state even in the middle of playback.
static void test_reset_on_seek() {
BufferingGate gate(policy());
BufferingEvent ev;
CHECK(!gate.update(5000, false, false, &ev));
gate.reset_for_start();
CHECK(gate.priming());
CHECK(gate.update(1000, false, false, &ev));
CHECK(!gate.update(2500, false, false, &ev));
}
int main() {
test_disabled();
test_priming();
test_rebuffering_hysteresis();
test_ready_anyway();
test_reset_on_seek();
return testfw::test_failures();
}