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