import io import logging import unittest from unittest import mock import bragi import constants import variables as var class FakeCache: def __init__(self): self.freed_id = None def free_and_delete(self, item_id): self.freed_id = item_id class FakeItem: id = "track-id" def is_ready(self): return True def is_failed(self): return False def format_debug_string(self): return "fake item" def format_title(self): return "Fake Item" class FakePlaylist: def __init__(self, item=None): self.item = item self.removed_id = None self.current_index = 0 if item else -1 def current_item(self): return self.item def remove_by_id(self, item_id): self.removed_id = item_id self.item = None self.current_index = -1 class FakeSoundOutput: def get_buffer_size(self): return 0 class FakeMumble: def __init__(self): self.sound_output = FakeSoundOutput() self.alive_checks = 0 def is_alive(self): self.alive_checks += 1 return self.alive_checks < 2 class FfmpegHttpErrorTests(unittest.TestCase): def setUp(self): constants.load_lang("en_US") def make_bot(self): bot = bragi.MumbleBot.__new__(bragi.MumbleBot) bot.thread_stderr = None bot.last_ffmpeg_err = "" bot.ffmpeg_fatal_error = "" bot.redirect_ffmpeg_log = False bot.log = logging.getLogger("test") return bot def test_ffmpeg_http_404_stderr_is_fatal(self): bot = self.make_bot() bot.thread_stderr = io.StringIO("[http @ 0x123] HTTP error 404 Not Found\n") bot._read_ffmpeg_stderr() self.assertEqual(bot.ffmpeg_fatal_error, "[http @ 0x123] HTTP error 404 Not Found") def test_ffmpeg_fatal_error_removes_current_item(self): item = FakeItem() var.playlist = FakePlaylist(item) var.cache = FakeCache() bot = self.make_bot() bot.ffmpeg_fatal_error = "[http @ 0x123] HTTP error 404 Not Found" bot._cleanup_ffmpeg_process = mock.Mock() bot.send_channel_msg = mock.Mock() bot._fail_current_ffmpeg_item() bot._cleanup_ffmpeg_process.assert_called_once_with() self.assertEqual(var.playlist.removed_id, item.id) self.assertEqual(var.cache.freed_id, item.id) bot.send_channel_msg.assert_called_once() self.assertEqual(bot.ffmpeg_fatal_error, "") def test_waiting_ready_item_ignores_stale_ffmpeg_stderr_before_launch(self): item = FakeItem() var.playlist = FakePlaylist(item) var.cache = FakeCache() bot = self.make_bot() bot.mumble = FakeMumble() bot.thread = None bot.is_pause = False bot.wait_for_ready = True bot.exit = False bot.read_pcm_size = 0 bot.pcm_buffer_size = 1920 bot.playhead = 0 bot.song_start_at = -1 bot._loop_status = "" bot.last_ffmpeg_err = "[aist#0:0/pcm_s16le] Guessed Channel Layout: stereo" bot._cleanup_ffmpeg_process = mock.Mock(return_value=None) bot.launch_music = mock.Mock() bot.async_download_next = mock.Mock() bot.send_channel_msg = mock.Mock() with mock.patch("bragi.time.sleep", return_value=None): bragi.MumbleBot.loop(bot) bot.launch_music.assert_called_once_with(item, 0) bot.async_download_next.assert_called_once_with() self.assertIsNone(var.playlist.removed_id) self.assertIsNone(var.cache.freed_id) bot.send_channel_msg.assert_not_called() self.assertFalse(bot.wait_for_ready) if __name__ == "__main__": unittest.main()