test_lessonfile.py :  » Business-Application » GNU-Solfege » solfege-3.16.3 » solfege » tests » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Business Application » GNU Solfege 
GNU Solfege » solfege 3.16.3 » solfege » tests » test_lessonfile.py
# Solfege - free ear training software
# vim: set fileencoding=utf-8 :
# Copyright (C) 2007, 2008 Tom Cato Amundsen
# License is GPL, see file COPYING

from __future__ import absolute_import
import gtk
import unittest
import time

from solfege.testlib import I18nSetup
import solfege.lessonfile
solfege.lessonfile._test_mode = True
from solfege.lessonfile import *
from solfege import dataparser
from solfege import mpd
from solfege.mpd import mpdutils
from solfege import cfg

class TestParser(unittest.TestCase):
    def test_bad_musictype(self):
        s = 'question {\n' \
            'music = music("c e g", "chor")\n' \
            '}'
        p = LessonfileCommon()
        try:
            p.parse_string(s)
        except dataparser.WrongArgumentCount, e:
            self.assertEquals('(line 1): question {\n'
                              '(line 2): music = music("c e g", "chor")\n'
                              '                  ^',
                              e.m_nonwrapped_text)
    def test_gettext(self):
        s = 'question {\n' \
            '  name = _("chord|m7")\n' \
            '  iname = _i("chord|m7")\n' \
            '}'
        p = LessonfileCommon()
        p.parse_string(s)
        self.assertEquals(p.m_questions[0].name, "chord|m7")
        self.assertEquals(p.m_questions[0].name.cval, "chord|m7")
        self.assertEquals(p.m_questions[0].iname, "m7")
        self.assertEquals(p.m_questions[0].iname.cval, "chord|m7")

class LessonfileTestCase(unittest.TestCase):
    def _m(self, idx=0):
        return self.p.m_questions[idx]['music']

