File indexing completed on 2024-04-21 04:52:51

0001 /*
0002     SPDX-FileCopyrightText: 2018-2022 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003     SPDX-FileCopyrightText: 2022 Eric Jiang
0004     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 #include "test_utils.hpp"
0007 // test specific headers
0008 #include "bin/binplaylist.hpp"
0009 #include "doc/kdenlivedoc.h"
0010 #include "timeline2/model/builders/meltBuilder.hpp"
0011 #include "xml/xml.hpp"
0012 
0013 #include <QTemporaryFile>
0014 #include <QUndoGroup>
0015 
0016 using namespace fakeit;
0017 
0018 TEST_CASE("Save File", "[SF]")
0019 {
0020     auto binModel = pCore->projectItemModel();
0021     binModel->clean();
0022     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0023 
0024     SECTION("Simple insert and save")
0025     {
0026         // Create document
0027         KdenliveDoc document(undoStack);
0028         pCore->projectManager()->m_project = &document;
0029         QDateTime documentDate = QDateTime::currentDateTime();
0030         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0031         auto timeline = document.getTimeline(document.uuid());
0032         pCore->projectManager()->testSetActiveDocument(&document, timeline);
0033         KdenliveDoc::next_id = 0;
0034         QDir dir = QDir::temp();
0035 
0036         QString binId = createProducerWithSound(pCore->getProjectProfile(), binModel);
0037         QString binId2 = createProducer(pCore->getProjectProfile(), "red", binModel, 20, false);
0038 
0039         int tid1 = timeline->getTrackIndexFromPosition(2);
0040 
0041         // Setup timeline audio drop info
0042         QMap<int, QString> audioInfo;
0043         audioInfo.insert(1, QStringLiteral("stream1"));
0044         timeline->m_binAudioTargets = audioInfo;
0045         timeline->m_videoTarget = tid1;
0046         // Insert 2 clips (length=20, pos = 80 / 100)
0047         int cid1 = -1;
0048         REQUIRE(timeline->requestClipInsertion(binId2, tid1, 80, cid1, true, true, false));
0049         int l = timeline->getClipPlaytime(cid1);
0050         int cid2 = -1;
0051         REQUIRE(timeline->requestClipInsertion(binId2, tid1, 80 + l, cid2, true, true, false));
0052         // Resize first clip (length=100)
0053         REQUIRE(timeline->requestItemResize(cid1, 100, false) == 100);
0054 
0055         auto state = [&]() {
0056             REQUIRE(timeline->checkConsistency());
0057             REQUIRE(timeline->getTrackClipsCount(tid1) == 2);
0058             REQUIRE(timeline->getClipTrackId(cid1) == tid1);
0059             REQUIRE(timeline->getClipTrackId(cid2) == tid1);
0060             REQUIRE(timeline->getClipPosition(cid1) == 0);
0061             REQUIRE(timeline->getClipPosition(cid2) == 100);
0062             REQUIRE(timeline->getClipPlaytime(cid1) == 100);
0063             REQUIRE(timeline->getClipPlaytime(cid2) == 20);
0064         };
0065         state();
0066         REQUIRE(timeline->checkConsistency());
0067         pCore->projectManager()->testSaveFileAs(dir.absoluteFilePath(QStringLiteral("test.kdenlive")));
0068         // Undo resize
0069         undoStack->undo();
0070         // Undo first insert
0071         undoStack->undo();
0072         // Undo second insert
0073         undoStack->undo();
0074         pCore->projectManager()->closeCurrentDocument(false, false);
0075     }
0076     SECTION("Reopen and check in/out points")
0077     {
0078         // Create new document
0079         // We mock the project class so that the undoStack function returns our undoStack, and our mocked document
0080         KdenliveDoc::next_id = 0;
0081         QString saveFile = QDir::temp().absoluteFilePath(QStringLiteral("test.kdenlive"));
0082         QUrl openURL = QUrl::fromLocalFile(saveFile);
0083 
0084         QUndoGroup *undoGroup = new QUndoGroup();
0085         undoGroup->addStack(undoStack.get());
0086         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0087         REQUIRE(openResults.isSuccessful() == true);
0088 
0089         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0090         pCore->projectManager()->m_project = openedDoc.get();
0091         const QUuid uuid = openedDoc->uuid();
0092         QDateTime documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0093         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0094         pCore->projectManager()->testSetActiveDocument(openedDoc.get());
0095         auto timeline = pCore->projectManager()->m_project->getTimeline(uuid);
0096         const QString hash = openedDoc->getSequenceProperty(uuid, QStringLiteral("timelineHash"));
0097         REQUIRE(timeline->getTracksCount() == 4);
0098         REQUIRE(timeline->checkConsistency());
0099         int tid1 = timeline->getTrackIndexFromPosition(2);
0100         int cid1 = timeline->getClipByStartPosition(tid1, 0);
0101         int cid2 = timeline->getClipByStartPosition(tid1, 100);
0102         REQUIRE(cid1 > -1);
0103         REQUIRE(cid2 > -1);
0104         auto state = [&]() {
0105             REQUIRE(timeline->checkConsistency());
0106             REQUIRE(timeline->getTrackClipsCount(tid1) == 2);
0107             REQUIRE(timeline->getClipTrackId(cid1) == tid1);
0108             REQUIRE(timeline->getClipTrackId(cid2) == tid1);
0109             REQUIRE(timeline->getClipPosition(cid1) == 0);
0110             REQUIRE(timeline->getClipPosition(cid2) == 100);
0111             REQUIRE(timeline->getClipPlaytime(cid1) == 100);
0112             REQUIRE(timeline->getClipPlaytime(cid2) == 20);
0113         };
0114         state();
0115         QByteArray updatedHex = timeline->timelineHash().toHex();
0116         REQUIRE(updatedHex == hash);
0117         pCore->projectManager()->closeCurrentDocument(false, false);
0118         QDir dir = QDir::temp();
0119         QFile::remove(dir.absoluteFilePath(QStringLiteral("test.kdenlive")));
0120     }
0121     SECTION("Open a file with AV clips")
0122     {
0123         // Create new document
0124         QString path = sourcesPath + "/dataset/av.kdenlive";
0125         QUrl openURL = QUrl::fromLocalFile(path);
0126 
0127         QUndoGroup *undoGroup = new QUndoGroup();
0128         undoGroup->addStack(undoStack.get());
0129         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0130         REQUIRE(openResults.isSuccessful() == true);
0131         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0132 
0133         pCore->projectManager()->m_project = openedDoc.get();
0134         const QUuid uuid = openedDoc->uuid();
0135         QDateTime documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0136         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0137         auto timeline = pCore->projectManager()->m_project->getTimeline(uuid);
0138         pCore->projectManager()->testSetActiveDocument(openedDoc.get(), timeline);
0139 
0140         REQUIRE(timeline->checkConsistency());
0141         int tid1 = timeline->getTrackIndexFromPosition(0);
0142         int tid2 = timeline->getTrackIndexFromPosition(1);
0143         int tid3 = timeline->getTrackIndexFromPosition(2);
0144         int tid4 = timeline->getTrackIndexFromPosition(3);
0145         // Check we have audio and video tracks
0146         REQUIRE(timeline->isAudioTrack(tid1));
0147         REQUIRE(timeline->isAudioTrack(tid2));
0148         REQUIRE(timeline->isAudioTrack(tid3) == false);
0149         REQUIRE(timeline->isAudioTrack(tid4) == false);
0150         int cid1 = timeline->getClipByStartPosition(tid1, 0);
0151         int cid2 = timeline->getClipByStartPosition(tid2, 0);
0152         int cid3 = timeline->getClipByStartPosition(tid3, 0);
0153         int cid4 = timeline->getClipByStartPosition(tid4, 0);
0154         // Check we have our clips
0155         REQUIRE(cid1 == -1);
0156         REQUIRE(cid2 > -1);
0157         REQUIRE(cid3 > -1);
0158         REQUIRE(cid4 == -1);
0159         REQUIRE(timeline->getClipPlaytime(cid2) == 500);
0160         REQUIRE(timeline->getClipPlaytime(cid3) == 500);
0161         pCore->projectManager()->closeCurrentDocument(false, false);
0162     }
0163 }
0164 
0165 TEST_CASE("Check File Corruption", "[CFC]")
0166 {
0167     auto binModel = pCore->projectItemModel();
0168     binModel->clean();
0169     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0170 
0171     SECTION("Open a file and check id consistency")
0172     {
0173         // open
0174         QString path = sourcesPath + "/dataset/clip-ids.kdenlive";
0175         QUrl openURL = QUrl::fromLocalFile(path);
0176 
0177         QUndoGroup *undoGroup = new QUndoGroup();
0178         undoGroup->addStack(undoStack.get());
0179         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0180         REQUIRE(openResults.isSuccessful() == true);
0181 
0182         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0183         // Mock<KdenliveDoc> docMock(*openedDoc.get());
0184         // When(Method(docMock, getCacheDir)).AlwaysReturn(QDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)));
0185         // KdenliveDoc &mockedDoc = docMock.get();
0186         pCore->projectManager()->m_project = openedDoc.get();
0187         const QUuid uuid = openedDoc->uuid();
0188         QDateTime documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0189         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0190 
0191         QMap<QUuid, QString> allSequences = binModel->getAllSequenceClips();
0192         const QString firstSeqId = allSequences.value(uuid);
0193         pCore->projectManager()->openTimeline(firstSeqId, uuid);
0194         std::shared_ptr<TimelineItemModel> timeline = openedDoc->getTimeline(uuid);
0195         pCore->projectManager()->testSetActiveDocument(openedDoc.get(), timeline);
0196 
0197         // Now reopen all timeline sequences
0198         QList<QUuid> allUuids = allSequences.keys();
0199         allUuids.removeAll(uuid);
0200         for (auto &u : allUuids) {
0201             const QString id = allSequences.value(u);
0202             pCore->projectManager()->openTimeline(id, u);
0203         }
0204 
0205         // std::shared_ptr<TimelineItemModel> timeline = openedDoc->getTimeline(uuid);
0206         // pCore->projectManager()->testSetActiveDocument(&mockedDoc);
0207         // auto timeline = mockedDoc.getTimeline(uuid);
0208 
0209         REQUIRE(timeline->checkConsistency());
0210         int tid1 = timeline->getTrackIndexFromPosition(0);
0211         int tid2 = timeline->getTrackIndexFromPosition(1);
0212         int tid3 = timeline->getTrackIndexFromPosition(2);
0213         int tid4 = timeline->getTrackIndexFromPosition(3);
0214         // Check we have audio and video tracks
0215         REQUIRE(timeline->isAudioTrack(tid1));
0216         REQUIRE(timeline->isAudioTrack(tid2));
0217         REQUIRE(timeline->isAudioTrack(tid3) == false);
0218         REQUIRE(timeline->isAudioTrack(tid4) == false);
0219         int cid1 = timeline->getClipByStartPosition(tid4, 16);  // Blue
0220         int cid2 = timeline->getClipByStartPosition(tid4, 21);  // Green
0221         int cid3 = timeline->getClipByStartPosition(tid4, 26);  // Red
0222         int cid4 = timeline->getClipByStartPosition(tid4, 31);  // Yellow
0223         int cid1b = timeline->getClipByStartPosition(tid3, 11); // Blue
0224         int cid2b = timeline->getClipByStartPosition(tid3, 16); // Green
0225         int cid3b = timeline->getClipByStartPosition(tid3, 21); // Red
0226         int cid4b = timeline->getClipByStartPosition(tid3, 26); // Yellow
0227         // Check we have our clips
0228         REQUIRE(cid1 > -1);
0229         REQUIRE(cid2 > -1);
0230         REQUIRE(cid3 > -1);
0231         REQUIRE(cid4 > -1);
0232         REQUIRE(cid1b > -1);
0233         REQUIRE(cid2b > -1);
0234         REQUIRE(cid3b > -1);
0235         REQUIRE(cid4b > -1);
0236         REQUIRE(timeline->getClipPtr(cid1)->clipName() == QLatin1String("blue.mpg"));
0237         REQUIRE(timeline->getClipPtr(cid1b)->clipName() == QLatin1String("blue.mpg"));
0238         REQUIRE(timeline->getClipPtr(cid2)->clipName() == QLatin1String("green.mpg"));
0239         REQUIRE(timeline->getClipPtr(cid2b)->clipName() == QLatin1String("green.mpg"));
0240         REQUIRE(timeline->getClipPtr(cid3)->clipName() == QLatin1String("red.mpg"));
0241         REQUIRE(timeline->getClipPtr(cid3b)->clipName() == QLatin1String("red.mpg"));
0242         REQUIRE(timeline->getClipPtr(cid4)->clipName() == QLatin1String("yellow.mpg"));
0243         REQUIRE(timeline->getClipPtr(cid4b)->clipName() == QLatin1String("yellow.mpg"));
0244         pCore->projectManager()->closeCurrentDocument(false, false);
0245     }
0246 }
0247 
0248 TEST_CASE("Non-BMP Unicode", "[NONBMP]")
0249 {
0250     auto binModel = pCore->projectItemModel();
0251     binModel->clean();
0252 
0253     // A Kdenlive bug (bugzilla bug 435768) caused characters outside the Basic
0254     // Multilingual Plane to be lost when the file is loaded. This string
0255     // contains the onigiri emoji which should survive a save+open round trip.
0256     // If Kdenlive drops the emoji, then the result is just "testtest" which can
0257     // be checked for.
0258 
0259     const QString emojiTestString = QString::fromUtf8("test\xF0\x9F\x8D\x99test");
0260     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0261 
0262     QTemporaryFile saveFile(QDir::temp().filePath("kdenlive_test_XXXXXX.kdenlive"));
0263     qDebug() << "Choosing temp file with template" << (QDir::temp().filePath("kdenlive_test_XXXXXX.kdenlive"));
0264     REQUIRE(saveFile.open());
0265     saveFile.close();
0266     qDebug() << "New temporary file:" << saveFile.fileName();
0267 
0268     SECTION("Save title with special chars")
0269     {
0270         // Create document
0271         KdenliveDoc document(undoStack);
0272         pCore->projectManager()->m_project = &document;
0273         QDateTime documentDate = QDateTime::currentDateTime();
0274         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0275         auto timeline = document.getTimeline(document.uuid());
0276         pCore->projectManager()->m_activeTimelineModel = timeline;
0277         pCore->projectManager()->testSetActiveDocument(&document, timeline);
0278         QDir dir = QDir::temp();
0279 
0280         // create a simple title with the non-BMP test string
0281         const QString titleXml =
0282             QString("<kdenlivetitle duration=\"150\" LC_NUMERIC=\"C\" width=\"1920\" height=\"1080\" out=\"149\">\n <item type=\"QGraphicsTextItem\" "
0283                     "z-index=\"0\">\n  <position x=\"777\" y=\"482\">\n   <transform>1,0,0,0,1,0,0,0,1</transform>\n  </position>\n  <content "
0284                     "shadow=\"0;#64000000;3;3;3\" font-underline=\"0\" box-height=\"138\" font-outline-color=\"0,0,0,255\" font=\"DejaVu Sans\" "
0285                     "letter-spacing=\"0\" font-pixel-size=\"120\" font-italic=\"0\" typewriter=\"0;2;1;0;0\" alignment=\"0\" font-weight=\"63\" "
0286                     "font-outline=\"3\" box-width=\"573.25\" font-color=\"252,233,79,255\">") +
0287             emojiTestString +
0288             QString("</content>\n </item>\n <startviewport rect=\"0,0,1920,1080\"/>\n <endviewport rect=\"0,0,1920,1080\"/>\n <background "
0289                     "color=\"0,0,0,0\"/>\n</kdenlivetitle>\n");
0290 
0291         QString binId2 = createTextProducer(pCore->getProjectProfile(), binModel, titleXml, emojiTestString, 150);
0292 
0293         TrackModel::construct(timeline, -1, -1, QString(), true);
0294         TrackModel::construct(timeline, -1, -1, QString(), true);
0295         int tid1 = timeline->getTrackIndexFromPosition(2);
0296 
0297         // Setup timeline audio drop info
0298         QMap<int, QString> audioInfo;
0299         audioInfo.insert(1, QStringLiteral("stream1"));
0300         timeline->m_binAudioTargets = audioInfo;
0301         timeline->m_videoTarget = tid1;
0302 
0303         pCore->projectManager()->testSaveFileAs(saveFile.fileName());
0304 
0305         // open the file and check that it contains emojiTestString
0306         QFile file(saveFile.fileName());
0307         REQUIRE(file.open(QIODevice::ReadOnly));
0308         QByteArray contents = file.readAll();
0309         if (contents.contains(emojiTestString.toUtf8())) {
0310             qDebug() << "File contains test string";
0311         } else {
0312             qDebug() << "File does not contain test string:" << contents;
0313         }
0314         REQUIRE(contents.contains(emojiTestString.toUtf8()));
0315 
0316         // try opening the file as a Kdenlivedoc and check that the title hasn't
0317         // lost the emoji
0318 
0319         QUrl openURL = QUrl::fromLocalFile(saveFile.fileName());
0320         QUndoGroup *undoGroup = new QUndoGroup();
0321         undoGroup->addStack(undoStack.get());
0322         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(),
0323             undoGroup, false, nullptr);
0324         REQUIRE(openResults.isSuccessful() == true);
0325 
0326         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0327         QDomDocument *newDoc = &openedDoc->m_document;
0328         auto producers = newDoc->elementsByTagName(QStringLiteral("producer"));
0329         QDomElement textTitle;
0330         for (int i = 0; i < producers.size(); i++) {
0331             auto kdenliveid = getProperty(producers.at(i).toElement(), QStringLiteral("kdenlive:id"));
0332             if (kdenliveid != nullptr && kdenliveid->text() == binId2) {
0333                 textTitle = producers.at(i).toElement();
0334                 break;
0335             }
0336         }
0337         auto clipname = getProperty(textTitle, QStringLiteral("kdenlive:clipname"));
0338         REQUIRE(clipname != nullptr);
0339         CHECK(clipname->text() == emojiTestString);
0340         auto xmldata = getProperty(textTitle, QStringLiteral("xmldata"));
0341         REQUIRE(xmldata != nullptr);
0342         CHECK(clipname->text().contains(emojiTestString));
0343         pCore->projectManager()->closeCurrentDocument(false, false);
0344     }
0345 
0346     SECTION("Save project and check profile")
0347     {
0348 
0349         // Create document
0350         pCore->setCurrentProfile(QStringLiteral("atsc_1080p_25"));
0351         KdenliveDoc document(undoStack);
0352 
0353         // We mock the project class so that the undoStack function returns our undoStack, and our mocked document
0354         pCore->projectManager()->m_project = &document;
0355         QDateTime documentDate = QDateTime::currentDateTime();
0356         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0357         auto timeline = document.getTimeline(document.uuid());
0358         pCore->projectManager()->testSetActiveDocument(&document, timeline);
0359 
0360         QDir dir = QDir::temp();
0361         int tid1 = timeline->getTrackIndexFromPosition(2);
0362 
0363         // Setup timeline audio drop info
0364         QMap<int, QString> audioInfo;
0365         audioInfo.insert(1, QStringLiteral("stream1"));
0366         timeline->m_binAudioTargets = audioInfo;
0367         timeline->m_videoTarget = tid1;
0368 
0369         pCore->projectManager()->testSaveFileAs(saveFile.fileName());
0370 
0371         // open the file and check that it contains the correct profile info
0372         QFile file(saveFile.fileName());
0373         REQUIRE(file.open(QIODevice::ReadOnly));
0374         QByteArray contents = file.readAll();
0375         QString contentCheck("<property name=\"kdenlive:docproperties.profile\">atsc_1080p_25</property>");
0376         if (contents.contains(contentCheck.toUtf8())) {
0377             qDebug() << "File contains test string";
0378         } else {
0379             qDebug() << "File does not contain test string:" << contents;
0380         }
0381         REQUIRE(contents.contains(contentCheck.toUtf8()));
0382         pCore->projectManager()->closeCurrentDocument(false, false);
0383     }
0384 }
0385 
0386 TEST_CASE("Opening Mix", "[OPENMIX]")
0387 {
0388     auto binModel = pCore->projectItemModel();
0389     binModel->clean();
0390 
0391     // Check that mixes (and reverse mixes) load correctly
0392 
0393     const QString emojiTestString = QString::fromUtf8("test\xF0\x9F\x8D\x99test");
0394 
0395     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0396 
0397     SECTION("Load file with a mix")
0398     {
0399         // We mock the project class so that the undoStack function returns our undoStack, and our mocked document
0400         QUrl openURL = QUrl::fromLocalFile(sourcesPath + "/dataset/test-mix.kdenlive");
0401 
0402         QUndoGroup *undoGroup = new QUndoGroup();
0403         undoGroup->addStack(undoStack.get());
0404         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0405         REQUIRE(openResults.isSuccessful() == true);
0406 
0407         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0408 
0409         pCore->projectManager()->m_project = openedDoc.get();
0410         const QUuid uuid = openedDoc->uuid();
0411         QDateTime documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0412         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0413         auto timeline = openedDoc->getTimeline(uuid);
0414         pCore->projectManager()->testSetActiveDocument(openedDoc.get(), timeline);
0415 
0416         REQUIRE(timeline->getTracksCount() == 4);
0417         int mixtrackId = timeline->getTrackIndexFromPosition(2);
0418         REQUIRE(timeline->getTrackById_const(mixtrackId)->mixCount() == 2);
0419         int mixtrackId2 = timeline->getTrackIndexFromPosition(3);
0420         REQUIRE(timeline->getTrackById_const(mixtrackId2)->mixCount() == 1);
0421 
0422         QDomDocument *newDoc = &openedDoc->m_document;
0423         auto producers = newDoc->elementsByTagName(QStringLiteral("producer"));
0424         pCore->projectManager()->closeCurrentDocument(false, false);
0425     }
0426 }
0427 
0428 TEST_CASE("Opening File With Keyframes", "[OPENKFRS]")
0429 {
0430     auto binModel = pCore->projectItemModel();
0431     binModel->clean();
0432     std::shared_ptr<DocUndoStack> undoStack = std::make_shared<DocUndoStack>(nullptr);
0433 
0434     SECTION("Open a file with Keyframes")
0435     {
0436         // Create new document
0437         QString path = sourcesPath + "/dataset/test-keyframes.kdenlive";
0438         QUrl openURL = QUrl::fromLocalFile(path);
0439 
0440         QUndoGroup *undoGroup = new QUndoGroup();
0441         undoGroup->addStack(undoStack.get());
0442         DocOpenResult openResults = KdenliveDoc::Open(openURL, QDir::temp().path(), undoGroup, false, nullptr);
0443         REQUIRE(openResults.isSuccessful() == true);
0444         std::unique_ptr<KdenliveDoc> openedDoc = openResults.getDocument();
0445 
0446         pCore->projectManager()->m_project = openedDoc.get();
0447         const QUuid uuid = openedDoc->uuid();
0448         QDateTime documentDate = QFileInfo(openURL.toLocalFile()).lastModified();
0449         pCore->projectManager()->updateTimeline(false, QString(), QString(), documentDate, 0);
0450         pCore->projectManager()->testSetActiveDocument(openedDoc.get());
0451         auto timeline = pCore->projectManager()->m_project->getTimeline(uuid);
0452 
0453         REQUIRE(timeline->checkConsistency());
0454         int tid1 = timeline->getTrackIndexFromPosition(0);
0455         int tid2 = timeline->getTrackIndexFromPosition(1);
0456         int tid3 = timeline->getTrackIndexFromPosition(2);
0457         int tid4 = timeline->getTrackIndexFromPosition(3);
0458         // Check we have audio and video tracks
0459         REQUIRE(timeline->isAudioTrack(tid1));
0460         REQUIRE(timeline->isAudioTrack(tid2));
0461         REQUIRE(timeline->isAudioTrack(tid3) == false);
0462         REQUIRE(timeline->isAudioTrack(tid4) == false);
0463         int cid1 = timeline->getClipByStartPosition(tid1, 0);
0464         int cid2 = timeline->getClipByStartPosition(tid2, 0);
0465         int cid3 = timeline->getClipByStartPosition(tid3, 0);
0466         int cid4 = timeline->getClipByStartPosition(tid4, 0);
0467         // Check we have our clips
0468         REQUIRE(cid1 == -1);
0469         REQUIRE(cid2 > -1);
0470         REQUIRE(cid3 > -1);
0471         REQUIRE(cid4 == -1);
0472         pCore->projectManager()->closeCurrentDocument(false, false);
0473     }
0474 }