diff --git a/AUTHORS b/AUTHORS index 5edb9eb..cbe7e02 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ -Andreas Cord-Landwehr +Andreas Cord-Landwehr Magdalena Konkiewicz Oindrila Gupta Samikshan Bairagya diff --git a/autotests/courseresource/resourcerepositorystub.cpp b/autotests/courseresource/resourcerepositorystub.cpp index 420eaf1..afab0bb 100644 --- a/autotests/courseresource/resourcerepositorystub.cpp +++ b/autotests/courseresource/resourcerepositorystub.cpp @@ -1,24 +1,24 @@ /* - * Copyright 2019 Andreas Cord-Landwehr + * Copyright 2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "resourcerepositorystub.h" // define one virtual method out of line to pin CourseStub to this translation unit ResourceRepositoryStub::~ResourceRepositoryStub() = default; diff --git a/autotests/courseresource/resourcerepositorystub.h b/autotests/courseresource/resourcerepositorystub.h index f9f5f1b..3cf2a10 100644 --- a/autotests/courseresource/resourcerepositorystub.h +++ b/autotests/courseresource/resourcerepositorystub.h @@ -1,81 +1,81 @@ /* - * Copyright 2019 Andreas Cord-Landwehr + * Copyright 2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef RESOURCEREPOSITORYSTUB_H #define RESOURCEREPOSITORYSTUB_H #include "core/iresourcerepository.h" #include #include class Language; class ICourse; /** * @brief The ResourceRepositoryStub that only provides languages and a storage location, but nothing else */ class ResourceRepositoryStub : public IResourceRepository { Q_OBJECT public: ResourceRepositoryStub(QVector languages) { m_languages = languages; } ~ResourceRepositoryStub() override; QString storageLocation() const override { return m_storageLocation; } QVector courses() const override { return QVector(); // do not return any courses: stub shall only provide languages } QVector courses(Language *language) const override { Q_UNUSED(language); return QVector(); // do not return any courses: stub shall only provide languages } void reloadCourses() override { ; // do nothing, stub shall only provide languages } QVector languages() const override { return m_languages; } Q_SIGNALS: void courseAboutToBeAdded(ICourse*,int) override; void courseAdded() override; void courseAboutToBeRemoved(int) override; void courseRemoved() override; private: QString m_storageLocation; QVector m_languages; }; #endif diff --git a/autotests/courseresource/test_courseresource.cpp b/autotests/courseresource/test_courseresource.cpp index 4c298e7..8110c97 100644 --- a/autotests/courseresource/test_courseresource.cpp +++ b/autotests/courseresource/test_courseresource.cpp @@ -1,255 +1,255 @@ /* - * Copyright 2013 Andreas Cord-Landwehr + * Copyright 2013 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "test_courseresource.h" #include "resourcerepositorystub.h" #include "core/language.h" #include "core/unit.h" #include "core/phrase.h" #include "core/resources/languageresource.h" #include "core/resources/courseresource.h" #include #include #include #include #include #include #include #include #include TestCourseResource::TestCourseResource() { } void TestCourseResource::init() { } void TestCourseResource::cleanup() { } void TestCourseResource::courseSchemeValidationTest() { QUrl schemeFile = QUrl::fromLocalFile(QStringLiteral("schemes/course.xsd")); QXmlSchema courseSchema; QVERIFY(courseSchema.load(schemeFile)); QVERIFY(courseSchema.isValid()); } void TestCourseResource::loadCourseResource() { Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); const QString courseDirectory = "data/courses/de/"; const QString courseFile = courseDirectory + "de.xml"; CourseResource course(QUrl::fromLocalFile(courseFile), &repository); QCOMPARE(course.file().toLocalFile(), courseFile); QCOMPARE(course.id(), "de"); QCOMPARE(course.foreignId(), "artikulate-basic"); QCOMPARE(course.title(), "Artikulate Deutsch"); QCOMPARE(course.description(), "Ein Kurs in (hoch-)deutscher Aussprache."); QVERIFY(course.language() != nullptr); QCOMPARE(course.language()->id(), "de"); QCOMPARE(course.unitList().count(), 1); const auto unit = course.unitList().first(); QVERIFY(unit != nullptr); QCOMPARE(unit->id(), "1"); QCOMPARE(unit->title(), QStringLiteral("Auf der Straße")); QCOMPARE(unit->foreignId(), "{dd60f04a-eb37-44b7-9787-67aaf7d3578d}"); QCOMPARE(unit->phraseList().count(), 3); // note: this test takes the silent assumption that phrases are added to the list in same // order as they are defined in the file. This assumption should be made explicit or dropped const auto firstPhrase = unit->phraseList().first(); QVERIFY(firstPhrase != nullptr); QCOMPARE(firstPhrase->id(), "1"); QCOMPARE(firstPhrase->foreignId(), "{3a4c1926-60d7-44c6-80d1-03165a641c75}"); QCOMPARE(firstPhrase->text(), "Guten Tag."); QCOMPARE(firstPhrase->soundFileUrl(), courseDirectory + "de_01.ogg"); QCOMPARE(firstPhrase->type(), Phrase::Type::Sentence); QVERIFY(firstPhrase->phonemes().isEmpty()); } void TestCourseResource::unitAddAndRemoveHandling() { // boilerplate Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); const QString courseDirectory = "data/courses/de/"; const QString courseFile = courseDirectory + "de.xml"; CourseResource course(QUrl::fromLocalFile(courseFile), &repository); // begin of test Unit unit; unit.setId("testunit"); const int initialUnitNumber = course.unitList().count(); QCOMPARE(initialUnitNumber, 1); QSignalSpy spyAboutToBeAdded(&course, SIGNAL(unitAboutToBeAdded(Unit*, int))); QSignalSpy spyAdded(&course, SIGNAL(unitAdded())); QCOMPARE(spyAboutToBeAdded.count(), 0); QCOMPARE(spyAdded.count(), 0); course.addUnit(&unit); QCOMPARE(course.unitList().count(), initialUnitNumber + 1); QCOMPARE(spyAboutToBeAdded.count(), 1); QCOMPARE(spyAdded.count(), 1); } void TestCourseResource::coursePropertyChanges() { // boilerplate Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); const QString courseDirectory = "data/courses/de/"; const QString courseFile = courseDirectory + "de.xml"; CourseResource course(QUrl::fromLocalFile(courseFile), &repository); // id { const QString value = "newId"; QSignalSpy spy(&course, SIGNAL(idChanged())); QCOMPARE(spy.count(), 0); course.setId(value); QCOMPARE(course.id(), value); QCOMPARE(spy.count(), 1); } // foreign id { const QString value = "newForeignId"; QSignalSpy spy(&course, SIGNAL(foreignIdChanged())); QCOMPARE(spy.count(), 0); course.setForeignId(value); QCOMPARE(course.foreignId(), value); QCOMPARE(spy.count(), 1); } // title { const QString value = "newTitle"; QSignalSpy spy(&course, SIGNAL(titleChanged())); QCOMPARE(spy.count(), 0); course.setTitle(value); QCOMPARE(course.title(), value); QCOMPARE(spy.count(), 1); } // title { const QString value = "newI18nTitle"; QSignalSpy spy(&course, SIGNAL(i18nTitleChanged())); QCOMPARE(spy.count(), 0); course.setI18nTitle(value); QCOMPARE(course.i18nTitle(), value); QCOMPARE(spy.count(), 1); } // description { const QString value = "newDescription"; QSignalSpy spy(&course, SIGNAL(descriptionChanged())); QCOMPARE(spy.count(), 0); course.setDescription(value); QCOMPARE(course.description(), value); QCOMPARE(spy.count(), 1); } // language { Language testLanguage; QSignalSpy spy(&course, SIGNAL(languageChanged())); QCOMPARE(spy.count(), 0); course.setLanguage(&testLanguage); QCOMPARE(course.language(), &testLanguage); QCOMPARE(spy.count(), 1); } } // FIXME porting break void TestCourseResource::fileLoadSaveCompleteness() { // ResourceManager manager; // manager.addLanguage(QUrl::fromLocalFile(QStringLiteral("data/languages/de.xml"))); // manager.addCourse(QUrl::fromLocalFile(QStringLiteral("data/courses/de.xml"))); // // test to encure further logic // QVERIFY(manager.courseResources(manager.languageResources().constFirst()->language()).count() == 1); // Course *testCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constFirst()->course(); // QTemporaryFile outputFile; // outputFile.open(); // QUrl oldFileName = testCourse->file(); // testCourse->setFile(QUrl::fromLocalFile(outputFile.fileName())); // testCourse->setLanguage(manager.languageResources().constFirst()->language()); // testCourse->sync(); // testCourse->setFile(oldFileName); // restore for later tests // QFile file(outputFile.fileName()); // if (!file.open(QIODevice::ReadOnly)) { // qCritical() << "Could not open file to read."; // } // //TODO this only works, since the resource manager not checks uniqueness of course ids! // manager.addCourse(QUrl::fromLocalFile(outputFile.fileName())); // Course *compareCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constLast()->course(); // // test that we actually call the different files // QVERIFY(testCourse->file().toLocalFile() != compareCourse->file().toLocalFile()); // QVERIFY(testCourse->id() == compareCourse->id()); // QVERIFY(testCourse->foreignId() == compareCourse->foreignId()); // QVERIFY(testCourse->title() == compareCourse->title()); // QVERIFY(testCourse->description() == compareCourse->description()); // QVERIFY(testCourse->language()->id() == compareCourse->language()->id()); // QVERIFY(testCourse->unitList().count() == compareCourse->unitList().count()); // Unit *testUnit = testCourse->unitList().constFirst(); // Unit *compareUnit = compareCourse->unitList().constFirst(); // QVERIFY(testUnit->id() == compareUnit->id()); // QVERIFY(testUnit->foreignId() == compareUnit->foreignId()); // QVERIFY(testUnit->title() == compareUnit->title()); // QVERIFY(testUnit->phraseList().count() == compareUnit->phraseList().count()); // Phrase *testPhrase = testUnit->phraseList().constFirst(); // Phrase *comparePhrase = new Phrase(this); // // Note that this actually means that we DO NOT respect phrase orders by list order! // foreach (Phrase *phrase, compareUnit->phraseList()) { // if (testPhrase->id() == phrase->id()) { // comparePhrase = phrase; // break; // } // } // QVERIFY(testPhrase->id() == comparePhrase->id()); // QVERIFY(testPhrase->foreignId() == comparePhrase->foreignId()); // QVERIFY(testPhrase->text() == comparePhrase->text()); // QVERIFY(testPhrase->type() == comparePhrase->type()); // QVERIFY(testPhrase->sound().fileName() == comparePhrase->sound().fileName()); // QVERIFY(testPhrase->phonemes().count() == comparePhrase->phonemes().count()); // //FIXME implement phoneme checks after phonemes are fully implemented } QTEST_GUILESS_MAIN(TestCourseResource) diff --git a/autotests/courseresource/test_courseresource.h b/autotests/courseresource/test_courseresource.h index ac6685f..1139079 100644 --- a/autotests/courseresource/test_courseresource.h +++ b/autotests/courseresource/test_courseresource.h @@ -1,75 +1,75 @@ /* - * Copyright 2013-2019 Andreas Cord-Landwehr + * Copyright 2013-2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef TESTCOURSERESOURCE_H #define TESTCOURSERESOURCE_H #include #include class TestCourseResource : public QObject { Q_OBJECT public: TestCourseResource(); private slots: /** * @brief Called before every test case. */ void init(); /** * @brief Called after every test case. */ void cleanup(); /** * @brief Test if course XSD specification is valid. */ void courseSchemeValidationTest(); /** * @brief Test simple loading of course resource XML file */ void loadCourseResource(); /** * @brief Test handling of unit insertions (specifically, the signals) */ void unitAddAndRemoveHandling(); /** * @brief Test of all course property changes except unit handling */ void coursePropertyChanges(); /** * Test if serialization of unserialized file gives original file. * TODO this is a test by only string equality and should improved to test on a data level */ void fileLoadSaveCompleteness(); private: bool m_systemUseCourseRepositoryValue; }; #endif diff --git a/autotests/editablecourseresource/resourcerepositorystub.cpp b/autotests/editablecourseresource/resourcerepositorystub.cpp index 420eaf1..afab0bb 100644 --- a/autotests/editablecourseresource/resourcerepositorystub.cpp +++ b/autotests/editablecourseresource/resourcerepositorystub.cpp @@ -1,24 +1,24 @@ /* - * Copyright 2019 Andreas Cord-Landwehr + * Copyright 2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "resourcerepositorystub.h" // define one virtual method out of line to pin CourseStub to this translation unit ResourceRepositoryStub::~ResourceRepositoryStub() = default; diff --git a/autotests/editablecourseresource/resourcerepositorystub.h b/autotests/editablecourseresource/resourcerepositorystub.h index f9f5f1b..3cf2a10 100644 --- a/autotests/editablecourseresource/resourcerepositorystub.h +++ b/autotests/editablecourseresource/resourcerepositorystub.h @@ -1,81 +1,81 @@ /* - * Copyright 2019 Andreas Cord-Landwehr + * Copyright 2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef RESOURCEREPOSITORYSTUB_H #define RESOURCEREPOSITORYSTUB_H #include "core/iresourcerepository.h" #include #include class Language; class ICourse; /** * @brief The ResourceRepositoryStub that only provides languages and a storage location, but nothing else */ class ResourceRepositoryStub : public IResourceRepository { Q_OBJECT public: ResourceRepositoryStub(QVector languages) { m_languages = languages; } ~ResourceRepositoryStub() override; QString storageLocation() const override { return m_storageLocation; } QVector courses() const override { return QVector(); // do not return any courses: stub shall only provide languages } QVector courses(Language *language) const override { Q_UNUSED(language); return QVector(); // do not return any courses: stub shall only provide languages } void reloadCourses() override { ; // do nothing, stub shall only provide languages } QVector languages() const override { return m_languages; } Q_SIGNALS: void courseAboutToBeAdded(ICourse*,int) override; void courseAdded() override; void courseAboutToBeRemoved(int) override; void courseRemoved() override; private: QString m_storageLocation; QVector m_languages; }; #endif diff --git a/autotests/editablecourseresource/test_editablecourseresource.cpp b/autotests/editablecourseresource/test_editablecourseresource.cpp index 42dd7d2..46325c7 100644 --- a/autotests/editablecourseresource/test_editablecourseresource.cpp +++ b/autotests/editablecourseresource/test_editablecourseresource.cpp @@ -1,241 +1,241 @@ /* - * Copyright 2013-2019 Andreas Cord-Landwehr + * Copyright 2013-2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "test_editablecourseresource.h" #include "resourcerepositorystub.h" #include "core/language.h" #include "core/unit.h" #include "core/phrase.h" #include "core/resources/courseparser.h" #include "core/resources/languageresource.h" #include "core/resources/editablecourseresource.h" #include #include #include #include #include #include #include #include #include TestEditableCourseResource::TestEditableCourseResource() { } void TestEditableCourseResource::init() { } void TestEditableCourseResource::cleanup() { } void TestEditableCourseResource::courseSchemeValidationTest() { QUrl schemeFile = QUrl::fromLocalFile(QStringLiteral("schemes/course.xsd")); QXmlSchema courseSchema; QVERIFY(courseSchema.load(schemeFile)); QVERIFY(courseSchema.isValid()); //TODO shall be used in skeleton specific test QUrl skeletonFile = QUrl::fromLocalFile(QStringLiteral("schemes/skeleton.xsd")); QXmlSchema skeletonScheme; QVERIFY(skeletonScheme.load(skeletonFile)); QVERIFY(skeletonScheme.isValid()); } void TestEditableCourseResource::loadCourseResource() { Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); EditableCourseResource course(QUrl::fromLocalFile(":/courses/de.xml"), &repository); QCOMPARE(course.file().toLocalFile(), ":/courses/de.xml"); QCOMPARE(course.id(), "de"); QCOMPARE(course.foreignId(), "artikulate-basic"); QCOMPARE(course.title(), "Artikulate Deutsch"); QCOMPARE(course.description(), "Ein Kurs in (hoch-)deutscher Aussprache."); QVERIFY(course.language() != nullptr); QCOMPARE(course.language()->id(), "de"); QCOMPARE(course.unitList().count(), 1); const auto unit = course.unitList().first(); QVERIFY(unit != nullptr); QCOMPARE(unit->id(), "1"); QCOMPARE(unit->title(), QStringLiteral("Auf der Straße")); QCOMPARE(unit->foreignId(), "{dd60f04a-eb37-44b7-9787-67aaf7d3578d}"); QCOMPARE(unit->phraseList().count(), 3); // note: this test takes the silent assumption that phrases are added to the list in same // order as they are defined in the file. This assumption should be made explicit or dropped const auto firstPhrase = unit->phraseList().first(); QVERIFY(firstPhrase != nullptr); QCOMPARE(firstPhrase->id(), "1"); QCOMPARE(firstPhrase->foreignId(), "{3a4c1926-60d7-44c6-80d1-03165a641c75}"); QCOMPARE(firstPhrase->text(), "Guten Tag."); QCOMPARE(firstPhrase->soundFileUrl(), ":/courses/de_01.ogg"); QCOMPARE(firstPhrase->type(), Phrase::Type::Sentence); QVERIFY(firstPhrase->phonemes().isEmpty()); } void TestEditableCourseResource::unitAddAndRemoveHandling() { // boilerplate Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); EditableCourseResource course(QUrl::fromLocalFile(":/courses/de.xml"), &repository); // begin of test Unit unit; unit.setId("testunit"); const int initialUnitNumber = course.unitList().count(); QCOMPARE(initialUnitNumber, 1); QSignalSpy spyAboutToBeAdded(&course, SIGNAL(unitAboutToBeAdded(Unit*, int))); QSignalSpy spyAdded(&course, SIGNAL(unitAdded())); QCOMPARE(spyAboutToBeAdded.count(), 0); QCOMPARE(spyAdded.count(), 0); course.addUnit(&unit); QCOMPARE(course.unitList().count(), initialUnitNumber + 1); QCOMPARE(spyAboutToBeAdded.count(), 1); QCOMPARE(spyAdded.count(), 1); } void TestEditableCourseResource::coursePropertyChanges() { // boilerplate Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); CourseResource course(QUrl::fromLocalFile(":/courses/de.xml"), &repository); // id { const QString value = "newId"; QSignalSpy spy(&course, SIGNAL(idChanged())); QCOMPARE(spy.count(), 0); course.setId(value); QCOMPARE(course.id(), value); QCOMPARE(spy.count(), 1); } // foreign id { const QString value = "newForeignId"; QSignalSpy spy(&course, SIGNAL(foreignIdChanged())); QCOMPARE(spy.count(), 0); course.setForeignId(value); QCOMPARE(course.foreignId(), value); QCOMPARE(spy.count(), 1); } // title { const QString value = "newTitle"; QSignalSpy spy(&course, SIGNAL(titleChanged())); QCOMPARE(spy.count(), 0); course.setTitle(value); QCOMPARE(course.title(), value); QCOMPARE(spy.count(), 1); } // title { const QString value = "newI18nTitle"; QSignalSpy spy(&course, SIGNAL(i18nTitleChanged())); QCOMPARE(spy.count(), 0); course.setI18nTitle(value); QCOMPARE(course.i18nTitle(), value); QCOMPARE(spy.count(), 1); } // description { const QString value = "newDescription"; QSignalSpy spy(&course, SIGNAL(descriptionChanged())); QCOMPARE(spy.count(), 0); course.setDescription(value); QCOMPARE(course.description(), value); QCOMPARE(spy.count(), 1); } // language { Language testLanguage; QSignalSpy spy(&course, SIGNAL(languageChanged())); QCOMPARE(spy.count(), 0); course.setLanguage(&testLanguage); QCOMPARE(course.language(), &testLanguage); QCOMPARE(spy.count(), 1); } } void TestEditableCourseResource::fileLoadSaveCompleteness() { // boilerplate Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); EditableCourseResource course(QUrl::fromLocalFile(":/courses/de.xml"), &repository); QTemporaryFile outputFile; outputFile.open(); course.exportCourse(QUrl::fromLocalFile(outputFile.fileName())); // note: this only works, since the resource manager not checks uniqueness of course ids! EditableCourseResource loadedCourse(QUrl::fromLocalFile(outputFile.fileName()), &repository); // test that we actually call the different files QVERIFY(course.file().toLocalFile() != loadedCourse.file().toLocalFile()); QVERIFY(course.id() == loadedCourse.id()); QVERIFY(course.foreignId() == loadedCourse.foreignId()); QVERIFY(course.title() == loadedCourse.title()); QVERIFY(course.description() == loadedCourse.description()); QVERIFY(course.language()->id() == loadedCourse.language()->id()); QVERIFY(course.unitList().count() == loadedCourse.unitList().count()); Unit *testUnit = course.unitList().constFirst(); Unit *compareUnit = loadedCourse.unitList().constFirst(); QVERIFY(testUnit->id() == compareUnit->id()); QVERIFY(testUnit->foreignId() == compareUnit->foreignId()); QVERIFY(testUnit->title() == compareUnit->title()); QVERIFY(testUnit->phraseList().count() == compareUnit->phraseList().count()); Phrase *testPhrase = testUnit->phraseList().constFirst(); Phrase *comparePhrase = new Phrase(this); // note that this actually means that we DO NOT respect phrase orders by list order for (Phrase *phrase : compareUnit->phraseList()) { if (testPhrase->id() == phrase->id()) { comparePhrase = phrase; break; } } QVERIFY(testPhrase->id() == comparePhrase->id()); QVERIFY(testPhrase->foreignId() == comparePhrase->foreignId()); QVERIFY(testPhrase->text() == comparePhrase->text()); QVERIFY(testPhrase->type() == comparePhrase->type()); QVERIFY(testPhrase->sound().fileName() == comparePhrase->sound().fileName()); QVERIFY(testPhrase->phonemes().count() == comparePhrase->phonemes().count()); } QTEST_GUILESS_MAIN(TestEditableCourseResource) diff --git a/autotests/editablecourseresource/test_editablecourseresource.h b/autotests/editablecourseresource/test_editablecourseresource.h index d07351d..16a58b1 100644 --- a/autotests/editablecourseresource/test_editablecourseresource.h +++ b/autotests/editablecourseresource/test_editablecourseresource.h @@ -1,71 +1,71 @@ /* - * Copyright 2013-2019 Andreas Cord-Landwehr + * Copyright 2013-2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef TESTEDITABLECOURSERESOURCE_H #define TESTEDITABLECOURSERESOURCE_H #include #include class TestEditableCourseResource : public QObject { Q_OBJECT public: TestEditableCourseResource(); private Q_SLOTS: /** * @brief Called before every test case. */ void init(); /** * @brief Called after every test case. */ void cleanup(); /** * @brief Test if course XSD specification is valid. */ void courseSchemeValidationTest(); /** * @brief Test simple loading of course resource XML file */ void loadCourseResource(); /** * @brief Test handling of unit insertions (specifically, the signals) */ void unitAddAndRemoveHandling(); /** * @brief Test of all course property changes except unit handling */ void coursePropertyChanges(); /** * Test if serialization of unserialized file gives original file. */ void fileLoadSaveCompleteness(); }; #endif diff --git a/autotests/skeletonresource/resourcerepositorystub.cpp b/autotests/skeletonresource/resourcerepositorystub.cpp index 420eaf1..afab0bb 100644 --- a/autotests/skeletonresource/resourcerepositorystub.cpp +++ b/autotests/skeletonresource/resourcerepositorystub.cpp @@ -1,24 +1,24 @@ /* - * Copyright 2019 Andreas Cord-Landwehr + * Copyright 2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "resourcerepositorystub.h" // define one virtual method out of line to pin CourseStub to this translation unit ResourceRepositoryStub::~ResourceRepositoryStub() = default; diff --git a/autotests/skeletonresource/resourcerepositorystub.h b/autotests/skeletonresource/resourcerepositorystub.h index f9f5f1b..3cf2a10 100644 --- a/autotests/skeletonresource/resourcerepositorystub.h +++ b/autotests/skeletonresource/resourcerepositorystub.h @@ -1,81 +1,81 @@ /* - * Copyright 2019 Andreas Cord-Landwehr + * Copyright 2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef RESOURCEREPOSITORYSTUB_H #define RESOURCEREPOSITORYSTUB_H #include "core/iresourcerepository.h" #include #include class Language; class ICourse; /** * @brief The ResourceRepositoryStub that only provides languages and a storage location, but nothing else */ class ResourceRepositoryStub : public IResourceRepository { Q_OBJECT public: ResourceRepositoryStub(QVector languages) { m_languages = languages; } ~ResourceRepositoryStub() override; QString storageLocation() const override { return m_storageLocation; } QVector courses() const override { return QVector(); // do not return any courses: stub shall only provide languages } QVector courses(Language *language) const override { Q_UNUSED(language); return QVector(); // do not return any courses: stub shall only provide languages } void reloadCourses() override { ; // do nothing, stub shall only provide languages } QVector languages() const override { return m_languages; } Q_SIGNALS: void courseAboutToBeAdded(ICourse*,int) override; void courseAdded() override; void courseAboutToBeRemoved(int) override; void courseRemoved() override; private: QString m_storageLocation; QVector m_languages; }; #endif diff --git a/autotests/skeletonresource/test_skeletonresource.cpp b/autotests/skeletonresource/test_skeletonresource.cpp index aee1d8a..a083cf1 100644 --- a/autotests/skeletonresource/test_skeletonresource.cpp +++ b/autotests/skeletonresource/test_skeletonresource.cpp @@ -1,225 +1,225 @@ /* - * Copyright 2019 Andreas Cord-Landwehr + * Copyright 2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "test_skeletonresource.h" #include "resourcerepositorystub.h" #include "core/language.h" #include "core/unit.h" #include "core/phrase.h" #include "core/resources/languageresource.h" #include "core/resources/skeletonresource.h" #include #include #include #include #include #include #include #include #include TestSkeletonResource::TestSkeletonResource() { } void TestSkeletonResource::init() { } void TestSkeletonResource::cleanup() { } void TestSkeletonResource::schemeValidationTest() { QUrl skeletonFile = QUrl::fromLocalFile(QStringLiteral("schemes/skeleton.xsd")); QXmlSchema skeletonScheme; QVERIFY(skeletonScheme.load(skeletonFile)); QVERIFY(skeletonScheme.isValid()); } void TestSkeletonResource::loadSkeletonResource() { Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); const QString courseDirectory = "data/contributorrepository/skeletons/"; const QString courseFile = courseDirectory + "skeleton.xml"; SkeletonResource course(QUrl::fromLocalFile(courseFile), &repository); QCOMPARE(course.file().toLocalFile(), courseFile); QCOMPARE(course.id(), "skeleton-testdata"); QCOMPARE(course.foreignId(), "skeleton-testdata"); // always same as ID QCOMPARE(course.title(), "Artikulate Test Course Title"); QCOMPARE(course.description(), "Artikulate Test Course Description"); QVERIFY(course.language() == nullptr); // a skeleton must not have a language QCOMPARE(course.unitList().count(), 2); const auto unit = course.unitList().first(); QVERIFY(unit != nullptr); QCOMPARE(unit->id(), "{11111111-b885-4833-97ff-27cb1ca2f543}"); QCOMPARE(unit->title(), QStringLiteral("Numbers")); QCOMPARE(unit->phraseList().count(), 2); // note: this test takes the silent assumption that phrases are added to the list in same // order as they are defined in the file. This assumption should be made explicit or dropped const auto firstPhrase = unit->phraseList().first(); QVERIFY(firstPhrase != nullptr); QCOMPARE(firstPhrase->id(), "{22222222-9234-4da5-a6fe-dbd5104f57d5}"); QCOMPARE(firstPhrase->text(), "0"); QCOMPARE(firstPhrase->type(), Phrase::Type::Word); const auto secondPhrase = unit->phraseList().at(1); QVERIFY(secondPhrase != nullptr); QCOMPARE(secondPhrase->id(), "{333333333-b4a9-4264-9a26-75a55aa5d302}"); QCOMPARE(secondPhrase->text(), "1"); QCOMPARE(secondPhrase->type(), Phrase::Type::Word); } void TestSkeletonResource::unitAddAndRemoveHandling() { // boilerplate Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); const QString courseDirectory = "data/courses/de/"; const QString courseFile = courseDirectory + "de.xml"; SkeletonResource course(QUrl::fromLocalFile(courseFile), &repository); // begin of test Unit unit; unit.setId("testunit"); const int initialUnitNumber = course.unitList().count(); QCOMPARE(initialUnitNumber, 1); QSignalSpy spyAboutToBeAdded(&course, SIGNAL(unitAboutToBeAdded(Unit*, int))); QSignalSpy spyAdded(&course, SIGNAL(unitAdded())); QCOMPARE(spyAboutToBeAdded.count(), 0); QCOMPARE(spyAdded.count(), 0); course.addUnit(&unit); QCOMPARE(course.unitList().count(), initialUnitNumber + 1); QCOMPARE(spyAboutToBeAdded.count(), 1); QCOMPARE(spyAdded.count(), 1); } void TestSkeletonResource::coursePropertyChanges() { // boilerplate Language language; language.setId("de"); ResourceRepositoryStub repository({&language}); const QString courseDirectory = "data/courses/de/"; const QString courseFile = courseDirectory + "de.xml"; SkeletonResource course(QUrl::fromLocalFile(courseFile), &repository); // id { const QString value = "newId"; QSignalSpy spy(&course, SIGNAL(idChanged())); QCOMPARE(spy.count(), 0); course.setId(value); QCOMPARE(course.id(), value); QCOMPARE(spy.count(), 1); } // title { const QString value = "newTitle"; QSignalSpy spy(&course, SIGNAL(titleChanged())); QCOMPARE(spy.count(), 0); course.setTitle(value); QCOMPARE(course.title(), value); QCOMPARE(spy.count(), 1); } // description { const QString value = "newDescription"; QSignalSpy spy(&course, SIGNAL(descriptionChanged())); QCOMPARE(spy.count(), 0); course.setDescription(value); QCOMPARE(course.description(), value); QCOMPARE(spy.count(), 1); } } // FIXME porting break //void TestCourseResource::fileLoadSaveCompleteness() //{ // ResourceManager manager; // manager.addLanguage(QUrl::fromLocalFile(QStringLiteral("data/languages/de.xml"))); // manager.addCourse(QUrl::fromLocalFile(QStringLiteral("data/courses/de.xml"))); // // test to encure further logic // QVERIFY(manager.courseResources(manager.languageResources().constFirst()->language()).count() == 1); // Course *testCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constFirst()->course(); // QTemporaryFile outputFile; // outputFile.open(); // QUrl oldFileName = testCourse->file(); // testCourse->setFile(QUrl::fromLocalFile(outputFile.fileName())); // testCourse->setLanguage(manager.languageResources().constFirst()->language()); // testCourse->sync(); // testCourse->setFile(oldFileName); // restore for later tests // QFile file(outputFile.fileName()); // if (!file.open(QIODevice::ReadOnly)) { // qCritical() << "Could not open file to read."; // } // //TODO this only works, since the resource manager not checks uniqueness of course ids! // manager.addCourse(QUrl::fromLocalFile(outputFile.fileName())); // Course *compareCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constLast()->course(); // // test that we actually call the different files // QVERIFY(testCourse->file().toLocalFile() != compareCourse->file().toLocalFile()); // QVERIFY(testCourse->id() == compareCourse->id()); // QVERIFY(testCourse->foreignId() == compareCourse->foreignId()); // QVERIFY(testCourse->title() == compareCourse->title()); // QVERIFY(testCourse->description() == compareCourse->description()); // QVERIFY(testCourse->language()->id() == compareCourse->language()->id()); // QVERIFY(testCourse->unitList().count() == compareCourse->unitList().count()); // Unit *testUnit = testCourse->unitList().constFirst(); // Unit *compareUnit = compareCourse->unitList().constFirst(); // QVERIFY(testUnit->id() == compareUnit->id()); // QVERIFY(testUnit->foreignId() == compareUnit->foreignId()); // QVERIFY(testUnit->title() == compareUnit->title()); // QVERIFY(testUnit->phraseList().count() == compareUnit->phraseList().count()); // Phrase *testPhrase = testUnit->phraseList().constFirst(); // Phrase *comparePhrase = new Phrase(this); // // Note that this actually means that we DO NOT respect phrase orders by list order! // foreach (Phrase *phrase, compareUnit->phraseList()) { // if (testPhrase->id() == phrase->id()) { // comparePhrase = phrase; // break; // } // } // QVERIFY(testPhrase->id() == comparePhrase->id()); // QVERIFY(testPhrase->foreignId() == comparePhrase->foreignId()); // QVERIFY(testPhrase->text() == comparePhrase->text()); // QVERIFY(testPhrase->type() == comparePhrase->type()); // QVERIFY(testPhrase->sound().fileName() == comparePhrase->sound().fileName()); // QVERIFY(testPhrase->phonemes().count() == comparePhrase->phonemes().count()); // //FIXME implement phoneme checks after phonemes are fully implemented //} QTEST_GUILESS_MAIN(TestSkeletonResource) diff --git a/autotests/skeletonresource/test_skeletonresource.h b/autotests/skeletonresource/test_skeletonresource.h index 7ff8085..19f284e 100644 --- a/autotests/skeletonresource/test_skeletonresource.h +++ b/autotests/skeletonresource/test_skeletonresource.h @@ -1,75 +1,75 @@ /* - * Copyright 2013-2019 Andreas Cord-Landwehr + * Copyright 2013-2019 Andreas Cord-Landwehr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef TESTSKELETONRESOURCE_H #define TESTSKELETONRESOURCE_H #include #include class TestSkeletonResource : public QObject { Q_OBJECT public: TestSkeletonResource(); private slots: /** * @brief Called before every test case. */ void init(); /** * @brief Called after every test case. */ void cleanup(); /** * @brief Test if course XSD specification is valid. */ void schemeValidationTest(); /** * @brief Test simple loading of course resource XML file */ void loadSkeletonResource(); /** * @brief Test handling of unit insertions (specifically, the signals) */ void unitAddAndRemoveHandling(); /** * @brief Test of all course property changes except unit handling */ void coursePropertyChanges(); /** * Test if serialization of unserialized file gives original file. * TODO this is a test by only string equality and should improved to test on a data level */ // void fileLoadSaveCompleteness(); private: bool m_systemUseCourseRepositoryValue; }; #endif