class TestMpdTransposable(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = "atonal", -5, 5 }
        question { music = chord("c e g") }
        """)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.p._idx = 0
    def test_get_musicdata_transposed(self):
        self.assertEquals("d fis a", self.p.m_questions[0]['music'].get_musicdata_transposed(self.p))
        self.p.header.random_transpose = ("key", -5, 6)
        # get_musicdata_transposed works for all transposition modes.
        self.assertEquals("d fis a", self.p.m_questions[0]['music'].get_musicdata_transposed(self.p))
        self.assertEquals("c e g", self.p.m_questions[0]['music'].m_musicdata)

class TestChord(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = chord("c e g") }
        """)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.p._idx = 0
    def get_get_mpd_music_string(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_mpd_music_string(self.p),
            r"\staff{ <c e g> }")
        self.p.header.random_transpose = (True,)
        self.assertEquals(self.p.m_questions[0]['music'].get_mpd_music_string(self.p),
            r"\staff\transpose d'{ <c e g> }")
    def test_get_music_as_notename_list(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_music_as_notename_list(self.p), ['c', 'e', 'g'])
        self.p.header.random_transpose = (True,)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.assertEquals(self.p.m_questions[0]['music'].get_music_as_notename_list(self.p), ['d', 'fis', 'a'])
    def test_get_lilypond_code(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code(self.p), "\\score{  \\transpose c' d'{ <c e g> } \\layout {   ragged-last = ##t   \\context { \\Staff \\remove \"Time_signature_engraver\" }  }}")
        self.p.header.random_transpose = ('atonal', -5, 5)
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code(self.p), "\\score{    { <d fis a> } \\layout {   ragged-last = ##t   \\context { \\Staff \\remove \"Time_signature_engraver\" }  }}")
    def test_get_lilypond_code_first_note(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code_first_note(self.p), r"\transpose c' d'{ c }")
        self.p.header.random_transpose = ('atonal', -5, 5)
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code_first_note(self.p), r"{ d }")
    def test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 p0:0 v0:100 n48 n52 n55 d1/4 o48 o52 o55")
    def test_3patch_play(self):
        cfg.set_bool('config/override_default_instrument', True)
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:1 v0:121 n0:48 p1:2 v1:122 n1:52 p2:3 v2:123 n2:55 d1/4 o48 o52 o55")
    def test_play_arpeggio(self):
        question = self.p.m_questions[0]
        question['music'].play_arpeggio(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t180/4 p0:0 v0:100 n48 d1/4 o48 n52 d1/4 o52 n55 d1/4 o55")
        self.p.header.random_transpose = (True,)
        question['music'].play_arpeggio(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t180/4 p0:0 v0:100 n50 d1/4 o50 n54 d1/4 o54 n57 d1/4 o57")
        cfg.set_bool('config/override_default_instrument', True)
        question['music'].play_arpeggio(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t180/4 p0:1 v0:121 n50 d1/4 o50 p0:2 v0:122 n54 d1/4 o54 p0:3 v0:123 n57 d1/4 o57")
    def test_atonal_transpose(self):
        self.p.header.random_transpose = ('atonal', -4, 4)
        self.assertEquals(self.p.m_questions[0]['music'].get_musicdata_transposed(self.p), "d fis a")
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("es'")
        self.assertEquals(self.p.m_questions[0]['music'].get_musicdata_transposed(self.p), "ees g bes")

class TestMusic(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = music("\staff{c''}\staff{e'}\staff{c}") }
        question { 
            instrument = 33, 34, 35, 36, 37, 38
            music = music("\staff{c''}\staff{e'}\staff{c}")
        }
        question { 
            instrument = 33, 34, 35, 36, 37, 38
            music = music("\staff{c''}\staff{b'}")
        }
        question { 
            instrument = 33, 34, 35, 36, 37, 38
            music = music("\staff{c''}")
        }
        """)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.p._idx = 0
    def test_too_many_instruments_play(self):
        # If the question has two tracks, and the instrument variable
        # has more instruments, then only the first and last instrument
        # is used
        question = self.p.m_questions[2]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:37 v0:38 n0:72 p1:33 v1:34 n1:71 d1/4 o72 o71")
        # If the question has only one track, the last instrument,
        # representing the highest instrument, is used.
        question = self.p.m_questions[3]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:37 v0:38 n0:72 d1/4 o72")
    def test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:0 v0:100 n0:72 n0:64 n0:48 d1/4 o72 o64 o48")
        # Music objects should ignore config/override_default_instrument
        cfg.set_bool('config/override_default_instrument', True)
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:0 v0:100 n0:72 n0:64 n0:48 d1/4 o72 o64 o48")
        #
        question = self.p.m_questions[1]
        # If the instrument variable it set, and it has more than one
        # instrument, as it as in questions[1], then even Music will
        # play with more than one instrument.:w
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:37 v0:38 n0:72 p1:35 v1:36 n1:64 p2:33 v2:34 n2:48 d1/4 o72 o64 o48")
    def test_play_slowly(self):
        question = self.p.m_questions[0]
        #test.py TestMusic viser at det ikke blir generert riktig instrument
        #for ovelser som progressions-2 (harmonicprogressiondictation)
        question['music'].play_slowly(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t30/4 p0:0 v0:100 n0:72 n0:64 n0:48 d1/4 o72 o64 o48")
        cfg.set_bool('config/override_default_instrument', True)
        question['music'].play_slowly(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t30/4 p0:0 v0:100 n0:72 n0:64 n0:48 d1/4 o72 o64 o48")

class TestMusic3(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = music3("\staff{c''}\staff{e'}\staff{c}") }
        question {
            instrument = 33, 34, 35, 36, 37, 38
            music = music3("\staff{c''}\staff{g'}\staff{e'}\staff{c}")
        }
        """)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.p._idx = 0
    def test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:0 v0:100 n0:72 n0:64 n0:48 d1/4 o72 o64 o48")
        #
        cfg.set_bool('config/override_default_instrument', True)
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:3 v0:123 n0:72 p1:2 v1:122 n1:64 p2:1 v2:121 n2:48 d1/4 o72 o64 o48")
        #
        question = self.p.m_questions[1]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(1),
            "t60/4 p0:37 v0:38 n0:72 p1:35 v1:36 n1:67 n1:64 p2:33 v2:34 n2:48 d1/4 o72 o67 o64 o48")

class TestVoiceCommon(unittest.TestCase):
    def test_get_first_pitch(self):
        for s, n in (
            ("c d e", "c"),
            ("<c'' e>", "c''"),
            ("< c'' e>", "c''"),
            (" c,,16", "c,,"),
            (" \n c d e", "c"),
            (r"\clef bass c d e", "c"),
            (r"\clef violin \time 3/8 fis", "fis"),
            (r'\clef "violin_8" d', "d"),
            ("\\key g \\major \\time 2/4\n d'8 | [g g]", "d'"),
            ("\nc", "c"),
            ):
            x = Rvoice(s)
            self.assertEquals(x.get_first_pitch().get_octave_notename(), n)
        self.assertRaises(MusicObjectException, lambda: Rvoice("\\clef bass").get_first_pitch())


class TestVoice(LessonfileTestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = voice("c d e") }
        question { music = voice("< e") }
        """)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.p._idx = 0
    def test_get_mpd_music_string(self):
        self.assertEquals(self._m().get_mpd_music_string(self.p),
                          "\\staff{\nc d e\n}")
        self.p.header.random_transpose = [True]
        self.assertEquals(self._m().get_mpd_music_string(self.p),
                          "\\staff\\transpose d'{\nc d e\n}")
        self.p.header.random_transpose = ['atonal', -5, 6]
        self.assertEquals(self._m().get_mpd_music_string(self.p),
                          "\\staff{\nd e fis\n}")
    def test_get_lilypond_code(self):
        self.assertEquals(self._m().get_lilypond_code(self.p),
                          r"{ c d e }")
        self.p.header.random_transpose = [True]
        self.assertEquals(self._m().get_lilypond_code(self.p),
                          r"\transpose c' d'{ c d e }")
        self.p.header.random_transpose = "atonal", -5, 6
        self.assertEquals(self._m().get_lilypond_code(self.p),
                          r"{ d e fis }")
    def test_get_lilypond_code_first_note(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code_first_note(self.p), r"\score{ \new Staff<< \new Voice{ \cadenzaOn c } \new Voice{ \hideNotes c d e } >> \layout { ragged-last = ##t } }")
        self.p.header.random_transpose = [True]
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code_first_note(self.p), ur"\score{ \new Staff<< \new Voice\transpose c' d'{ \cadenzaOn c } \new Voice{ \hideNotes c d e } >> \layout { ragged-last = ##t } }")
        self.p.header.random_transpose = "atonal", -5, 6
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code_first_note(self.p), r"\score{ \new Staff<< \new Voice{ \cadenzaOn d } \new Voice{ \hideNotes c d e } >> \layout { ragged-last = ##t } }")
    def _test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 p0:0 v0:100 n48 d1/4 o48 n50 d1/4 o50 n52 d1/4 o52")
    def test_play(self):
        self._test_play()
    def test_3patch_play(self):
        """
        voice music objects ignore config/override_default_instrument
        by design.
        """
        question = self.p.m_questions[0]
        self._test_play()
    def test_play_slowly(self):
        question = self.p.m_questions[0]
        question['music'].play_slowly(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t30/4 p0:0 v0:100 n48 d1/4 o48 n50 d1/4 o50 n52 d1/4 o52")
    def test_findfirst(self):
        for p1, p2, s, n in (
            (0, 1, "c d e", "c"),
            (1, 4, "<c'' e>", "c''"),
            (2, 5, "< c'' e>", "c''"),
            (2, 5, "\n\nERR", "ERR"),
            (1, 4, " c,,16", "c,,"),
            (3, 4, " \n c d e", "c"),
            (11, 12, r"\clef bass c d e", "c"),
            (23, 26, r"\clef violin \time 3/8 fis", "fis"),
            (17, 18, r'\clef "violin_8" d', "d"),
            (25, 27, "\\key g \\major \\time 2/4\n d'8 | [g g]", "d'"),
            (1, 2, "\nc", "c"),
            ):
            x = Rvoice(s)
            self.assertEquals((p1, p2), mpdutils.find_possible_first_note(x.m_musicdata), "String failed: %s: %s" % (s, mpdutils.find_possible_first_note(x.m_musicdata)))
            self.assertEquals(s[p1:p2], n)
    def test_error_handling(self):
        m = self._m(1).get_mpd_music_string(self.p)
        try:
            mpd.parser.parse_to_score_object(m)
        except mpd.MpdException, e:
            self._m(1).complete_to_musicdata_coords(self.p, e)
            ec = self._m(1).get_err_context(e, self.p)
            self.assertEquals(ec, 
              "Bad input to the music object of type voice made\n"
              "the parser fail to parse the following generated\n"
              "music code:\n"
              "\\staff{\n"
              "< e\n"
              "}\n"
              "^")

        else:
            self.fail("Test failed. No exception raised.")
        return
        try:
            m = self._m(5).get_mpd_music_string(self.p)
        except mpd.MpdException, e:
            # We can not call complete_to_musicdata_coords becuase
            # get_mpd_music_string promises to always raise exceptions
            # relative to musicdata.
            self.assertEquals(self._m(5).get_err_context(e, self.p),
                "ERR f\n^^^")
        else:
            self.fail("Test failed. No exception raised.")
        self.p.header.random_transpose = ('atonal', -4, 4)
        try:
            m = self._m(5).get_mpd_music_string(self.p)
        except mpd.MpdException, e:
            self.assertEquals(self._m(5).get_err_context(e, self.p),
                "ERR f\n^^^")
        else:
            self.fail("Test failed. No exception raised.")

class TestErrorHandling(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
    def _dotest(self, musictypes, bad_code):
        for t in musictypes:
            for code, err_context in bad_code:
                self.p = QuestionsLessonfile()
                self.p.parse_string('''
                header { random_transpose = no }
                question { music = %s("%s") }
                ''' % (t, code))
                self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
                self.p._idx = 0
                question = self.p.m_questions[0]
                try:
                    self.p.play_question(question)
                except MusicObjectException, e:
                    self.assertEquals(err_context, str(e))
                except mpd.MpdException, e:
                    ec = question.music.get_err_context(e, self.p)
                    self.assertEquals(err_context, ec, "Music failed with musictype %s:\n%s !=\n%s" % (t, err_context, ec))
                else:
                    assert False, "No error found in code %s" % code
    def test_1(self):
        cfg.set_bool('config/override_default_instrument', False)
        self._test_1()
    def test_1_3patches(self):
        """
        Test with 3 different patches, just in case implementation details
        make error handling different with config/override_default_instrument
        set and unset.
        """
        cfg.set_bool('config/override_default_instrument', True)
        self._test_1()
    def _test_1(self):
        self._dotest(("chord", "voice", "rhythm", "percussion", "rhythm"),
                   (("c d e ERR f",
                     "c d e ERR f\n"
                     "      ^^^"),
                    ("c d e f\ng ERR a",
                    "g ERR a\n"
                     "  ^^^"),
                    ("c d XX e f\ng ERR a",
                     "c d XX e f\n"
                     "    ^^"),
                    ("ERR",
                     "ERR\n"
                     "^^^"),
                  ))
    def test_satb(self):
        self._test_satb()
    def test_satb_3patches(self):
        cfg.set_bool('config/override_default_instrument', True)
        self._test_satb()
    def _test_satb(self):
        self._dotest(("satb",),
            (("c'' | ERR | g | c",
              "c'' | ERR | g | c\n"
              "     ^^^^^"),
             ("c''|g'|ERR| c",
              "c''|g'|ERR| c\n"
              "       ^^^"),
             ("c'' |e' d'|\n ERR |c",
              "The music code from the lesson file has been modified by\n"
              "removing the new-line characters. This to more easily show\n"
              "where the error occured. Satb music should not contain music\n"
              "characters.\n"
              "c'' |e' d'| ERR |c\n"
              "           ^^^^^"),
             ("|||",
              "Satb music does not allow an empty voice"),
             ("{ | g",
              "Satb music should be divided into 4 parts by the '|' character",),
              ))
    def test_music(self):
        self._dotest(("music",),
            (("\\staff{ c' d ERR e }",
              "\\staff{ c' d ERR e }\n"
              "             ^^^"),
             ("\\staff{ c4. c. }",
              "\\staff{ c4. c. }\n"
              "            ^^"),
             ("\\addvoice{ jojo ",
              "\\addvoice{ jojo \n"
              "^^^^^^^^^"),
             ("\\staff { c4 c4. c. }",
              "\\staff { c4 c4. c. }\n"
              "                ^^"),
             ("\\staff { c4\n"
              "ERR }",
              "ERR }\n"
              "^^^"),
             ("\\staff{ \\clef ERROR c",
              "\\staff{ \\clef ERROR c\n"
                "        ^^^^^^^^^^^"),
            ))


class TestRvoice(LessonfileTestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = rvoice("c' d b c") }
        question { music = rvoice("[c'8 d] e16") }
        question { music = rvoice("c,, d' b c") }
        question { music = rvoice("b,, d' b c") }
        question { music = rvoice("< e") }
        question { music = rvoice("ERR") }
        question { music = rvoice("c d e f\ng ERR a") }
        """)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.p._idx = 0
    def test_get_mpd_music_string(self):
        self.assertEquals(self._m().get_mpd_music_string(self.p),
            "\\staff\\relative c'{\nc d b c\n}")
        self.p.header.random_transpose = (True,)
        self.assertEquals(self._m().get_mpd_music_string(self.p),
            "\\staff\\transpose d'\\relative c'{ c d b c }")
        self.p.header.random_transpose = ['atonal', -5, 6]
        self.assertEquals(self._m().get_mpd_music_string(self.p),
            "\\staff\\relative d'{\nd e cis d\n}")
        self.assertEquals(self._m(1).get_mpd_music_string(self.p),
            "\\staff\\relative d'{\n[ d8 e ] fis16\n}")
        self.assertEquals(self._m(2).get_mpd_music_string(self.p),
            "\\staff\\relative d,,{\nd e' cis d\n}")
        self.assertEquals(self._m(3).get_mpd_music_string(self.p),
            "\\staff\\relative cis,{\ncis e' cis d\n}")
    def _test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 p0:0 v0:100 n60 d1/4 o60 n62 d1/4 o62 n59 d1/4 o59 n60 d1/4 o60")
    def test_play(self):
        self._test_play()
    def test_3patch_play(self):
        """
        rvoice music objects ignore config/override_default_instrument
        by design.
        """
        question = self.p.m_questions[0]
        self._test_play()
    def test_play_slowly(self):
        question = self.p.m_questions[0]
        question['music'].play_slowly(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t30/4 p0:0 v0:100 n60 d1/4 o60 n62 d1/4 o62 n59 d1/4 o59 n60 d1/4 o60")
    def test_get_lilypond_code(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code(self.p), r"\transpose c' d'\relative c{ c' d b c }")
    def test_get_lilypond_code_first_note(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_lilypond_code_first_note(self.p), r"\score{ \new Staff<< \new Voice\transpose c' d'\relative c{ \cadenzaOn c' } \new Voice{ \hideNotes c' d b c } >> \layout { ragged-last = ##t } }")
    def test_bad_first_note(self):
        self.p.header.random_transpose = (True, 0, 0)
        m = self._m(4).get_mpd_music_string(self.p)
        try:
            mpd.parser.parse_to_score_object(m)
        except mpd.parser.ParseError, e:
            self.assertEquals(self._m(4).get_err_context(e, self.p),
                "Bad input to the music object of type rvoice made\n"
                "the parser fail to parse the following generated\n"
                "music code:\n"
                "\\staff\\transpose d'\\relative e{ < e }\n"
                "                                    ^")
        else:
            self.fail("Test failed. No exception raised.")
        m = self._m(5).get_mpd_music_string(self.p)
        try:
            mpd.parser.parse_to_score_object(m)
        except mpd.InvalidNotenameException, e:
            self.assertEquals(self._m(5).get_err_context(e, self.p),
                "Bad input to the music object of type rvoice made\n"
                "the parser fail to parse the following generated\n"
                "music code:\n"
                "\\staff\\transpose d'\\relative ERR{ ERR }\n"
                "                   ^^^^^^^^^^^^^")
        else:
            self.fail("Test failed. No exception raised.")
        m = self._m(6).get_mpd_music_string(self.p)
        try:
            mpd.parser.parse_to_score_object(m)
        except mpd.InvalidNotenameException, e:
            self.assertEquals(self._m(6).get_err_context(e, self.p),
                "Bad input to the music object of type rvoice made\n"
                "the parser fail to parse the following generated\n"
                "music code:\n"
                "\\staff\\transpose d'\\relative c{ c d e f\n"
                "g ERR a }\n"
                "  ^^^")

class TestSatb(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { random_transpose = no }
        question { music = satb("c''| e'| g | c") }
        question { key = "aes \\major" music = satb("c''|as'|es'|as") }
        question { music = satb("c''| g' e'| g | c") }
        """)
        self.p.m_transpose = mpd.MusicalPitch.new_from_notename("d'")
        self.p._idx = 0
    def test_get_mpd_music_string(self):
        self.assertEquals(self.p.m_questions[0]['music'].get_mpd_music_string(self.p),
            "\\staff{ \\key c \\major\\stemUp <c''> }\n" \
            "\\addvoice{ \\stemDown <e'> }\n" \
            "\\staff{ \\key c \\major\\clef bass \\stemUp <g>}\n" \
            "\\addvoice{ \\stemDown <c>}")
        # FIXME Satb only works if the music object is the current selected
        # question. Can we get around this?
        self.p._idx  = 1
        self.assertEquals(self.p.m_questions[1]['music'].get_mpd_music_string(self.p),
            "\\staff{ \\key aes \\major\\stemUp <c''> }\n" \
            "\\addvoice{ \\stemDown <as'> }\n" \
            "\\staff{ \\key aes \\major\\clef bass \\stemUp <es'>}\n" \
            "\\addvoice{ \\stemDown <as>}")
    def test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 p0:0 v0:100 n72 n64 n55 n48 d1/4 o72 o64 o55 o48")
    def test_play_arpeggio(self):
        question = self.p.m_questions[0]
        question['music'].play_arpeggio(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 p0:0 v0:100 n60 d1/4 o60 n52 d1/4 o52 n55 d1/4 o55 n48 d1/4 o48")
        question = self.p.m_questions[2]
        question['music'].play_arpeggio(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 p0:0 v0:100 n60 d1/4 o60 n55 d1/4 o55 n52 d1/4 o52 n55 d1/4 o55 n48 d1/4 o48")
        # Then with transposition
        self.p.header.random_transpose = (True,)
        question['music'].play_arpeggio(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 p0:0 v0:100 n62 d1/4 o62 n57 d1/4 o57 n54 d1/4 o54 n57 d1/4 o57 n50 d1/4 o50")

class TestRhythm(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        question { music = rhythm("d c8") }
        question { music = rhythm("c \time 3\4 c d") }
        """)
        self.p._idx = 0
    def test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 v9:100 P80 d1/4 o80 P37 d1/8 o37")
    def test_bad_time(self):
        question = self.p.m_questions[1]
        question.music.get_mpd_music_string(self.p)

class TestPercussion(unittest.TestCase):
    def setUp(self):
        cfg.set_bool('config/override_default_instrument', False)
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        question { music = percussion("e16 f g4") }
        """)
        self.p._idx = 0
    def test_play(self):
        question = self.p.m_questions[0]
        question['music'].play(self.p, question)
        self.assertEquals(soundcard.synth.flush_testdata(),
            "t60/4 v9:100 P52 d1/16 o52 P53 d1/16 o53 P55 d1/4 o55")


class TestWavfile(unittest.TestCase):
    def setUp(self):
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        question { music = wavfile("exercises/standard/lesson-files/share/fifth-small-293.33.wav") }
        """)
        self.p._idx = 0
    def test_play(self):
        question = self.p.m_questions[0]
        if cfg.get_bool('testing/may_play_sound'):
            question['music'].play(self.p, question)
            time.sleep(3)
    def test_get_mpd_music_string(self):
        question = self.p.m_questions[0]
        self.assertEquals(question['music'].get_mpd_music_string(self.p),
                          "Wavfile:exercises/standard/lesson-files/share/fifth-small-293.33.wav")
        self.assertEquals(question.music.m_musicdata,
                          "exercises/standard/lesson-files/share/fifth-small-293.33.wav")
        self.assertTrue(isinstance(question.music, Wavfile))

