diff options
author | Zachary Ware <zachary.ware@gmail.com> | 2016-09-05 21:06:56 (GMT) |
---|---|---|
committer | Zachary Ware <zachary.ware@gmail.com> | 2016-09-05 21:06:56 (GMT) |
commit | b3b7a5a16b4e3c5bdd8d378d95e0645ab16a9547 (patch) | |
tree | 8e0166b33b269db054aadeb9d82f18b687492b88 /Lib | |
parent | f7e2ea2f333f166575dcf6e4ccadf7b3bff6c712 (diff) | |
download | cpython-b3b7a5a16b4e3c5bdd8d378d95e0645ab16a9547.zip cpython-b3b7a5a16b4e3c5bdd8d378d95e0645ab16a9547.tar.gz cpython-b3b7a5a16b4e3c5bdd8d378d95e0645ab16a9547.tar.bz2 |
Issue #27748: Simplify test_winsound.
The tests no longer attempt to figure out if a soundcard or particular
system sounds are available. Instead, it just tries everything and
accepts RuntimeError as a flavor of success.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/check_soundcard.vbs | 13 | ||||
-rw-r--r-- | Lib/test/test_winsound.py | 252 |
2 files changed, 62 insertions, 203 deletions
diff --git a/Lib/test/check_soundcard.vbs b/Lib/test/check_soundcard.vbs deleted file mode 100644 index 8c21852..0000000 --- a/Lib/test/check_soundcard.vbs +++ /dev/null @@ -1,13 +0,0 @@ -rem Check for a working sound-card - exit with 0 if OK, 1 otherwise. -set wmi = GetObject("winmgmts:") -set scs = wmi.InstancesOf("win32_sounddevice") -for each sc in scs - set status = sc.Properties_("Status") - wscript.Echo(sc.Properties_("Name") + "/" + status) - if status = "OK" then - wscript.Quit 0 rem normal exit - end if -next -rem No sound card found - exit with status code of 1 -wscript.Quit 1 - diff --git a/Lib/test/test_winsound.py b/Lib/test/test_winsound.py index 2a78388..4a8ab7d 100644 --- a/Lib/test/test_winsound.py +++ b/Lib/test/test_winsound.py @@ -1,38 +1,42 @@ # Ridiculously simple test of the winsound module for Windows. -import unittest -from test import support -support.requires('audio') -import time +import functools import os import subprocess +import time +import unittest + +from test import support +support.requires('audio') winsound = support.import_module('winsound') -ctypes = 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() == 0: - return False - - key = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, - "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound)) - return winreg.EnumValue(key, 0)[1] != "" - except OSError: - return False + + +# Unless we actually have an ear in the room, we have no idea whether a sound +# actually plays, and it's incredibly flaky trying to figure out if a sound +# even *should* play. Instead of guessing, just call the function and assume +# it either passed or raised the RuntimeError we expect in case of failure. +def sound_func(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: + ret = func(*args, **kwargs) + except RuntimeError as e: + if support.verbose: + print(func.__name__, 'failed:', e) + else: + if support.verbose: + print(func.__name__, 'returned') + return ret + return wrapper + + +safe_Beep = sound_func(winsound.Beep) +safe_MessageBeep = sound_func(winsound.MessageBeep) +safe_PlaySound = sound_func(winsound.PlaySound) + 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) @@ -40,27 +44,12 @@ class BeepTest(unittest.TestCase): self.assertRaises(ValueError, winsound.Beep, 32768, 75) def test_extremes(self): - self._beep(37, 75) - self._beep(32767, 75) + safe_Beep(37, 75) + safe_Beep(32767, 75) def test_increasingfrequency(self): for i in range(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 + safe_Beep(i, 75) class MessageBeepTest(unittest.TestCase): @@ -70,22 +59,22 @@ class MessageBeepTest(unittest.TestCase): def test_default(self): self.assertRaises(TypeError, winsound.MessageBeep, "bad") self.assertRaises(TypeError, winsound.MessageBeep, 42, 42) - winsound.MessageBeep() + safe_MessageBeep() def test_ok(self): - winsound.MessageBeep(winsound.MB_OK) + safe_MessageBeep(winsound.MB_OK) def test_asterisk(self): - winsound.MessageBeep(winsound.MB_ICONASTERISK) + safe_MessageBeep(winsound.MB_ICONASTERISK) def test_exclamation(self): - winsound.MessageBeep(winsound.MB_ICONEXCLAMATION) + safe_MessageBeep(winsound.MB_ICONEXCLAMATION) def test_hand(self): - winsound.MessageBeep(winsound.MB_ICONHAND) + safe_MessageBeep(winsound.MB_ICONHAND) def test_question(self): - winsound.MessageBeep(winsound.MB_ICONQUESTION) + safe_MessageBeep(winsound.MB_ICONQUESTION) class PlaySoundTest(unittest.TestCase): @@ -99,151 +88,34 @@ class PlaySoundTest(unittest.TestCase): "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_aliases(self): + aliases = [ + "SystemAsterisk", + "SystemExclamation", + "SystemExit", + "SystemHand", + "SystemQuestion", + ] + for alias in aliases: + with self.subTest(alias=alias): + safe_PlaySound(alias, winsound.SND_ALIAS) def test_alias_fallback(self): - # In the absence 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 + safe_PlaySound('!"$%&/(#+*', winsound.SND_ALIAS) 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 - ) + safe_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() - p.stdout.close() - return __have_soundcard_cache + safe_PlaySound( + 'SystemQuestion', + winsound.SND_ALIAS | winsound.SND_ASYNC | winsound.SND_LOOP + ) + time.sleep(0.5) + safe_PlaySound('SystemQuestion', winsound.SND_ALIAS | winsound.SND_NOSTOP) + # Issue 8367: PlaySound(None, winsound.SND_PURGE) + # does not raise on systems without a sound card. + winsound.PlaySound(None, winsound.SND_PURGE) if __name__ == "__main__": |