CppEditor/CppTools: Tests: Fix potential race condition

...when updating the code model.

Change-Id: Ifc55b7d0bb795b9cfd72465990991bc2cc907846
Reviewed-by: Christian Stenger <christian.stenger@digia.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
Nikolai Kosjar
2013-12-11 14:10:09 +01:00
committed by Erik Verbruggen
parent dad0140134
commit 9b41023b68
10 changed files with 67 additions and 90 deletions

View File

@@ -86,16 +86,14 @@ TestCase::TestCase(const QByteArray &input)
Utils::FileSaver srcSaver(fileName); Utils::FileSaver srcSaver(fileName);
srcSaver.write(originalText); srcSaver.write(originalText);
srcSaver.finalize(); srcSaver.finalize();
CppTools::CppModelManagerInterface::instance()->updateSourceFiles(QStringList()<<fileName);
// Wait for the parser in the future to give us the document // Update Code Model
while (true) { CppTools::CppModelManagerInterface *mmi = CppTools::CppModelManagerInterface::instance();
Snapshot s = CppTools::CppModelManagerInterface::instance()->snapshot(); mmi->updateSourceFiles(QStringList(fileName)).waitForFinished();
if (s.contains(fileName)) QCoreApplication::processEvents();
break; QVERIFY(mmi->snapshot().contains(fileName));
QCoreApplication::processEvents();
}
// Open Editor
editor = dynamic_cast<CPPEditor *>(EditorManager::openEditor(fileName)); editor = dynamic_cast<CPPEditor *>(EditorManager::openEditor(fileName));
QVERIFY(editor); QVERIFY(editor);
editorWidget = dynamic_cast<CPPEditorWidget *>(editor->editorWidget()); editorWidget = dynamic_cast<CPPEditorWidget *>(editor->editorWidget());

View File

@@ -67,20 +67,12 @@ public:
} }
// Update Code Model // Update Code Model
m_cmm->updateSourceFiles(filePaths); m_cmm->updateSourceFiles(filePaths).waitForFinished();
QCoreApplication::processEvents();
// Wait for the parser in the future to give us the document const Snapshot snapshot = m_cmm->snapshot();
QStringList filePathsNotYetInSnapshot(filePaths); QVERIFY(!snapshot.isEmpty());
forever { foreach (const QString &filePath, filePaths)
const Snapshot snapshot = m_cmm->snapshot(); QVERIFY(snapshot.contains(filePath));
foreach (const QString &filePath, filePathsNotYetInSnapshot) {
if (snapshot.contains(filePath))
filePathsNotYetInSnapshot.removeOne(filePath);
}
if (filePathsNotYetInSnapshot.isEmpty())
break;
QCoreApplication::processEvents();
}
} }
~TestCase() ~TestCase()

View File