class TestMidifile(unittest.TestCase):
    def setUp(self):
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        question { music = midifile("exercises/standard/lesson-files/share/fanfare.midi") }
        """)
        self.p._idx = 0
    def test_play(self):
        question = self.p.m_questions[0]
        if cfg.get_bool('testing/may_play_sound'):
            question['music'].play(self.p, question)
            time.sleep(3)
    def test_get_mpd_music_string(self):
        question = self.p.m_questions[0]
        self.assertEquals(question['music'].get_mpd_music_string(self.p),
                          "Midifile:exercises/standard/lesson-files/share/fanfare.midi")
        self.assertEquals(question.music.m_musicdata,
                          "exercises/standard/lesson-files/share/fanfare.midi")
        self.assertTrue(isinstance(question.music, Midifile))


class TestCmdline(unittest.TestCase):
    def setUp(self):
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        question { music = cmdline("/usr/bin/play exercises/standard/lesson-files/share/fifth-pure-220.00.wav") }
        """)
        self.p._idx = 0
    def test_play(self):
        question = self.p.m_questions[0]
        if cfg.get_bool('testing/may_play_sound'):
            question['music'].play(self.p, question)
            time.sleep(3)

class TestCSound(unittest.TestCase):
    def test_CSound(self):
        self.p = QuestionsLessonfile()
        self.p.parse_string('''
header {
    lesson_id = "csound-intonation-M3-5cent"
    module = idbyname
    help = "idbyname-intonation"
    title = "Test "
}

question {
 name = "III temperature"
 set=0
 csound_sco = """
f1     0    4096 10   1  ; use GEN10 to compute a sine wave
; p1  p2    p3  p4     p5    p6     p7
;ins  strt  dur amp    freq  attack release
  i1  0     1   10000  440   0.2    0.08
  i1  +     1   10000  660   0.08    0.08
e
 """
 music = csound(load("exercises/standard/lesson-files/share/sinus-ad.orc"), csound_sco)
}''')
        question = self.p.m_questions[0]
        if cfg.get_bool('testing/may_play_sound'):
            question['music'].play(self.p, question)


