Skip to content

Commit

Permalink
Add test for tree model consistency & make it pass
Browse files Browse the repository at this point in the history
  • Loading branch information
krkartikay committed Jun 22, 2020
1 parent 48d860c commit 0990831
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 8 deletions.
5 changes: 5 additions & 0 deletions libmscore/accidental.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ class Accidental final : public Element
Accidental* clone() const override { return new Accidental(*this); }
ElementType type() const override { return ElementType::ACCIDENTAL; }

// Score Tree functions
ScoreElement* treeParent() const override;
ScoreElement* treeChild(int idx) const override;
int treeChildCount() const override;

QString subtypeUserName() const;
void setSubtype(const QString& s);
void setAccidentalType(AccidentalType t) { _accidentalType = t; }
Expand Down
47 changes: 39 additions & 8 deletions libmscore/scoretree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,11 @@ int Segment::treeChildCount() const

ScoreElement* ChordRest::treeParent() const
{
if (isGrace()) {
// grace notes do not have a segment of their own
// their parent is the chord they are attached to
return parent();
}
return segment();
}

Expand Down Expand Up @@ -400,7 +405,7 @@ int ChordRest::treeChildCount() const

ScoreElement* Chord::treeParent() const
{
return segment();
return ChordRest::treeParent();
}

ScoreElement* Chord::treeChild(int idx) const
Expand Down Expand Up @@ -498,7 +503,7 @@ int Chord::treeChildCount() const

ScoreElement* Rest::treeParent() const
{
return segment();
return ChordRest::treeParent();
}

ScoreElement* Rest::treeChild(int idx) const
Expand Down Expand Up @@ -570,6 +575,29 @@ int Note::treeChildCount() const
return numChildren;
}

//---------------------------------------------------------
// Accidental
//---------------------------------------------------------

ScoreElement* Accidental::treeParent() const
{
if (parent()->isTrillSegment()) {
return parent()->treeParent();
}
return note();
}

ScoreElement* Accidental::treeChild(int idx) const
{
Q_UNUSED(idx);
return nullptr;
}

int Accidental::treeChildCount() const
{
return 0;
}

//---------------------------------------------------------
// Beam
//---------------------------------------------------------
Expand Down Expand Up @@ -783,24 +811,27 @@ int BarLine::treeChildCount() const

ScoreElement* Trill::treeParent() const
{
return segment();
return Spanner::treeParent();
}

ScoreElement* Trill::treeChild(int idx) const
{
Q_ASSERT(0 <= idx && idx <= treeChildCount());
if (idx == 0) {
return accidental();
if (accidental()) {
if (idx == 0) {
return accidental();
}
idx--;
}
return nullptr;
return Spanner::treeChild(idx);
}

int Trill::treeChildCount() const
{
if (accidental()) {
return 1;
return 1 + Spanner::treeChildCount();
}
return 0;
return Spanner::treeChildCount();
}

//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions mtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ subdirs (
libmscore/timesig
libmscore/tools # Some tests disabled
libmscore/transpose
libmscore/tree_model
libmscore/tuplet
# libmscore/text work in progress...
libmscore/utils
Expand Down
16 changes: 16 additions & 0 deletions mtest/libmscore/tree_model/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#=============================================================================
# MuseScore
# Music Composition & Notation
#
# Copyright (C) 2011 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 LICENSE.GPL
#=============================================================================

set(TARGET tst_tree_model)

include(${PROJECT_SOURCE_DIR}/mtest/cmake.inc)

109 changes: 109 additions & 0 deletions mtest/libmscore/tree_model/tst_tree_model.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// 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"

#define DIR QString("libmscore/layout_elements")

using namespace Ms;

//---------------------------------------------------------
// TestTreeModel
/// Ensures that the tree model is consistent. Starting
/// from Score each element in the tree should have the
/// correct parent element, the one whose children list
/// it appears in.
//---------------------------------------------------------

class TestTreeModel : public QObject, public MTest
{
Q_OBJECT

MasterScore * score;
void beam(const char* path);
void tstTree(QString file);
void traverseTree(ScoreElement* element);

QString elementToText(ScoreElement* element);

private slots:
void initTestCase();
void tstTreeElements() { tstTree("tree_elements.mscx"); }
void tstTreeTablature() { tstTree("tree_elements_tab.mscx"); }
void tstTreeMoonlight() { tstTree("moonlight.mscx"); }
void tstTreeGoldberg() { tstTree("goldberg.mscx"); }
};

//---------------------------------------------------------
// initTestCase
//---------------------------------------------------------

void TestTreeModel::initTestCase()
{
initMTest();
}

//---------------------------------------------------------
// tstTree
//---------------------------------------------------------

void TestTreeModel::tstTree(QString file)
{
MasterScore* score = readScore(DIR + file);
traverseTree(score);
}

//---------------------------------------------------------
// traverseTree
/// Checks whether parent element of current element is
/// correct, then recursively checks all children.
//---------------------------------------------------------

void TestTreeModel::traverseTree(ScoreElement* element)
{
for (ScoreElement* child : (*element)) {
if (child) {
// if parent is not correct print some logging info and exit
if (element->treeParent() != parent) {
qDebug() << "Element does not have correct parent!";
qDebug() << "Element name: " << elementToText(element);
qDebug() << "Parent in tree model: " << elementToText(element->treeParent());
qDebug() << "Expected parent: " << elementToText(parent);
}
QCOMPARE(element->treeParent(), parent);

// recursively apply to the rest of the tree
traverseTree(child);
}
}
}

//---------------------------------------------------------
// elementToText
/// for printing debug info about any element
//---------------------------------------------------------

QString TestTreeModel::elementToText(ScoreElement* element){
if (element == nullptr) {
return "nullptr";
}
if (element->isElement()){
return QString(toElement(element)->name()) + " (" + toElement(element)->accessibleInfo() + ")";
}
return element->userName();
}


QTEST_MAIN(TestTreeModel)
#include "tst_tree_model.moc"
1 change: 1 addition & 0 deletions mtest/mtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const char* tests[] = {
"libmscore/instrumentchange/tst_instrumentchange",
"libmscore/join/tst_join",
"libmscore/transpose/tst_transpose",
"libmscore/tree_model/tst_tree_model",
"libmscore/copypaste/tst_copypaste",
"libmscore/concertpitch/tst_concertpitchbenchmark",
"libmscore/selectionfilter/tst_selectionfilter",
Expand Down

0 comments on commit 0990831

Please sign in to comment.