File indexing completed on 2024-05-12 04:38:23

0001 /*
0002     SPDX-FileCopyrightText: 2021 Christoph Roick <chrisito@gmx.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "test_workingsets.h"
0008 
0009 #include "../core.h"
0010 #include "../documentcontroller.h"
0011 #include "../session.h"
0012 #include "../uicontroller.h"
0013 #include "../workingsetcontroller.h"
0014 #include "../workingsets/workingset.h"
0015 
0016 #include <sublime/area.h>
0017 #include <sublime/document.h>
0018 #include <sublime/view.h>
0019 
0020 #include <tests/autotestshell.h>
0021 #include <tests/testcore.h>
0022 
0023 #include <KParts/MainWindow>
0024 
0025 #include <QTest>
0026 
0027 #include <QLayout>
0028 #include <QMainWindow>
0029 #include <QMenuBar>
0030 #include <QSplitter>
0031 
0032 #include <algorithm>
0033 
0034 using namespace KDevelop;
0035 
0036 const QString setName = QStringLiteral("TestSet");
0037 const QString setName2 = QStringLiteral("TestSet2");
0038 const QString setName3 = QStringLiteral("TestSet3");
0039 const QString text = QStringLiteral("Test");
0040 
0041 void TestWorkingSetController::initTestCase()
0042 {
0043     AutoTestShell::init({{}});
0044     TestCore::initialize();
0045     m_workingSetCtrl = Core::self()->workingSetControllerInternal();
0046     auto uiController = Core::self()->uiControllerInternal();
0047     m_area = uiController->activeArea();
0048     m_area_debug = nullptr;
0049     m_documentCtrl = Core::self()->documentController();
0050     QVERIFY(m_mainWindow = uiController->activeMainWindow());
0051     auto areaDisplay = m_mainWindow->menuBar()->cornerWidget(Qt::TopRightCorner);
0052     // active working set + separator + closed working sets + tool button
0053     QCOMPARE(areaDisplay->layout()->count(), 4);
0054     // widget that contains the buttons of the currently closed working sets
0055     m_closedSets = areaDisplay->layout()->itemAt(2)->widget();
0056 }
0057 
0058 void TestWorkingSetController::init()
0059 {
0060     m_file.setFileTemplate(m_tempDir.path() + "/tmp_XXXXXX.txt");
0061     if(!m_file.open()) {
0062         QFAIL("Cannot create temp file");
0063     }
0064 }
0065 
0066 void TestWorkingSetController::cleanupTestCase()
0067 {
0068     m_mainWindow->close();
0069     TestCore::shutdown();
0070 }
0071 
0072 void TestWorkingSetController::restartSession()
0073 {
0074     // End session and store it for now
0075     Core::self()->activeSession()->setTemporary(false);
0076     cleanupTestCase();
0077     // Reload session and make it temporary again
0078     initTestCase();
0079     Core::self()->activeSession()->setTemporary(true);
0080 }
0081 
0082 
0083 void TestWorkingSetController::createWorkingSet()
0084 {
0085     // Create a persistent working set
0086     m_area->setWorkingSet(setName);
0087     const auto workingSets = m_workingSetCtrl->allWorkingSets();
0088     QCOMPARE(workingSets.size(), 1);
0089     const auto id = workingSets.first()->id();
0090     workingSets.first()->setPersistent(true);
0091     QVERIFY(workingSets.first()->isPersistent());
0092     // Open a document such that the working set is not empty
0093     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0094 
0095     // Create and activate a non-persistent working set
0096     m_area->setWorkingSet(setName3, false);
0097     QCOMPARE(m_workingSetCtrl->allWorkingSets().size(), 2);
0098     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0099 
0100     // Create and activate another non-persistent working set
0101     m_area->setWorkingSet(setName2, false);
0102     QCOMPARE(m_workingSetCtrl->allWorkingSets().size(), 3);
0103     const auto id2 = m_workingSetCtrl->workingSet(m_area->workingSet())->id();
0104     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0105 
0106     QTRY_COMPARE(m_closedSets->layout()->count(), 2); // working sets 1 + 3 (2 is active)
0107 
0108     restartSession();
0109 
0110     // Check if last non-persistent working set is active and persistent set exists
0111     QCOMPARE(m_workingSetCtrl->allWorkingSets().size(), 2);
0112     auto set = m_workingSetCtrl->workingSet(m_area->workingSet());
0113     QCOMPARE(set->id(), id2);
0114     QVERIFY(!set->isPersistent());
0115 
0116     // Activate persistent working set
0117     m_area->setWorkingSet(setName);
0118     QCOMPARE(m_workingSetCtrl->allWorkingSets().size(), 2);
0119     set = m_workingSetCtrl->workingSet(m_area->workingSet());
0120     QCOMPARE(set->id(), id);
0121     QVERIFY(set->isPersistent());
0122 
0123     QTRY_COMPARE(m_closedSets->layout()->count(), 1); // working set 2 (1 is active)
0124 }
0125 
0126 void TestWorkingSetController::deleteWorkingSet()
0127 {
0128     // Create a persistent working set
0129     m_area->setWorkingSet(setName2);
0130     auto set2 = m_workingSetCtrl->workingSet(m_area->workingSet());
0131     set2->setPersistent(true);
0132     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0133 
0134     // Create and activate another persistent working set
0135     m_area->setWorkingSet(setName);
0136     auto set = m_workingSetCtrl->workingSet(m_area->workingSet());
0137     set->setPersistent(true);
0138     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0139 
0140     QTRY_COMPARE(m_closedSets->layout()->count(), 1); // working set 2 (1 is active)
0141 
0142     // Delete the first set
0143     set2->deleteSet(false);
0144     // Try deleting the active set
0145     set->deleteSet(false);
0146 
0147     QCOMPARE(m_closedSets->layout()->count(), 0); // no closed working set
0148 
0149     restartSession();
0150 
0151     const auto sets = m_workingSetCtrl->allWorkingSets();
0152     QVERIFY(std::any_of(sets.constBegin(), sets.constEnd(), [&](WorkingSet* set){ return set->id() == setName; }));
0153     QVERIFY(std::none_of(sets.constBegin(), sets.constEnd(), [&](WorkingSet* set){ return set->id() == setName2; }));
0154 
0155     QCOMPARE(m_closedSets->layout()->count(), 0); // no closed working set
0156 }
0157 
0158 void TestWorkingSetController::switchArea()
0159 {
0160     // Create a persistent working set
0161     m_area->setWorkingSet(setName2);
0162     auto set2 = m_workingSetCtrl->workingSet(m_area->workingSet());
0163     set2->setPersistent(true);
0164     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0165 
0166     // Create and activate another persistent working set
0167     m_area->setWorkingSet(setName);
0168     auto set = m_workingSetCtrl->workingSet(m_area->workingSet());
0169     set->setPersistent(true);
0170     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0171 
0172     Core::self()->uiController()->switchToArea(QStringLiteral("debug"), IUiController::ThisWindow);
0173     m_area_debug = Core::self()->uiControllerInternal()->activeArea();
0174      // explicitly set the current working set, as in DebugController::addSession
0175     m_area_debug->setWorkingSet(setName, m_area->workingSetPersistent(), m_area);
0176 
0177     QTRY_COMPARE(m_closedSets->layout()->count(), 1); // working set 2
0178 
0179     m_area_debug->setWorkingSet(setName2);
0180     QTest::qSleep(1000);
0181     QCOMPARE(m_closedSets->layout()->count(), 1); // working set 1, BUG 375446
0182 
0183     Core::self()->uiController()->switchToArea(QStringLiteral("code"), IUiController::ThisWindow);
0184      // explicitly set the current working set, as in DebugController::debuggerStateChanged
0185     m_area->setWorkingSet(setName2, m_area_debug->workingSetPersistent(), m_area_debug);
0186     m_area->setWorkingSet(setName);
0187 
0188     QTRY_COMPARE(m_closedSets->layout()->count(), 1); // working set 2, BUG 375446
0189 }
0190 
0191 void TestWorkingSetController::restoreSplits()
0192 {
0193     // we need to show the window to calculate actual widget sizes
0194     m_mainWindow->show();
0195 
0196     // Create a persistent working set with 4 split views
0197     m_area->setWorkingSet(setName);
0198     auto set2 = m_workingSetCtrl->workingSet(m_area->workingSet());
0199     set2->setPersistent(true);
0200     auto doc = m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0201 
0202     // Split view
0203     auto view_bottom_left = dynamic_cast<Sublime::Document*>(doc)->createView();
0204     m_area->addView(view_bottom_left, m_area->activeView(), Qt::Vertical);
0205     auto view_top_right = dynamic_cast<Sublime::Document*>(doc)->createView();
0206     m_area->addView(view_top_right, m_area->activeView(), Qt::Horizontal);
0207     auto view_bottom_right = dynamic_cast<Sublime::Document*>(doc)->createView();
0208     m_area->addView(view_bottom_right, view_bottom_left, Qt::Horizontal);
0209 
0210     // required to arrange the view widgets in the window
0211     QApplication::processEvents();
0212 
0213     QSet<Sublime::AreaIndex*> indices;
0214     for (auto &view : m_area->views()) {
0215         indices.insert(m_area->indexOf(view));
0216     }
0217     QCOMPARE(indices.size(), 4); // number of view containers
0218 
0219     auto *splitter_bottom = qobject_cast<QSplitter*>(view_bottom_left->widget()
0220                                                          ->parentWidget()
0221                                                          ->parentWidget()   // view container
0222                                                          ->parentWidget()   // splitter containing a single container
0223                                                          ->parentWidget()); // splitter containing lower containers
0224     QVERIFY(splitter_bottom);
0225 
0226     QVERIFY(splitter_bottom->isVisible());
0227     // ensure the splitter handle is visible, which is esp. required for running the test with the offscreen QPA
0228     splitter_bottom->handle(0)->setVisible(true);
0229     QVERIFY(splitter_bottom->handle(0)->isVisible());
0230 
0231     QApplication::processEvents();
0232 
0233     splitter_bottom->setSizes({1, 1000});
0234     auto sizes_bottom = splitter_bottom->sizes();
0235     QVERIFY(sizes_bottom.at(0) < sizes_bottom.at(1));
0236 
0237     auto *splitter_mid = qobject_cast<QSplitter*>(splitter_bottom->parentWidget());
0238     QVERIFY(splitter_mid);
0239     splitter_mid->setSizes({1, 1000});
0240     auto sizes_mid = splitter_mid->sizes();
0241     QVERIFY(sizes_mid.at(0) < sizes_mid.at(1));
0242 
0243     QVERIFY(!qobject_cast<QSplitter*>(splitter_mid->parentWidget()));
0244 
0245     // Create and activate another persistent working set with a single view
0246     m_area->setWorkingSet(setName2);
0247     auto set = m_workingSetCtrl->workingSet(m_area->workingSet());
0248     set->setPersistent(true);
0249     m_documentCtrl->openDocument(QUrl::fromLocalFile(m_file.fileName()));
0250 
0251     indices.clear();
0252     for (auto &view : m_area->views()) {
0253         indices.insert(m_area->indexOf(view));
0254     }
0255     QCOMPARE(indices.size(), 1);
0256 
0257     m_area->setWorkingSet(setName);
0258 
0259     QApplication::processEvents();
0260 
0261     indices.clear();
0262     for (auto &view : m_area->views()) {
0263         indices.insert(m_area->indexOf(view));
0264     }
0265     QCOMPARE(indices.size(), 4);
0266     view_bottom_left = m_area->views().at(2);
0267 
0268     // check if the splitter sizes are restored
0269     splitter_bottom = qobject_cast<QSplitter*>(view_bottom_left->widget()
0270                                                    ->parentWidget()
0271                                                    ->parentWidget()   // view container
0272                                                    ->parentWidget()   // splitter containing a single container
0273                                                    ->parentWidget()); // splitter containing lower containers
0274     QVERIFY(splitter_bottom);
0275     QCOMPARE(splitter_bottom->sizes(), sizes_bottom);
0276 
0277     splitter_mid = qobject_cast<QSplitter*>(splitter_bottom->parentWidget());
0278     QVERIFY(splitter_mid);
0279     QCOMPARE(splitter_mid->sizes(), sizes_mid);
0280 }
0281 
0282 QTEST_MAIN(TestWorkingSetController)
0283 
0284 #include "moc_test_workingsets.cpp"