class TestMma(unittest.TestCase):
    def test_1arg(self):
        s = """
        question {
            music = mma("1 Cmaj7")
        }
        """
        p = QuestionsLessonfile()
        p.parse_string(s)
        q = p.m_questions[0]
        if cfg.get_bool('testing/may_play_sound'):
            q['music'].play(p, q)
    def test_2arg(self):
        s = """
        question {
            music = mma("ballad", "1 Cmaj7")
        }
        """
        p = QuestionsLessonfile()
        p.parse_string(s)
        q = p.m_questions[0]
        if cfg.get_bool('testing/may_play_sound'):
            q['music'].play(p, q)


class TestLessonfileHeader(I18nSetup):
    def test_untranslated_variable(self):
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header { untranslated = "jojo"
           translated = _("major")
        }
        question { } #dummy question to avoid NoQuestionsInFileException
        """)
        self.assertEquals(self.p.header['untranslated'], u"jojo")
        self.assertEquals(self.p.header['untranslated'].cval, u"jojo")
        self.assertEquals(self.p.header['translated'], u"dur")
        self.assertEquals(self.p.header['translated'].cval, u"major")
        self.assertEquals(self.p.header.untranslated, u"jojo")
        self.assertEquals(self.p.header.untranslated.cval, u"jojo")
        self.assertEquals(self.p.header.translated, u"dur")
        self.assertEquals(self.p.header.translated.cval, u"major")
    def test_infile_translations_discard(self):
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        header {
           title = "C-locale header"
           title[et] = "et-locale header"
        }
        question { } #dummy question to avoid NoQuestionsInFileException
        """)
        # This test is run with LANGUAGE='no', so the 'et' translation
        # is discarded
        self.assertEquals(self.p.header.title, "C-locale header")
        self.assertEquals(self.p.header.title.cval, "C-locale header")