@@ -209,20 +209,12 @@ void TestCase::init(const QStringList &includePaths)
QStringList filePaths; QStringList filePaths;
foreach (const TestDocumentPtr &testFile, testFiles) foreach (const TestDocumentPtr &testFile, testFiles)
filePaths << testFile->filePath(); filePaths << testFile->filePath();
cmm->updateSourceFiles(filePaths); cmm->updateSourceFiles(filePaths).waitForFinished();
QCoreApplication::processEvents();
// Wait for the parser in the future to give us the document const Snapshot snapshot = cmm->snapshot();
QStringList filePathsNotYetInSnapshot(filePaths); QVERIFY(!snapshot.isEmpty());
forever { foreach (const QString &filePath, filePaths)
Snapshot snapshot = cmm->snapshot(); QVERIFY(snapshot.contains(filePath));
foreach (const QString &filePath, filePathsNotYetInSnapshot) {
if (snapshot.contains(filePath))
filePathsNotYetInSnapshot.removeOne(filePath);
}
if (filePathsNotYetInSnapshot.isEmpty())
break;
QCoreApplication::processEvents();
}
// Open Files // Open Files
foreach (TestDocumentPtr testFile, testFiles) { foreach (TestDocumentPtr testFile, testFiles) {

View File

@@ -309,21 +309,13 @@ void TestCase::init()
QStringList filePaths; QStringList filePaths;
foreach (const TestDocumentPtr &testFile, m_testFiles) foreach (const TestDocumentPtr &testFile, m_testFiles)
filePaths << testFile->filePath(); filePaths << testFile->filePath();
CppTools::CppModelManagerInterface::instance()->updateSourceFiles(filePaths); CppModelManagerInterface *mmi = CppTools::CppModelManagerInterface::instance();
mmi->updateSourceFiles(filePaths).waitForFinished();
// Wait for the indexer to process all files. QCoreApplication::processEvents();
// All these files are "Fast Checked", that is the function bodies are not processed. const Snapshot snapshot = mmi->snapshot();
QStringList filePathsNotYetInSnapshot(filePaths); QVERIFY(!snapshot.isEmpty());
forever { foreach (const QString &filePath, filePaths)
Snapshot snapshot = CppTools::CppModelManagerInterface::instance()->snapshot(); QVERIFY(snapshot.contains(filePath));
foreach (const QString &filePath, filePathsNotYetInSnapshot) {
if (snapshot.contains(filePath))
filePathsNotYetInSnapshot.removeOne(filePath);
}
if (filePathsNotYetInSnapshot.isEmpty())
break;
QCoreApplication::processEvents();
}
// Open Files // Open Files
foreach (TestDocumentPtr testFile, m_testFiles) { foreach (TestDocumentPtr testFile, m_testFiles) {

View File

@@ -82,8 +82,8 @@ private:
virtual void doBeforeLocatorRun() virtual void doBeforeLocatorRun()
{ {
m_modelManager->updateSourceFiles(QStringList() << m_fileName).waitForFinished(); m_modelManager->updateSourceFiles(QStringList() << m_fileName).waitForFinished();
QVERIFY(m_modelManager->snapshot().contains(m_fileName));
QCoreApplication::processEvents(); QCoreApplication::processEvents();
QVERIFY(m_modelManager->snapshot().contains(m_fileName));
} }
virtual void doAfterLocatorRun() virtual void doAfterLocatorRun()

View File

@@ -200,6 +200,15 @@ private:
const QString &m_filePath; const QString &m_filePath;
}; };
static QStringList updateProjectInfo(CppModelManager *modelManager, ModelManagerTestHelper *helper,
const ProjectInfo &projectInfo)
{
helper->resetRefreshedSourceFiles();
modelManager->updateProjectInfo(projectInfo).waitForFinished();
QCoreApplication::processEvents();
return helper->waitForRefreshedSourceFiles();
}
} // anonymous namespace } // anonymous namespace
/// Check: The preprocessor cleans include and framework paths. /// Check: The preprocessor cleans include and framework paths.
@@ -304,10 +313,8 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
part->includePaths = QStringList() << testDataDir.includeDir(false); part->includePaths = QStringList() << testDataDir.includeDir(false);
part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
pi.appendProjectPart(part); pi.appendProjectPart(part);
mm->updateProjectInfo(pi);
QStringList refreshedFiles = helper.waitForRefreshedSourceFiles();
QStringList refreshedFiles = updateProjectInfo(mm, &helper, pi);
QCOMPARE(refreshedFiles.size(), 1); QCOMPARE(refreshedFiles.size(), 1);
QVERIFY(refreshedFiles.contains(testCpp)); QVERIFY(refreshedFiles.contains(testCpp));
CPlusPlus::Snapshot snapshot = mm->snapshot(); CPlusPlus::Snapshot snapshot = mm->snapshot();
@@ -323,9 +330,8 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
part->projectDefines = QByteArray("#define TEST_DEFINE 1\n"); part->projectDefines = QByteArray("#define TEST_DEFINE 1\n");
pi.clearProjectParts(); pi.clearProjectParts();
pi.appendProjectPart(part); pi.appendProjectPart(part);
mm->updateProjectInfo(pi);
refreshedFiles = helper.waitForRefreshedSourceFiles(); refreshedFiles = updateProjectInfo(mm, &helper, pi);
QCOMPARE(refreshedFiles.size(), 1); QCOMPARE(refreshedFiles.size(), 1);
QVERIFY(refreshedFiles.contains(testCpp)); QVERIFY(refreshedFiles.contains(testCpp));
@@ -385,11 +391,9 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times()
part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource)); part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
pi.appendProjectPart(part); pi.appendProjectPart(part);
mm->updateProjectInfo(pi); refreshedFiles = updateProjectInfo(mm, &helper, pi);
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.size(), 3); QCOMPARE(refreshedFiles.size(), 3);
QVERIFY(refreshedFiles.contains(testHeader1)); QVERIFY(refreshedFiles.contains(testHeader1));
QVERIFY(refreshedFiles.contains(testHeader2)); QVERIFY(refreshedFiles.contains(testHeader2));
QVERIFY(refreshedFiles.contains(testCpp)); QVERIFY(refreshedFiles.contains(testCpp));
@@ -432,8 +436,10 @@ void CppToolsPlugin::test_modelmanager_refresh_test_for_changes()
pi.appendProjectPart(part); pi.appendProjectPart(part);
// Reindexing triggers a reparsing thread // Reindexing triggers a reparsing thread
helper.resetRefreshedSourceFiles();
QFuture<void> firstFuture = mm->updateProjectInfo(pi); QFuture<void> firstFuture = mm->updateProjectInfo(pi);
QVERIFY(firstFuture.isStarted() || firstFuture.isRunning()); QVERIFY(firstFuture.isStarted() || firstFuture.isRunning());
firstFuture.waitForFinished();
const QStringList refreshedFiles = helper.waitForRefreshedSourceFiles(); const QStringList refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.size(), 1); QCOMPARE(refreshedFiles.size(), 1);
QVERIFY(refreshedFiles.contains(testCpp)); QVERIFY(refreshedFiles.contains(testCpp));
@@ -470,8 +476,7 @@ void CppToolsPlugin::test_modelmanager_refresh_added_and_purge_removed()
CPlusPlus::Snapshot snapshot; CPlusPlus::Snapshot snapshot;
QStringList refreshedFiles; QStringList refreshedFiles;
mm->updateProjectInfo(pi); refreshedFiles = updateProjectInfo(mm, &helper, pi);
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.size(), 2); QCOMPARE(refreshedFiles.size(), 2);
QVERIFY(refreshedFiles.contains(testHeader1)); QVERIFY(refreshedFiles.contains(testHeader1));
@@ -490,8 +495,7 @@ void CppToolsPlugin::test_modelmanager_refresh_added_and_purge_removed()
newPart->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader)); newPart->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader));
pi.appendProjectPart(newPart); pi.appendProjectPart(newPart);
mm->updateProjectInfo(pi); refreshedFiles = updateProjectInfo(mm, &helper, pi);
refreshedFiles = helper.waitForRefreshedSourceFiles();
// Only the added project file was reparsed // Only the added project file was reparsed
QCOMPARE(refreshedFiles.size(), 1); QCOMPARE(refreshedFiles.size(), 1);
@@ -530,8 +534,7 @@ void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_
CPlusPlus::Snapshot snapshot; CPlusPlus::Snapshot snapshot;
QStringList refreshedFiles; QStringList refreshedFiles;
mm->updateProjectInfo(pi); refreshedFiles = updateProjectInfo(mm, &helper, pi);
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.size(), initialProjectFiles.size()); QCOMPARE(refreshedFiles.size(), initialProjectFiles.size());
snapshot = mm->snapshot(); snapshot = mm->snapshot();
@@ -560,8 +563,7 @@ void CppToolsPlugin::test_modelmanager_refresh_timeStampModified_if_sourcefiles_
pi.clearProjectParts(); pi.clearProjectParts();
pi.appendProjectPart(part); pi.appendProjectPart(part);
mm->updateProjectInfo(pi); refreshedFiles = updateProjectInfo(mm, &helper, pi);
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.size(), finalProjectFiles.size()); QCOMPARE(refreshedFiles.size(), finalProjectFiles.size());
snapshot = mm->snapshot(); snapshot = mm->snapshot();
@@ -618,8 +620,7 @@ void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects()
<< _("foo.cpp") << _("foo.cpp")
<< _("main.cpp")); << _("main.cpp"));
mm->updateProjectInfo(project1.projectInfo); refreshedFiles = updateProjectInfo(mm, &helper, project1.projectInfo);
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.toSet(), project1.projectFiles.toSet()); QCOMPARE(refreshedFiles.toSet(), project1.projectFiles.toSet());
const int snapshotSizeAfterProject1 = mm->snapshot().size(); const int snapshotSizeAfterProject1 = mm->snapshot().size();
@@ -633,8 +634,7 @@ void CppToolsPlugin::test_modelmanager_snapshot_after_two_projects()
<< _("bar.cpp") << _("bar.cpp")
<< _("main.cpp")); << _("main.cpp"));
mm->updateProjectInfo(project2.projectInfo); refreshedFiles = updateProjectInfo(mm, &helper, project2.projectInfo);
refreshedFiles = helper.waitForRefreshedSourceFiles();
QCOMPARE(refreshedFiles.toSet(), project2.projectFiles.toSet()); QCOMPARE(refreshedFiles.toSet(), project2.projectFiles.toSet());
const int snapshotSizeAfterProject2 = mm->snapshot().size(); const int snapshotSizeAfterProject2 = mm->snapshot().size();
@@ -710,6 +710,7 @@ void CppToolsPlugin::test_modelmanager_gc_if_last_cppeditor_closed()
const QString file = testDataDirectory.file(_("main.cpp")); const QString file = testDataDirectory.file(_("main.cpp"));
CppModelManager *mm = CppModelManager::instance(); CppModelManager *mm = CppModelManager::instance();
helper.resetRefreshedSourceFiles();
// Open a file in the editor // Open a file in the editor
QCOMPARE(Core::EditorManager::documentModel()->openedDocuments().size(), 0); QCOMPARE(Core::EditorManager::documentModel()->openedDocuments().size(), 0);
@@ -740,6 +741,7 @@ void CppToolsPlugin::test_modelmanager_dont_gc_opened_files()
const QString file = testDataDirectory.file(_("main.cpp")); const QString file = testDataDirectory.file(_("main.cpp"));
CppModelManager *mm = CppModelManager::instance(); CppModelManager *mm = CppModelManager::instance();
helper.resetRefreshedSourceFiles();
// Open a file in the editor // Open a file in the editor
QCOMPARE(Core::EditorManager::documentModel()->openedDocuments().size(), 0); QCOMPARE(Core::EditorManager::documentModel()->openedDocuments().size(), 0);
@@ -750,6 +752,7 @@ void CppToolsPlugin::test_modelmanager_dont_gc_opened_files()
// Wait until the file is refreshed and check whether it is in the working copy // Wait until the file is refreshed and check whether it is in the working copy
helper.waitForRefreshedSourceFiles(); helper.waitForRefreshedSourceFiles();
QVERIFY(mm->workingCopy().contains(file)); QVERIFY(mm->workingCopy().contains(file));
// Run the garbage collector // Run the garbage collector
@@ -825,10 +828,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
pi.appendProjectPart(part1); pi.appendProjectPart(part1);
pi.appendProjectPart(part2); pi.appendProjectPart(part2);
mm->updateProjectInfo(pi); updateProjectInfo(mm, &helper, pi);
helper.waitForRefreshedSourceFiles();
QCOMPARE(mm->snapshot().size(), 4); QCOMPARE(mm->snapshot().size(), 4);
// Open a file in the editor // Open a file in the editor
@@ -897,10 +897,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project_pch()
pi.appendProjectPart(part1); pi.appendProjectPart(part1);
pi.appendProjectPart(part2); pi.appendProjectPart(part2);
mm->updateProjectInfo(pi); updateProjectInfo(mm, &helper, pi);
helper.waitForRefreshedSourceFiles();
QCOMPARE(mm->snapshot().size(), 4); QCOMPARE(mm->snapshot().size(), 4);
// Open a file in the editor // Open a file in the editor
@@ -968,9 +965,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_editor()
pi.appendProjectPart(part1); pi.appendProjectPart(part1);
pi.appendProjectPart(part2); pi.appendProjectPart(part2);
mm->updateProjectInfo(pi); updateProjectInfo(mm, &helper, pi);
helper.waitForRefreshedSourceFiles();
QCOMPARE(mm->snapshot().size(), 4); QCOMPARE(mm->snapshot().size(), 4);

