import configparser import logging import os import tempfile import types import unittest from unittest import mock import bragi import constants from database import DatabaseMigration, MusicDatabase, SettingsDatabase import command import util import variables as var class FakeBot: def __init__(self): self.registered = [] def register_command(self, cmd, handle, no_partial_match=False, access_outside_channel=False, admin=False): self.registered.append(cmd) class FakePlaylist: def __init__(self, item=None): self.item = item def __len__(self): return 1 if self.item is not None else 0 def current_item(self): return self.item class ExhaustedPlaylist: current_index = -1 def next(self): return False 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 VolumeRestoreTests(unittest.TestCase): def setUp(self): settings_file = tempfile.NamedTemporaryFile(delete=False) settings_file.close() music_file = tempfile.NamedTemporaryFile(delete=False) music_file.close() self.settings_path = settings_file.name self.music_path = music_file.name self.settings_db = SettingsDatabase(self.settings_path) self.music_db = MusicDatabase(self.music_path) DatabaseMigration(self.settings_db, self.music_db).migrate() self.config = configparser.ConfigParser(interpolation=None, allow_no_value=True) self.config.read("configuration.default.ini", encoding="utf-8") var.config = self.config var.db = self.settings_db var.music_db = self.music_db var.cache = None var.playlist = [] def tearDown(self): os.unlink(self.settings_path) os.unlink(self.music_path) def make_bot(self): bot = bragi.MumbleBot.__new__(bragi.MumbleBot) bot.volume_helper = util.VolumeHelper() bot.volume_helper.set_volume(1.0) bot.thread = None bot.on_interrupting = False bot.song_start_at = -1 bot.read_pcm_size = 0 bot.is_pause = False bot.wait_for_ready = False bot.log = logging.getLogger("test") return bot def test_restore_volume_on_stop_updates_runtime_and_db_from_config(self): self.config.set("bot", "restore_volume_on_stop", "True") self.config.set("bot", "volume", "0.7") self.settings_db.set("bot", "volume", "1.0") bot = self.make_bot() bot.restore_default_volume() self.assertAlmostEqual(bot.volume_helper.plain_volume_set, 0.7) self.assertAlmostEqual(self.settings_db.getfloat("bot", "volume"), 0.7) def test_restore_volume_on_stop_respects_max_volume_limit(self): self.config.set("bot", "restore_volume_on_stop", "True") self.config.set("bot", "volume", "0.9") self.settings_db.set("bot", "max_volume", "0.5") bot = self.make_bot() bot.restore_default_volume() self.assertAlmostEqual(bot.volume_helper.plain_volume_set, 0.5) self.assertAlmostEqual(self.settings_db.getfloat("bot", "volume"), 0.5) def test_restore_volume_on_stop_is_disabled_by_default(self): self.config.set("bot", "restore_volume_on_stop", "False") self.config.set("bot", "volume", "0.7") self.settings_db.set("bot", "volume", "1.0") bot = self.make_bot() bot.restore_default_volume() self.assertAlmostEqual(bot.volume_helper.plain_volume_set, 1.0) self.assertAlmostEqual(self.settings_db.getfloat("bot", "volume"), 1.0) def test_stop_restores_default_volume(self): self.config.set("bot", "restore_volume_on_stop", "True") var.playlist = [object()] bot = self.make_bot() bot.restore_default_volume = mock.Mock() bot._cleanup_ffmpeg_process = mock.Mock() bot.stop() bot.restore_default_volume.assert_called_once_with() def test_pause_does_not_restore_default_volume(self): var.playlist = FakePlaylist(types.SimpleNamespace(id="track-id")) bot = self.make_bot() bot.playhead = 12.5 bot.restore_default_volume = mock.Mock() bot.pause() bot.restore_default_volume.assert_not_called() def test_loop_restores_volume_without_entering_pause_when_queue_runs_empty(self): var.playlist = ExhaustedPlaylist() bot = self.make_bot() bot.mumble = FakeMumble() bot.restore_default_volume = mock.Mock() bot._cleanup_ffmpeg_process = mock.Mock() bot.exit = False bot.last_ffmpeg_err = "" bot.pcm_buffer_size = 1 bot.read_pcm_size = 1 bot._loop_status = "" bragi.MumbleBot.loop(bot) bot.restore_default_volume.assert_called_once_with() self.assertFalse(bot.is_pause) class HelpTextTests(unittest.TestCase): def test_help_text_does_not_reference_web_interface(self): constants.load_lang("en_US") help_text = constants.tr_cli("help") admin_help = constants.tr_cli("admin_help") self.assertNotIn("!web", help_text) self.assertNotIn("web interface", help_text.lower()) self.assertNotIn("web interface", admin_help.lower()) class CommandRegistrationTests(unittest.TestCase): def setUp(self): self.config = configparser.ConfigParser(interpolation=None, allow_no_value=True) self.config.read("configuration.default.ini", encoding="utf-8") var.config = self.config def test_register_all_commands_excludes_web_commands(self): bot = FakeBot() command.register_all_commands(bot) registered = ",".join(bot.registered) self.assertIn(self.config.get("commands", "volume"), registered) self.assertNotIn("web", registered) self.assertNotIn("webuseradd", registered) self.assertNotIn("webuserlist", registered) self.assertNotIn("webuserdel", registered) if __name__ == "__main__": unittest.main()