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 import time
      6 import os
      7 import subprocess
      8 
      9 winsound = test_support.import_module('winsound')
     10 ctypes = test_support.import_module('ctypes')
     11 import _winreg
     12 
     13 def has_sound(sound):
     14     """Find out if a particular event is configured with a default sound"""
     15     try:
     16         # Ask the mixer API for the number of devices it knows about.

     17         # When there are no devices, PlaySound will fail.

     18         if ctypes.windll.winmm.mixerGetNumDevs() is 0:
     19             return False
     20 
     21         key = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER,
     22                 "AppEvents\Schemes\Apps\.Default\{0}\.Default".format(sound))
     23         value = _winreg.EnumValue(key, 0)[1]
     24         if value is not u"":
     25             return True
     26         else:
     27             return False
     28     except WindowsError:
     29         return False
     30 
     31 class BeepTest(unittest.TestCase):
     32     # As with PlaySoundTest, incorporate the _have_soundcard() check

     33     # into our test methods.  If there's no audio device present,

     34     # winsound.Beep returns 0 and GetLastError() returns 127, which

     35     # is: ERROR_PROC_NOT_FOUND ("The specified procedure could not

     36     # be found").  (FWIW, virtual/Hyper-V systems fall under this

     37     # scenario as they have no sound devices whatsoever  (not even

     38     # a legacy Beep device).)

     39 
     40     def test_errors(self):
     41         self.assertRaises(TypeError, winsound.Beep)
     42         self.assertRaises(ValueError, winsound.Beep, 36, 75)
     43         self.assertRaises(ValueError, winsound.Beep, 32768, 75)
     44 
     45     def test_extremes(self):
     46         self._beep(37, 75)
     47         self._beep(32767, 75)
     48 
     49     def test_increasingfrequency(self):
     50         for i in xrange(100, 2000, 100):
     51             self._beep(i, 75)
     52 
     53     def _beep(self, *args):
     54         # these tests used to use _have_soundcard(), but it's quite

     55         # possible to have a soundcard, and yet have the beep driver

     56         # disabled. So basically, we have no way of knowing whether

     57         # a beep should be produced or not, so currently if these

     58         # tests fail we're ignoring them

     59         #

     60         # XXX the right fix for this is to define something like

     61         # _have_enabled_beep_driver() and use that instead of the

     62         # try/except below

     63         try:
     64             winsound.Beep(*args)
     65         except RuntimeError:
     66             pass
     67 
     68 class MessageBeepTest(unittest.TestCase):
     69 
     70     def tearDown(self):
     71         time.sleep(0.5)
     72 
     73     def test_default(self):
     74         self.assertRaises(TypeError, winsound.MessageBeep, "bad")
     75         self.assertRaises(TypeError, winsound.MessageBeep, 42, 42)
     76         winsound.MessageBeep()
     77 
     78     def test_ok(self):
     79         winsound.MessageBeep(winsound.MB_OK)
     80 
     81     def test_asterisk(self):
     82         winsound.MessageBeep(winsound.MB_ICONASTERISK)
     83 
     84     def test_exclamation(self):
     85         winsound.MessageBeep(winsound.MB_ICONEXCLAMATION)
     86 
     87     def test_hand(self):
     88         winsound.MessageBeep(winsound.MB_ICONHAND)
     89 
     90     def test_question(self):
     91         winsound.MessageBeep(winsound.MB_ICONQUESTION)
     92 
     93 
     94 class PlaySoundTest(unittest.TestCase):
     95 
     96     def test_errors(self):
     97         self.assertRaises(TypeError, winsound.PlaySound)
     98         self.assertRaises(TypeError, winsound.PlaySound, "bad", "bad")
     99         self.assertRaises(
    100             RuntimeError,
    101             winsound.PlaySound,
    102             "none", winsound.SND_ASYNC | winsound.SND_MEMORY
    103         )
    104 
    105     @unittest.skipUnless(has_sound("SystemAsterisk"), "No default SystemAsterisk")
    106     def test_alias_asterisk(self):
    107         if _have_soundcard():
    108             winsound.PlaySound('SystemAsterisk', winsound.SND_ALIAS)
    109         else:
    110             self.assertRaises(
    111                 RuntimeError,
    112                 winsound.PlaySound,
    113                 'SystemAsterisk', winsound.SND_ALIAS
    114             )
    115 
    116     @unittest.skipUnless(has_sound("SystemExclamation"), "No default SystemExclamation")
    117     def test_alias_exclamation(self):
    118         if _have_soundcard():
    119             winsound.PlaySound('SystemExclamation', winsound.SND_ALIAS)
    120         else:
    121             self.assertRaises(
    122                 RuntimeError,
    123                 winsound.PlaySound,
    124                 'SystemExclamation', winsound.SND_ALIAS
    125             )
    126 
    127     @unittest.skipUnless(has_sound("SystemExit"), "No default SystemExit")
    128     def test_alias_exit(self):
    129         if _have_soundcard():
    130             winsound.PlaySound('SystemExit', winsound.SND_ALIAS)
    131         else:
    132             self.assertRaises(
    133                 RuntimeError,
    134                 winsound.PlaySound,
    135                 'SystemExit', winsound.SND_ALIAS
    136             )
    137 
    138     @unittest.skipUnless(has_sound("SystemHand"), "No default SystemHand")
    139     def test_alias_hand(self):
    140         if _have_soundcard():
    141             winsound.PlaySound('SystemHand', winsound.SND_ALIAS)
    142         else:
    143             self.assertRaises(
    144                 RuntimeError,
    145                 winsound.PlaySound,
    146                 'SystemHand', winsound.SND_ALIAS
    147             )
    148 
    149     @unittest.skipUnless(has_sound("SystemQuestion"), "No default SystemQuestion")
    150     def test_alias_question(self):
    151         if _have_soundcard():
    152             winsound.PlaySound('SystemQuestion', winsound.SND_ALIAS)
    153         else:
    154             self.assertRaises(
    155                 RuntimeError,
    156                 winsound.PlaySound,
    157                 'SystemQuestion', winsound.SND_ALIAS
    158             )
    159 
    160     def test_alias_fallback(self):
    161         # This test can't be expected to work on all systems.  The MS

    162         # PlaySound() docs say:

    163         #

    164         #     If it cannot find the specified sound, PlaySound uses the

    165         #     default system event sound entry instead.  If the function

    166         #     can find neither the system default entry nor the default

    167         #     sound, it makes no sound and returns FALSE.

    168         #

    169         # It's known to return FALSE on some real systems.

    170 
    171         # winsound.PlaySound('!"$%&/(#+*', winsound.SND_ALIAS)

    172         return
    173 
    174     def test_alias_nofallback(self):
    175         if _have_soundcard():
    176             # Note that this is not the same as asserting RuntimeError

    177             # will get raised:  you cannot convert this to

    178             # self.assertRaises(...) form.  The attempt may or may not

    179             # raise RuntimeError, but it shouldn't raise anything other

    180             # than RuntimeError, and that's all we're trying to test

    181             # here.  The MS docs aren't clear about whether the SDK

    182             # PlaySound() with SND_ALIAS and SND_NODEFAULT will return

    183             # True or False when the alias is unknown.  On Tim's WinXP

    184             # box today, it returns True (no exception is raised).  What

    185             # we'd really like to test is that no sound is played, but

    186             # that requires first wiring an eardrum class into unittest

    187             # <wink>.

    188             try:
    189                 winsound.PlaySound(
    190                     '!"$%&/(#+*',
    191                     winsound.SND_ALIAS | winsound.SND_NODEFAULT
    192                 )
    193             except RuntimeError:
    194                 pass
    195         else:
    196             self.assertRaises(
    197                 RuntimeError,
    198                 winsound.PlaySound,
    199                 '!"$%&/(#+*', winsound.SND_ALIAS | winsound.SND_NODEFAULT
    200             )
    201 
    202     def test_stopasync(self):
    203         if _have_soundcard():
    204             winsound.PlaySound(
    205                 'SystemQuestion',
    206                 winsound.SND_ALIAS | winsound.SND_ASYNC | winsound.SND_LOOP
    207             )
    208             time.sleep(0.5)
    209             try:
    210                 winsound.PlaySound(
    211                     'SystemQuestion',
    212                     winsound.SND_ALIAS | winsound.SND_NOSTOP
    213                 )
    214             except RuntimeError:
    215                 pass
    216             else: # the first sound might already be finished

    217                 pass
    218             winsound.PlaySound(None, winsound.SND_PURGE)
    219         else:
    220             # Issue 8367: PlaySound(None, winsound.SND_PURGE)

    221             # does not raise on systems without a sound card.

    222             pass
    223 
    224 
    225 def _get_cscript_path():
    226     """Return the full path to cscript.exe or None."""
    227     for dir in os.environ.get("PATH", "").split(os.pathsep):
    228         cscript_path = os.path.join(dir, "cscript.exe")
    229         if os.path.exists(cscript_path):
    230             return cscript_path
    231 
    232 __have_soundcard_cache = None
    233 def _have_soundcard():
    234     """Return True iff this computer has a soundcard."""
    235     global __have_soundcard_cache
    236     if __have_soundcard_cache is None:
    237         cscript_path = _get_cscript_path()
    238         if cscript_path is None:
    239             # Could not find cscript.exe to run our VBScript helper. Default

    240             # to True: most computers these days *do* have a soundcard.

    241             return True
    242 
    243         check_script = os.path.join(os.path.dirname(__file__),
    244                                     "check_soundcard.vbs")
    245         p = subprocess.Popen([cscript_path, check_script],
    246                              stdout=subprocess.PIPE)
    247         __have_soundcard_cache = not p.wait()
    248     return __have_soundcard_cache
    249 
    250 
    251 def test_main():
    252     test_support.run_unittest(BeepTest, MessageBeepTest, PlaySoundTest)
    253 
    254 if __name__=="__main__":
    255     test_main()
    256