1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | Lib/test/test_winsound.py
# Ridiculously simple test of the winsound module for Windows. import unittest from test import test_support test_support.requires('audio') import time import os import subprocess winsound = test_support.import_module('winsound') ctypes = test_support.import_module('ctypes') import _winreg def has_sound(sound): """Find out if a particular event is configured with a default sound""" try: # Ask the mixer API for the number of devices it knows about. # When there are no devices, PlaySound will fail. if ctypes.windll.winmm.mixerGetNumDevs() is 0: return False key = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) value = _winreg.EnumValue(key, 0)[1] if value is not u"": return True else: return False except WindowsError: return False class BeepTest(unittest.TestCase): # As with PlaySoundTest, incorporate the _have_soundcard() check # into our test methods. If there's no audio device present, # winsound.Beep returns 0 and GetLastError() returns 127, which # is: ERROR_PROC_NOT_FOUND ("The specified procedure could not # be found"). (FWIW, virtual/Hyper-V systems fall under this # scenario as they have no sound devices whatsoever (not even # a legacy Beep device).) def test_errors(self): self.assertRaises(TypeError, winsound.Beep) self.assertRaises(ValueError, winsound.Beep, 36, 75) self.assertRaises(ValueError, winsound.Beep, 32768, 75) def test_extremes(self): self._beep(37, 75) self._beep(32767, 75) def test_increasingfrequency(self): for i in xrange(100, 2000, 100): self._beep(i, 75) def _beep(self, *args): # these tests used to use _have_soundcard(), but it's quite # possible to have a soundcard, and yet have the beep driver # disabled. So basically, we have no way of knowing whether # a beep should be produced or not, so currently if these # tests fail we're ignoring them # # XXX the right fix for this is to define something like # _have_enabled_beep_driver() and use that instead of the # try/except below try: winsound.Beep(*args) except RuntimeError: pass class MessageBeepTest(unittest.TestCase): def tearDown(self): time.sleep(0.5) def test_default(self): self.assertRaises(TypeError, winsound.MessageBeep, "bad") self.assertRaises(TypeError, winsound.MessageBeep, 42, 42) winsound.MessageBeep() def test_ok(self): winsound.MessageBeep(winsound.MB_OK) def test_asterisk(self): winsound.MessageBeep(winsound.MB_ICONASTERISK) def test_exclamation(self): winsound.MessageBeep(winsound.MB_ICONEXCLAMATION) def test_hand(self): winsound.MessageBeep(winsound.MB_ICONHAND) def test_question(self): winsound.MessageBeep(winsound.MB_ICONQUESTION) class PlaySoundTest(unittest.TestCase): def test_errors(self): self.assertRaises(TypeError, winsound.PlaySound) self.assertRaises(TypeError, winsound.PlaySound, "bad", "bad") self.assertRaises( RuntimeError, winsound.PlaySound, "none", winsound.SND_ASYNC | winsound.SND_MEMORY ) @unittest.skipUnless(has_sound("SystemAsterisk"), "No default SystemAsterisk") def test_alias_asterisk(self): if _have_soundcard(): winsound.PlaySound('SystemAsterisk', winsound.SND_ALIAS) else: self.assertRaises( RuntimeError, winsound.PlaySound, 'SystemAsterisk', winsound.SND_ALIAS ) @unittest.skipUnless(has_sound("SystemExclamation"), "No default SystemExclamation") def test_alias_exclamation(self): if _have_soundcard(): winsound.PlaySound('SystemExclamation', winsound.SND_ALIAS) else: self.assertRaises( RuntimeError, winsound.PlaySound, 'SystemExclamation', winsound.SND_ALIAS ) @unittest.skipUnless(has_sound("SystemExit"), "No default SystemExit") def test_alias_exit(self): if _have_soundcard(): winsound.PlaySound('SystemExit', winsound.SND_ALIAS) else: self.assertRaises( RuntimeError, winsound.PlaySound, 'SystemExit', winsound.SND_ALIAS ) @unittest.skipUnless(has_sound("SystemHand"), "No default SystemHand") def test_alias_hand(self): if _have_soundcard(): winsound.PlaySound('SystemHand', winsound.SND_ALIAS) else: self.assertRaises( RuntimeError, winsound.PlaySound, 'SystemHand', winsound.SND_ALIAS ) @unittest.skipUnless(has_sound("SystemQuestion"), "No default SystemQuestion") def test_alias_question(self): if _have_soundcard(): winsound.PlaySound('SystemQuestion', winsound.SND_ALIAS) else: self.assertRaises( RuntimeError, winsound.PlaySound, 'SystemQuestion', winsound.SND_ALIAS ) def test_alias_fallback(self): # In the absense of the ability to tell if a sound was actually # played, this test has two acceptable outcomes: success (no error, # sound was theoretically played; although as issue #19987 shows # a box without a soundcard can "succeed") or RuntimeError. Any # other error is a failure. try: winsound.PlaySound('!"$%&/(#+*', winsound.SND_ALIAS) except RuntimeError: pass def test_alias_nofallback(self): if _have_soundcard(): # Note that this is not the same as asserting RuntimeError # will get raised: you cannot convert this to # self.assertRaises(...) form. The attempt may or may not # raise RuntimeError, but it shouldn't raise anything other # than RuntimeError, and that's all we're trying to test # here. The MS docs aren't clear about whether the SDK # PlaySound() with SND_ALIAS and SND_NODEFAULT will return # True or False when the alias is unknown. On Tim's WinXP # box today, it returns True (no exception is raised). What # we'd really like to test is that no sound is played, but # that requires first wiring an eardrum class into unittest # <wink>. try: winsound.PlaySound( '!"$%&/(#+*', winsound.SND_ALIAS | winsound.SND_NODEFAULT ) except RuntimeError: pass else: self.assertRaises( RuntimeError, winsound.PlaySound, '!"$%&/(#+*', winsound.SND_ALIAS | winsound.SND_NODEFAULT ) def test_stopasync(self): if _have_soundcard(): winsound.PlaySound( 'SystemQuestion', winsound.SND_ALIAS | winsound.SND_ASYNC | winsound.SND_LOOP ) time.sleep(0.5) try: winsound.PlaySound( 'SystemQuestion', winsound.SND_ALIAS | winsound.SND_NOSTOP ) except RuntimeError: pass else: # the first sound might already be finished pass winsound.PlaySound(None, winsound.SND_PURGE) else: # Issue 8367: PlaySound(None, winsound.SND_PURGE) # does not raise on systems without a sound card. pass def _get_cscript_path(): """Return the full path to cscript.exe or None.""" for dir in os.environ.get("PATH", "").split(os.pathsep): cscript_path = os.path.join(dir, "cscript.exe") if os.path.exists(cscript_path): return cscript_path __have_soundcard_cache = None def _have_soundcard(): """Return True iff this computer has a soundcard.""" global __have_soundcard_cache if __have_soundcard_cache is None: cscript_path = _get_cscript_path() if cscript_path is None: # Could not find cscript.exe to run our VBScript helper. Default # to True: most computers these days *do* have a soundcard. return True check_script = os.path.join(os.path.dirname(__file__), "check_soundcard.vbs") p = subprocess.Popen([cscript_path, check_script], stdout=subprocess.PIPE) __have_soundcard_cache = not p.wait() return __have_soundcard_cache def test_main(): test_support.run_unittest(BeepTest, MessageBeepTest, PlaySoundTest) if __name__=="__main__": test_main() |