class TestLessonfileQuestion(I18nSetup):
    def test_question_name(self):
        self.p = QuestionsLessonfile()
        self.p.parse_string("""
        question { name = "untranslated" }
        question { name = _("major") }
        question { # question has no name
        }
        """)
        self.assertEquals(self.p.m_questions[0].name, u"untranslated")
        self.assertEquals(self.p.m_questions[0].name.cval, u"untranslated")
        self.assertEquals(self.p.m_questions[1].name, u"dur")
        self.assertEquals(self.p.m_questions[1].name.cval, u"major")
        self.assertRaises(AttributeError, lambda : self.p.m_questions[2].name)
    def test_setattr(self):
        q = dataparser.Question()
        q.var = 1
        self.assertEquals(q.var, 1)
        self.assertEquals(q['var'], 1)

class TestLessonfileMisc(unittest.TestCase):
    def test_eq(self):
        c = Chord("a b c")
        d = Rvoice("a b c")
        e = Rvoice("a b c")
        f = Rvoice("c c c")
        self.assertNotEquals(c, d)
        self.assertNotEquals(d, e)
        self.assertNotEquals(d, f)
    def test_IdPropertyLessonfileFilter(self):
        s = """header {
                qprops = "name", "inversion"
                qprop_labels = _("Name"), _("Inversion")
            }
            question { name = "one" }
            question { name = "two" inversion=2 }
            """
        p = IdPropertyLessonfile()
        p.parse_string(s)
        # One question should be discarded because it does not have
        # the inversion variable
        self.assertEquals(len(p.m_discards), 1)
        self.assertEquals(len(p.m_questions), 1)
    def test_IdPropertyLessonfileFilter2(self):
        s = 'header { qprops = "name", "inversion" qprop_labels = "Name", "Inversion" }\n' \
            'question { name = "one" inversion=1} \n' \
            'question { name = "two" inversion=2 top=0 } '
        p = IdPropertyLessonfile()
        p.parse_string(s)
        # No questions are discaded.
        # top is not a property since it is not added to qprops, so
        # thats why the first question is not discarded.
        self.assertEquals(len(p.m_discards), 0)
        self.assertEquals(len(p.m_questions), 2)
    def test_IdPropertyLessonfile_qprops(self):
        s = 'header { qprops = "name", "inversion", "toptone" qprop_labels = "Name", "Inversion", "Toptone" }\n' \
            'question { name = "one" inversion=1} \n' \
            'question { name = "two" inversion=2 top=0 } '
        p = IdPropertyLessonfile()
        p.parse_string(s)
        # No questions are discarded, since they both contain the same
        # two properties, of the tree listed in qprops. The 'top' variable
        # in the second question does not affect what is or is not discarded
        # because is it not a property (not defined in qprops)
        self.assertEquals(len(p.m_questions), 2)
    def test_ChordLessonfileFilter(self):
        s = """header { }
            question { name = "one" }
            question { name = "two" inversion=2 }
            """
        p = ChordLessonfile()
        p.parse_string(s)
        # One question should be discarded because it does not have
        # the inversion variable
        self.assertEquals(len(p.m_questions), 1)
    def test_ChordLessonfileFilter2(self):
        s = 'header { qprops = "name", "inversion" qprop_labels = "Name", "Inversion" }\n' \
            'question { name = "one" inversion=1} \n' \
            'question { name = "two" inversion=2 top=0 } '
        p = ChordLessonfile()
        p.parse_string(s)
        # No questions are discaded.
        # top is not a property since it is not added to qprops, so
        # thats why the first question is not discarded.
        self.assertEquals(len(p.m_questions), 2)
    def test_IdProperty(self):
        """
        Once, a single item qprops did not work.
        """
        s = 'header { qprops = "name" qprop_labels = "NAME" } ' \
            'question { name = "major" music = chord("c e g") } '
        p = IdPropertyLessonfile()
        p.parse_string(s)
        self.assertEquals(p.header.qprops, [u'name'])
    def test_nrandom(self):
        self._worker_Xrandom("nrandom")
    def test_prandom(self):
        self._worker_Xrandom("prandom")
    def _worker_Xrandom(self, rfunc):
        styles = ["8beat", "ballad", "rock"]
        s = """
        styles = %s
        question {
            style = %s("8beat", "ballad")
        }
        question {
            style = %s(styles)
        }
        """ % (", ".join(['"%s"' % x for x in styles]), rfunc, rfunc)
        p = QuestionsLessonfile()
        p.parse_string(s)
        for idx in range(2):
            st = p.m_questions[idx]['style']
            for x in range(20):
                self.assert_(str(st) in styles)
                self.assert_(unicode(st) in styles)
                st.randomize()
            # This test only works with nrandom, because prandom will
            # return a possible different value every time.
            if rfunc == 'nrandom':
                l = gtk.Label(st)
                self.assert_(l.get_text() == unicode(st), "%s and gtk does not cooperate." % rfunc)

