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