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