/ tests / test_note_parser.py
test_note_parser.py
 1  # The MIT License (MIT)
 2  #
 3  # Copyright (c) 2019 Kevin J. Walters
 4  #
 5  # Permission is hereby granted, free of charge, to any person obtaining a copy
 6  # of this software and associated documentation files (the "Software"), to deal
 7  # in the Software without restriction, including without limitation the rights
 8  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9  # copies of the Software, and to permit persons to whom the Software is
10  # furnished to do so, subject to the following conditions:
11  #
12  # The above copyright notice and this permission notice shall be included in
13  # all copies or substantial portions of the Software.
14  #
15  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  # THE SOFTWARE.
22  
23  import unittest
24  from unittest.mock import Mock, MagicMock, call
25  
26  import random
27  import os
28  
29  verbose = int(os.getenv("TESTVERBOSE", "2"))
30  
31  # adafruit_midi had an import usb_midi
32  import sys
33  
34  # sys.modules['usb_midi'] = MagicMock()
35  
36  # Borrowing the dhalbert/tannewt technique from adafruit/Adafruit_CircuitPython_Motor
37  sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
38  
39  from adafruit_midi.midi_message import note_parser
40  
41  
42  class Test_note_parser(unittest.TestCase):
43      def text_int_passthru(self):
44          self.assertEqual(note_parser(0), 0)
45          self.assertEqual(note_parser(70), 70)
46          self.assertEqual(note_parser(127), 127)
47  
48          # it does not range check so these should pass
49          self.assertEqual(note_parser(-303), -303)
50          self.assertEqual(note_parser(808), 808)
51  
52      def test_good_text(self):
53          note_prefix = {
54              "Cb": 11,
55              "C": 12,
56              "C#": 13,
57              "Db": 13,
58              "D": 14,
59              "D#": 15,
60              "Eb": 15,
61              "E": 16,
62              "Fb": 16,
63              "E#": 17,
64              "F": 17,
65              "F#": 18,
66              "Gb": 18,
67              "G": 19,
68              "G#": 20,
69              "Ab": 20,
70              "A": 21,
71              "A#": 22,
72              "Bb": 22,
73              "B": 23,
74              "B#": 24,
75          }
76  
77          # test from Cb0 to B#8
78          for prefix, base_value in note_prefix.items():
79              for octave in range(9):
80                  note = prefix + str(octave)
81                  expected_value = base_value + octave * 12  # 12 semitones in octave
82                  self.assertEqual(note_parser(note), expected_value)
83  
84          # re-test with simple C4/A4 tests to catch any bugs in above
85          self.assertEqual(note_parser("C4"), 60)
86          self.assertEqual(note_parser("A4"), 69)
87  
88      def test_bad_text(self):
89  
90          for text_note in ["H", "H4", "asdfasdfasdf", "000", "999"]:
91              with self.assertRaises(ValueError):
92                  note_parser(text_note)
93  
94  
95  if __name__ == "__main__":
96      unittest.main(verbosity=verbose)