from __future__ import unicode_literals # So that we can format strings with Unicode characters import random import sys from StringIO import StringIO from robot_interface.utils.microphone import ( choose_mic_default, choose_mic_interactive, choose_mic_arguments, choose_mic, get_microphones, ) class MicrophoneUtils(object): """Shared tests for any PyAudio-like implementation, e.g. mock and real.""" def test_choose_mic_default(self, pyaudio_instance): """ The result must contain at least "index", as this is used to identify the microphone. The "name" is used for logging, so it should also exist. It must have one or more channels. Lastly it must be capable of sending at least 16000 samples per second. """ result = choose_mic_default(pyaudio_instance) assert "index" in result assert isinstance(result["index"], (int, long)) assert "name" in result assert isinstance(result["name"], (str, unicode)) assert "maxInputChannels" in result assert isinstance(result["maxInputChannels"], (int, long)) assert result["maxInputChannels"] > 0 assert "defaultSampleRate" in result assert isinstance(result["defaultSampleRate"], float) assert result["defaultSampleRate"] >= 16000 def test_choose_mic_interactive_input_not_int(self, pyaudio_instance, mocker): """ First mock an input that's not an integer, then a valid integer. There should be no errors. """ microphones = get_microphones(pyaudio_instance) target_microphone = next(microphones) mock_input = mocker.patch("__builtin__.raw_input", side_effect=["not an integer", "0"]) fake_out = StringIO() mocker.patch.object(sys, "stdout", fake_out) result = choose_mic_interactive(pyaudio_instance) assert "index" in result assert isinstance(result["index"], (int, long)) assert result["index"] == target_microphone["index"] assert mock_input.called assert any(p.startswith("Please enter a number") for p in fake_out.getvalue().splitlines()) def test_choose_mic_interactive_negative_index(self, pyaudio_instance, mocker): """ Make sure that the interactive method does not allow negative integers as input. """ microphones = get_microphones(pyaudio_instance) target_microphone = next(microphones) mock_input = mocker.patch("__builtin__.raw_input", side_effect=["-1", "0"]) fake_out = StringIO() mocker.patch.object(sys, "stdout", fake_out) result = choose_mic_interactive(pyaudio_instance) assert "index" in result assert isinstance(result["index"], (int, long)) assert result["index"] == target_microphone["index"] assert mock_input.called assert any(p.startswith("Please enter a number") for p in fake_out.getvalue().splitlines()) def test_choose_mic_interactive_index_too_high(self, pyaudio_instance, mocker): """ Make sure that the interactive method does not allow indices higher than the highest mic index. """ real_count = len(list(get_microphones(pyaudio_instance))) mock_input = mocker.patch("__builtin__.raw_input", side_effect=[str(real_count), "0"]) fake_out = StringIO() mocker.patch.object(sys, "stdout", fake_out) result = choose_mic_interactive(pyaudio_instance) assert "index" in result assert isinstance(result["index"], (int, long)) assert mock_input.called assert any(p.startswith("Please enter a number") for p in fake_out.getvalue().splitlines()) def test_choose_mic_interactive_random_index(self, pyaudio_instance, mocker): """ Get a random index from the list of available mics, make sure it's correct. """ microphones = list(get_microphones(pyaudio_instance)) random_index = random.randrange(len(microphones)) mocker.patch("__builtin__.raw_input", side_effect=[str(random_index)]) result = choose_mic_interactive(pyaudio_instance) assert "index" in result assert isinstance(result["index"], (int, long)) assert result["index"] == microphones[random_index]["index"] def test_choose_mic_no_arguments(self, pyaudio_instance, mocker): mocker.patch.object(sys, "argv", []) result = choose_mic_arguments(pyaudio_instance) assert result is None def test_choose_mic_arguments(self, pyaudio_instance, mocker): for mic in get_microphones(pyaudio_instance): mocker.patch.object(sys, "argv", ["--microphone", mic["name"]]) result = choose_mic_arguments(pyaudio_instance) assert result is not None assert result == mic def test_choose_mic_arguments_eq(self, pyaudio_instance, mocker): for mic in get_microphones(pyaudio_instance): mocker.patch.object(sys, "argv", ["--microphone={}".format(mic["name"])]) result = choose_mic_arguments(pyaudio_instance) assert result is not None assert result == mic def test_choose_mic_arguments_not_exits(self, pyaudio_instance, mocker): mocker.patch.object(sys, "argv", ["--microphone", "Surely this microphone doesn't exist"]) result = choose_mic_arguments(pyaudio_instance) assert result is None def test_choose_mic_with_argument(self, pyaudio_instance, mocker): mic = next(get_microphones(pyaudio_instance)) mocker.patch.object(sys, "argv", ["--microphone", mic["name"]]) result = choose_mic(pyaudio_instance) assert result is not None assert result == mic def test_choose_mic_no_argument(self, pyaudio_instance, mocker): default_mic = choose_mic_default(pyaudio_instance) mocker.patch.object(sys, "argv", []) result = choose_mic(pyaudio_instance) assert result is not None assert result == default_mic