class TestLabelObject(unittest.TestCase):
    def test_construct(self):
        l = LabelObject("pangomarkup", "abc")
        self.assertEquals(l.cval, ("pangomarkup", "abc"))
    def test_rn_markup(self):
        for s, v in (
            ("Imaj7-", [('I', 'maj', '7', '-')]),
            ("bIIIm7 -", [('bIII', 'm', '7', ' -')]),
            ("Imaj7-IIm7-V9-Imaj7", [('I', 'maj', '7', '-'),
                                     ('II', 'm', '7', '-'),
                                     ('V', '', '9', '-'),
                                     ('I', 'maj', '7', '')]),
            ("Imaj7", [('I', 'maj', '7', '')]),
            ("iim9b5+13", [('ii', 'm', '9b5+13', '')]),
            ("Imaj7-V7", [('I', 'maj', '7', '-'), ('V', '', '7', '')]),
            ("Imaj7  -IIm9", [('I', 'maj', '7', '  -'), ('II', 'm', '9', '')]),
                ):
            self.assertEquals(rnc_markup_tokenizer(s), v, (rnc_markup_tokenizer(s), v))

    def test_chordname_markup(self):
        for s, v in (
            ("cis4", [('cis', '4', '', '')]),
            ('gmaj7', [('g', 'maj7', '', '')]),
            ('gesmaj7:9b5', [('ges', 'maj7', '9b5', '')]),
            ('g/g', [('g', '', '', 'g')]),
            ('g', [('g', '', '', '')]),
            ('gm', [('g', 'm', '', '')]),
            ('g:7', [('g', '', '7', '')]),
            ('gm:7', [('g', 'm', '7', '')]),
            ('d/fis', [('d', '', '', 'fis')]),
            ('gm/f', [('g', 'm', '', 'f')]),
            ('gm:7/d', [('g', 'm', '7', 'd')]),
            ('gm:13/5-/d', [('g', 'm', '13/5-', 'd')]),
            ):
            self.assertEquals(chordname_markup_tokenizer(s), v)


