code: //=============================================================================
  //  MuseScore
  //  Music Composition & Notation
  //
  //  Copyright (C) 2012 Werner Schweer
  //
  //  This program is free software; you can redistribute it and/or modify
  //  it under the terms of the GNU General Public License version 2
  //  as published by the Free Software Foundation and appearing in
  //  the file LICENCE.GPL
  //=============================================================================
  
  #include <QtTest/QtTest>
  #include "mtest/testutils.h"
  #include "libmscore/score.h"
  #include "libmscore/undo.h"
  #include "libmscore/excerpt.h"
  #include "libmscore/part.h"
  #include "libmscore/measure.h"
  #include "libmscore/segment.h"
  #include "libmscore/chordrest.h"
  #include "libmscore/harmony.h"
  #include "libmscore/duration.h"
  #include "libmscore/durationtype.h"
  
  #define DIR QString("libmscore/chordsymbol/")
  
  using namespace Ms;
  
  //---------------------------------------------------------
  //   TestChordSymbol
  //---------------------------------------------------------
  
  class TestChordSymbol : public QObject, public MTest {
        Q_OBJECT
  
        MasterScore* test_pre(const char* p);
        void test_post(MasterScore* score, const char* p);
  
        void selectAllChordSymbols(MasterScore* score);
        void realizeSelectionVoiced(MasterScore* score, Voicing voicing);
  
     private slots:
        void initTestCase();
        void testExtend();
        void testClear();
        void testAddLink();
        void testAddPart();
        void testNoSystem();
        void testTranspose();
        void testTransposePart();
        void testRealizeClose();
        void testRealizeDrop2();
        void testRealize3Note();
        void testRealize4Note();
        void testRealize6Note();
        void testRealizeConcertPitch();
        void testRealizeTransposed();
        void testRealizeOverride();
        void testRealizeTriplet();
        void testRealizeDuration();
        void testRealizeJazz();
        };
  
  //---------------------------------------------------------
  //   initTestCase
  //---------------------------------------------------------
  
  void TestChordSymbol::initTestCase()
        {
        initMTest();
        }
  
  //---------------------------------------------------------
  //   chordsymbol
  //---------------------------------------------------------
  
  MasterScore* TestChordSymbol::test_pre(const char* p)
        {
        QString p1 = DIR + p + ".mscx";
        MasterScore* score = readScore(p1);
        score->doLayout();
        return score;
        }
  
  void TestChordSymbol::test_post(MasterScore* score, const char* p)
        {
        QString p1 = p;
        p1 += "-test.mscx";
        QString p2 = DIR + p + "-ref.mscx";
        QVERIFY(saveCompareScore(score, p1, p2));
        delete score;
        }
  
  //---------------------------------------------------------
  //   TestChordSymbol
  ///   select all chord symbols within the specified score
  //---------------------------------------------------------
  void TestChordSymbol::selectAllChordSymbols(MasterScore* score)
        {
        //find a chord symbol
        Segment* seg = score->firstSegment(SegmentType::ChordRest);
        Element* e = 0;
        while (seg) {
              e = seg->findAnnotation(ElementType::HARMONY,
                                                0, score->ntracks());
              if (e)
                    break;
              seg = seg->next1();
              }
        score->selectSimilar(e, false);
        }
  
  //---------------------------------------------------------
  //   realizeSelectionVoiced
  ///   realize the current selection of the score using
  ///   the specified voicing
  //---------------------------------------------------------
  void TestChordSymbol::realizeSelectionVoiced(MasterScore* score, Voicing voicing)
        {
        for (Element* e : score->selection().elements()) {
              if (e->isHarmony())
                    e->setProperty(Pid::HARMONY_VOICING, int(voicing));
              }
        score->startCmd();
        score->cmdRealizeChordSymbols();
        score->endCmd();
        }
  
  void TestChordSymbol::testExtend()
        {
        MasterScore* score = test_pre("extend");
        Measure* m = score->firstMeasure();
        Segment* s = m->first(SegmentType::ChordRest);
        ChordRest* cr = s->cr(0);
        score->changeCRlen(cr, TDuration::DurationType::V_WHOLE);
        score->doLayout();
        test_post(score, "extend");
        }
  
  void TestChordSymbol::testClear()
        {
        MasterScore* score = test_pre("clear");
        Measure* m = score->firstMeasure();
        score->select(m, SelectType::SINGLE, 0);
        score->cmdDeleteSelection();
        score->doLayout();
        test_post(score, "clear");
        }
  
  void TestChordSymbol::testAddLink()
        {
        MasterScore* score = test_pre("add-link");
        Segment* seg = score->firstSegment(SegmentType::ChordRest);
        ChordRest* cr = seg->cr(0);
        Harmony* harmony = new Harmony(score);
        harmony->setHarmony("C7");
        harmony->setTrack(cr->track());
        harmony->setParent(cr->segment());
        score->undoAddElement(harmony);
        score->doLayout();
        test_post(score, "add-link");
        }
  
  void TestChordSymbol::testAddPart()
        {
        MasterScore* score = test_pre("add-part");
        Segment* seg = score->firstSegment(SegmentType::ChordRest);
        ChordRest* cr = seg->cr(0);
        Harmony* harmony = new Harmony(score);
        harmony->setHarmony("C7");
        harmony->setTrack(cr->track());
        harmony->setParent(cr->segment());
        score->undoAddElement(harmony);
        score->doLayout();
        test_post(score, "add-part");
        }
  
  void TestChordSymbol::testNoSystem()
        {
        MasterScore* score = test_pre("no-system");
  
        //
        // create first part
        //
        QList<Part*> parts;
        parts.append(score->parts().at(0));
        Score* nscore = new Score(score);
  
        Excerpt* ex = new Excerpt(score);
        ex->setPartScore(nscore);
        nscore->setExcerpt(ex);
        score->excerpts().append(ex);
        ex->setTitle(parts.front()->longName());
        ex->setParts(parts);
        Excerpt::createExcerpt(ex);
        QVERIFY(nscore);
  
  //      nscore->setTitle(parts.front()->partName());
        nscore->style().set(Sid::createMultiMeasureRests, true);
  
        //
        // create second part
        //
        parts.clear();
        parts.append(score->parts().at(1));
        nscore = new Score(score);
  
        ex = new Excerpt(score);
        ex->setPartScore(nscore);
        nscore->setExcerpt(ex);
        score->excerpts().append(ex);
        ex->setTitle(parts.front()->longName());
        ex->setParts(parts);
        Excerpt::createExcerpt(ex);
        QVERIFY(nscore);
  
  //      nscore->setTitle(parts.front()->partName());
        nscore->style().set(Sid::createMultiMeasureRests, true);
  
        score->setExcerptsChanged(true);
        score->doLayout();
        test_post(score, "no-system");
        }
  
  void TestChordSymbol::testTranspose()
        {
        MasterScore* score = test_pre("transpose");
        score->startCmd();
        score->cmdSelectAll();
        score->transpose(TransposeMode::BY_INTERVAL, TransposeDirection::UP, Key::C, 4, false, true, true);
        score->endCmd();
        test_post(score, "transpose");
        }
  
  void TestChordSymbol::testTransposePart()
        {
        MasterScore* score = test_pre("transpose-part");
        score->startCmd();
        score->cmdSelectAll();
        score->transpose(TransposeMode::BY_INTERVAL, TransposeDirection::UP, Key::C, 4, false, true, true);
        score->endCmd();
        test_post(score, "transpose-part");
        }
  
  //---------------------------------------------------------
  //   testRealizeClose
  ///   check close voicing algorithm
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeClose()
        {
        MasterScore* score = test_pre("realize");
        selectAllChordSymbols(score);
        realizeSelectionVoiced(score, Voicing::CLOSE);
        test_post(score, "realize-close");
        }
  
  //---------------------------------------------------------
  //   testRealizeDrop2
  ///   check Drop 2 voicing algorithm
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeDrop2()
        {
        MasterScore* score = test_pre("realize");
        selectAllChordSymbols(score);
        realizeSelectionVoiced(score, Voicing::DROP_2);
        test_post(score, "realize-drop2");
        }
  
  //---------------------------------------------------------
  //   testRealize3Note
  ///   check 3 note voicing algorithm
  //---------------------------------------------------------
  void TestChordSymbol::testRealize3Note()
        {
        MasterScore* score = test_pre("realize");
        selectAllChordSymbols(score);
        realizeSelectionVoiced(score, Voicing::THREE_NOTE);
        test_post(score, "realize-3note");
        }
  
  //---------------------------------------------------------
  //   testRealize4Note
  ///   check 4 note voicing algorithm
  //---------------------------------------------------------
  void TestChordSymbol::testRealize4Note()
        {
        MasterScore* score = test_pre("realize");
        selectAllChordSymbols(score);
        realizeSelectionVoiced(score, Voicing::FOUR_NOTE);
        test_post(score, "realize-4note");
        }
  
  //---------------------------------------------------------
  //   testRealize6Note
  ///   check 6 note voicing algorithm
  //---------------------------------------------------------
  void TestChordSymbol::testRealize6Note()
        {
        MasterScore* score = test_pre("realize");
        selectAllChordSymbols(score);
        realizeSelectionVoiced(score, Voicing::SIX_NOTE);
        test_post(score, "realize-6note");
        }
  
  //---------------------------------------------------------
  //   testRealizeConcertPitch
  ///   Check if the note pitches and tpcs are correct after realizing
  ///   chord symbols on transposed instruments.
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeConcertPitch()
        {
        MasterScore* score = test_pre("realize-concert-pitch");
        //concert pitch off
        score->startCmd();
        score->cmdConcertPitchChanged(false, true);
        score->endCmd();
  
        //realize all chord symbols
        selectAllChordSymbols(score);
        score->startCmd();
        score->cmdRealizeChordSymbols();
        score->endCmd();
        test_post(score, "realize-concert-pitch");
        }
  
  //---------------------------------------------------------
  //   testRealizeTransposed
  ///   Check if the note pitches and tpcs are correct after
  ///   transposing the score
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeTransposed()
        {
        MasterScore* score = test_pre("transpose");
        //transpose
        score->cmdSelectAll();
        score->transpose(TransposeMode::BY_INTERVAL, TransposeDirection::UP, Key::C, 4, false, true, true);
  
        //realize all chord symbols
        selectAllChordSymbols(score);
        score->startCmd();
        score->cmdRealizeChordSymbols();
        score->endCmd();
        test_post(score, "realize-transpose");
        }
  
  //---------------------------------------------------------
  //   testRealizeOverride
  ///   Check for correctness when using the override
  ///   feature for realizing chord symbols
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeOverride()
        {
        MasterScore* score = test_pre("realize-override");
        //realize all chord symbols
        selectAllChordSymbols(score);
        score->startCmd();
        score->cmdRealizeChordSymbols(true, Voicing::ROOT_ONLY, HDuration::SEGMENT_DURATION);
        score->endCmd();
        test_post(score, "realize-override");
        }
  
  //---------------------------------------------------------
  //   testRealizeTriplet
  ///   Check for correctness when realizing chord symbols on triplets
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeTriplet()
        {
        MasterScore* score = test_pre("realize-triplet");
        //realize all chord symbols
        selectAllChordSymbols(score);
        score->startCmd();
        score->cmdRealizeChordSymbols();
        score->endCmd();
        test_post(score, "realize-triplet");
        }
  
  //---------------------------------------------------------
  //   testRealizeDuration
  ///   Check for correctness when realizing chord symbols
  ///   with different durations
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeDuration()
        {
        MasterScore* score = test_pre("realize-duration");
        //realize all chord symbols
        selectAllChordSymbols(score);
        score->startCmd();
        score->cmdRealizeChordSymbols();
        score->endCmd();
        test_post(score, "realize-duration");
        }
  
  //---------------------------------------------------------
  //   testRealizeJazz
  ///   Check for correctness when realizing chord symbols
  ///   with jazz mode
  //---------------------------------------------------------
  void TestChordSymbol::testRealizeJazz()
        {
        MasterScore* score = test_pre("realize-jazz");
        //realize all chord symbols
        selectAllChordSymbols(score);
        score->startCmd();
        score->cmdRealizeChordSymbols();
        score->endCmd();
        test_post(score, "realize-jazz");
        }
  
  
  QTEST_MAIN(TestChordSymbol)
  #include "tst_chordsymbol.moc"
  