1 # Ridiculously simple test of the winsound module for Windows.
2
3 import functools
4 import pathlib
5 import time
6 import unittest
7
8 from test import support
9 from test.support import import_helper
10
11
12 support.requires('audio')
13 winsound = import_helper.import_module('winsound')
14
15
16 # Unless we actually have an ear in the room, we have no idea whether a sound
17 # actually plays, and it's incredibly flaky trying to figure out if a sound
18 # even *should* play. Instead of guessing, just call the function and assume
19 # it either passed or raised the RuntimeError we expect in case of failure.
20 def sound_func(func):
21 @functools.wraps(func)
22 def wrapper(*args, **kwargs):
23 try:
24 ret = func(*args, **kwargs)
25 except RuntimeError as e:
26 if support.verbose:
27 print(func.__name__, 'failed:', e)
28 else:
29 if support.verbose:
30 print(func.__name__, 'returned')
31 return ret
32 return wrapper
33
34
35 safe_Beep = sound_func(winsound.Beep)
36 safe_MessageBeep = sound_func(winsound.MessageBeep)
37 safe_PlaySound = sound_func(winsound.PlaySound)
38
39
40 class ESC[4;38;5;81mBeepTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
41
42 def test_errors(self):
43 self.assertRaises(TypeError, winsound.Beep)
44 self.assertRaises(ValueError, winsound.Beep, 36, 75)
45 self.assertRaises(ValueError, winsound.Beep, 32768, 75)
46
47 def test_extremes(self):
48 safe_Beep(37, 75)
49 safe_Beep(32767, 75)
50
51 def test_increasingfrequency(self):
52 for i in range(100, 2000, 100):
53 safe_Beep(i, 75)
54
55 def test_keyword_args(self):
56 safe_Beep(duration=75, frequency=2000)
57
58
59 class ESC[4;38;5;81mMessageBeepTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
60
61 def tearDown(self):
62 time.sleep(0.5)
63
64 def test_default(self):
65 self.assertRaises(TypeError, winsound.MessageBeep, "bad")
66 self.assertRaises(TypeError, winsound.MessageBeep, 42, 42)
67 safe_MessageBeep()
68
69 def test_ok(self):
70 safe_MessageBeep(winsound.MB_OK)
71
72 def test_asterisk(self):
73 safe_MessageBeep(winsound.MB_ICONASTERISK)
74
75 def test_exclamation(self):
76 safe_MessageBeep(winsound.MB_ICONEXCLAMATION)
77
78 def test_hand(self):
79 safe_MessageBeep(winsound.MB_ICONHAND)
80
81 def test_question(self):
82 safe_MessageBeep(winsound.MB_ICONQUESTION)
83
84 def test_keyword_args(self):
85 safe_MessageBeep(type=winsound.MB_OK)
86
87
88 # A class for testing winsound when the given path resolves
89 # to bytes rather than str.
90 class ESC[4;38;5;81mBytesPath(ESC[4;38;5;149mpathlibESC[4;38;5;149m.ESC[4;38;5;149mWindowsPath):
91 def __fspath__(self):
92 return bytes(super().__fspath__(), 'UTF-8')
93
94
95 class ESC[4;38;5;81mPlaySoundTest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
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 self.assertRaises(TypeError, winsound.PlaySound, b"bad", 0)
106 self.assertRaises(TypeError, winsound.PlaySound, "bad",
107 winsound.SND_MEMORY)
108 self.assertRaises(TypeError, winsound.PlaySound, 1, 0)
109 # embedded null character
110 self.assertRaises(ValueError, winsound.PlaySound, 'bad\0', 0)
111
112 def test_keyword_args(self):
113 safe_PlaySound(flags=winsound.SND_ALIAS, sound="SystemExit")
114
115 def test_snd_memory(self):
116 with open(support.findfile('pluck-pcm8.wav',
117 subdir='audiodata'), 'rb') as f:
118 audio_data = f.read()
119 safe_PlaySound(audio_data, winsound.SND_MEMORY)
120 audio_data = bytearray(audio_data)
121 safe_PlaySound(audio_data, winsound.SND_MEMORY)
122
123 def test_snd_filename(self):
124 fn = support.findfile('pluck-pcm8.wav', subdir='audiodata')
125 safe_PlaySound(fn, winsound.SND_FILENAME | winsound.SND_NODEFAULT)
126
127 def test_snd_filepath(self):
128 fn = support.findfile('pluck-pcm8.wav', subdir='audiodata')
129 path = pathlib.Path(fn)
130 safe_PlaySound(path, winsound.SND_FILENAME | winsound.SND_NODEFAULT)
131
132 def test_snd_filepath_as_bytes(self):
133 fn = support.findfile('pluck-pcm8.wav', subdir='audiodata')
134 self.assertRaises(
135 TypeError,
136 winsound.PlaySound,
137 BytesPath(fn),
138 winsound.SND_FILENAME | winsound.SND_NODEFAULT
139 )
140
141 def test_aliases(self):
142 aliases = [
143 "SystemAsterisk",
144 "SystemExclamation",
145 "SystemExit",
146 "SystemHand",
147 "SystemQuestion",
148 ]
149 for alias in aliases:
150 with self.subTest(alias=alias):
151 safe_PlaySound(alias, winsound.SND_ALIAS)
152
153 def test_alias_fallback(self):
154 safe_PlaySound('!"$%&/(#+*', winsound.SND_ALIAS)
155
156 def test_alias_nofallback(self):
157 safe_PlaySound('!"$%&/(#+*', winsound.SND_ALIAS | winsound.SND_NODEFAULT)
158
159 def test_stopasync(self):
160 safe_PlaySound(
161 'SystemQuestion',
162 winsound.SND_ALIAS | winsound.SND_ASYNC | winsound.SND_LOOP
163 )
164 time.sleep(0.5)
165 safe_PlaySound('SystemQuestion', winsound.SND_ALIAS | winsound.SND_NOSTOP)
166 # Issue 8367: PlaySound(None, winsound.SND_PURGE)
167 # does not raise on systems without a sound card.
168 winsound.PlaySound(None, winsound.SND_PURGE)
169
170
171 if __name__ == "__main__":
172 unittest.main()