Files
sonus/tests/control.cpp
T
khodowany 5600f03fc1
publish / publish (push) Successful in 13m13s
Cleanup
2026-09-24 19:44:00 -05:00

106 lines
3.2 KiB
C++

#include <boost/test/unit_test.hpp>
#include <atomic>
#include <algorithm>
#include <barrier>
#include <cmath>
#include <thread>
#include <vector>
#include <sonus.hpp>
#include "detail/playback_devices.hpp"
#include "detail/metronome_player.hpp"
BOOST_AUTO_TEST_CASE(sonus_updates_cannot_undo_concurrent_start_or_stop) {
auto config = sonus::audio_config{};
config.no_device = true;
auto created = sonus::engine::create(config);
BOOST_REQUIRE(created);
auto rendezvous = std::barrier{2};
auto failed = std::atomic<bool>{false};
auto updater = std::thread{[&] {
for (auto index = 0; index < 1000; ++index) {
for (auto phase = 0; phase < 2; ++phase) {
rendezvous.arrive_and_wait();
if (!created->update_metronome({})) {
failed.store(true);
}
rendezvous.arrive_and_wait();
}
}
}};
for (auto index = 0; index < 1000; ++index) {
rendezvous.arrive_and_wait();
if (!created->start_metronome({})) {
failed.store(true);
}
rendezvous.arrive_and_wait();
if (!created->metronome_active()) {
failed.store(true);
}
rendezvous.arrive_and_wait();
created->stop_metronome();
rendezvous.arrive_and_wait();
if (created->metronome_active()) {
failed.store(true);
}
}
updater.join();
BOOST_TEST(!failed.load());
}
BOOST_AUTO_TEST_CASE(sonus_device_selection_handles_empty_and_duplicate_devices) {
auto devices = std::vector<sonus::device_info>{
{.id = "0:1:speaker", .name = "speaker", .is_default = true},
{.id = "1:0:speaker", .name = "speaker", .is_default = false},
};
auto select = [&](auto id, auto name) {
return sonus::detail::find_playback_device(devices, id, name);
};
auto selected = select(devices[1].id, "speaker");
BOOST_REQUIRE(selected);
BOOST_TEST(*selected == 1U);
selected = select("stale-id", "speaker");
BOOST_REQUIRE(selected);
BOOST_TEST(*selected == 0U);
selected = select("", "speaker");
BOOST_REQUIRE(selected);
BOOST_TEST(*selected == 0U);
BOOST_TEST(!select("stale-id", ""));
BOOST_TEST(!select("", ""));
BOOST_TEST(!select("", "missing"));
devices.clear();
BOOST_TEST(!select("0:1:speaker", "speaker"));
}
BOOST_AUTO_TEST_CASE(sonus_metronome_player_publication_overlaps_audio_rendering) {
auto player = sonus::detail::metronome_player{};
auto done = std::atomic_bool{false};
auto valid = std::atomic_bool{true};
auto reader = std::thread{[&] {
auto samples = std::vector<std::float32_t>(128U);
while (!done.load()) {
std::fill(samples.begin(), samples.end(), 0.0F);
player.render(samples.data(), 64U, 2U);
for (auto sample : samples) {
if (!std::isfinite(sample) || sample < -1.0F || sample > 1.0F) {
valid.store(false);
}
}
}
}};
for (auto index = std::uint32_t{}; index < 1000U; ++index) {
player.configure({.bpm = 60U + index % 180U}, 48000U, true);
player.stop();
}
done.store(true);
reader.join();
player.collect();
BOOST_TEST(valid.load());
BOOST_TEST(!player.active());
auto silence = std::vector<std::float32_t>(128U);
player.render(silence.data(), 64U, 2U);
BOOST_TEST(std::all_of(silence.begin(), silence.end(), [](auto sample) { return sample == 0.0F; }));
}