View File

@@ -103,10 +103,14 @@ ModelManagerTestHelper::Project *ModelManagerTestHelper::createProject(const QSt
return tp; return tp;
} }
void ModelManagerTestHelper::resetRefreshedSourceFiles()
{
m_lastRefreshedSourceFiles.clear();
m_refreshHappened = false;
}
QStringList ModelManagerTestHelper::waitForRefreshedSourceFiles() QStringList ModelManagerTestHelper::waitForRefreshedSourceFiles()
{ {
m_refreshHappened = false;
while (!m_refreshHappened) while (!m_refreshHappened)
QCoreApplication::processEvents(); QCoreApplication::processEvents();

View File

@@ -80,6 +80,7 @@ public:
Project *createProject(const QString &name); Project *createProject(const QString &name);
void resetRefreshedSourceFiles();
QStringList waitForRefreshedSourceFiles(); QStringList waitForRefreshedSourceFiles();
void waitForFinishedGc(); void waitForFinishedGc();

View File

@@ -101,12 +101,12 @@ public:
{ {
QVERIFY(m_indexingSupportToUse); QVERIFY(m_indexingSupportToUse);
QVERIFY(m_modelManager->snapshot().isEmpty()); QVERIFY(m_modelManager->snapshot().isEmpty());
m_modelManager->updateSourceFiles(QStringList() << m_testFile).waitForFinished(); m_modelManager->updateSourceFiles(QStringList(m_testFile)).waitForFinished();
QCoreApplication::processEvents();
QVERIFY(m_modelManager->snapshot().contains(m_testFile)); QVERIFY(m_modelManager->snapshot().contains(m_testFile));
m_indexingSupportToRestore = m_modelManager->indexingSupport(); m_indexingSupportToRestore = m_modelManager->indexingSupport();
m_modelManager->setIndexingSupport(m_indexingSupportToUse); m_modelManager->setIndexingSupport(m_indexingSupportToUse);
QCoreApplication::processEvents();
} }
ResultDataList run(const SymbolSearcher::Parameters &searchParameters) const ResultDataList run(const SymbolSearcher::Parameters &searchParameters) const

View File

@@ -127,10 +127,13 @@ public:
// Parse files // Parse files
m_modelManager->updateSourceFiles(filePaths).waitForFinished(); m_modelManager->updateSourceFiles(filePaths).waitForFinished();
QCoreApplication::processEvents();
// Get class for which to generate the hierarchy
const Snapshot snapshot = m_modelManager->snapshot(); const Snapshot snapshot = m_modelManager->snapshot();
QVERIFY(!snapshot.isEmpty()); QVERIFY(!snapshot.isEmpty());
foreach (const QString &filePath, filePaths)
QVERIFY(snapshot.contains(filePath));
// Get class for which to generate the hierarchy
const Document::Ptr firstDocument = snapshot.document(filePaths.first()); const Document::Ptr firstDocument = snapshot.document(filePaths.first());
Class *clazz = FindFirstClassInDocument()(firstDocument); Class *clazz = FindFirstClassInDocument()(firstDocument);
QVERIFY(clazz); QVERIFY(clazz);