suite = unittest.makeSuite(TestParser)
suite.addTest(unittest.makeSuite(TestMpdTransposable))
suite.addTest(unittest.makeSuite(TestChord))
suite.addTest(unittest.makeSuite(TestMusic))
suite.addTest(unittest.makeSuite(TestMusic3))
suite.addTest(unittest.makeSuite(TestVoiceCommon))
suite.addTest(unittest.makeSuite(TestVoice))
suite.addTest(unittest.makeSuite(TestRvoice))
suite.addTest(unittest.makeSuite(TestSatb))
suite.addTest(unittest.makeSuite(TestRhythm))
suite.addTest(unittest.makeSuite(TestPercussion))
suite.addTest(unittest.makeSuite(TestWavfile))
suite.addTest(unittest.makeSuite(TestMidifile))
suite.addTest(unittest.makeSuite(TestCmdline))
suite.addTest(unittest.makeSuite(TestCSound))
suite.addTest(unittest.makeSuite(TestMma))
suite.addTest(unittest.makeSuite(TestLessonfileHeader))
suite.addTest(unittest.makeSuite(TestLessonfileQuestion))
suite.addTest(unittest.makeSuite(TestLessonfileMisc))
suite.addTest(unittest.makeSuite(TestErrorHandling))
suite.addTest(unittest.makeSuite(TestLabelObject))
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.