forked from qt-creator/qt-creator
AutoTest: Guard against concurrent access
While parsing for Qt Quick Tests it may happen that an internal map is accessed concurrently by different threads. Guard against this. Minor drive-by optimizations. Change-Id: Ic3b62c27feddb9a5ac5588a6c9643fc0e623ce19 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -261,7 +261,10 @@ bool QuickTestParser::handleQtQuickTest(QPromise<TestParseResultPtr> &promise,
|
|||||||
return false;
|
return false;
|
||||||
const FilePath cppFileName = document->filePath();
|
const FilePath cppFileName = document->filePath();
|
||||||
const FilePath proFile = FilePath::fromString(ppList.at(0)->projectFile);
|
const FilePath proFile = FilePath::fromString(ppList.at(0)->projectFile);
|
||||||
|
{
|
||||||
|
QWriteLocker lock(&m_parseLock);
|
||||||
m_mainCppFiles.insert(cppFileName, proFile);
|
m_mainCppFiles.insert(cppFileName, proFile);
|
||||||
|
}
|
||||||
const FilePath srcDir = FilePath::fromString(quickTestSrcDir(cppFileName));
|
const FilePath srcDir = FilePath::fromString(quickTestSrcDir(cppFileName));
|
||||||
if (srcDir.isEmpty())
|
if (srcDir.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
@@ -340,13 +343,13 @@ QuickTestParser::QuickTestParser(ITestFramework *framework)
|
|||||||
void QuickTestParser::init(const QSet<FilePath> &filesToParse, bool fullParse)
|
void QuickTestParser::init(const QSet<FilePath> &filesToParse, bool fullParse)
|
||||||
{
|
{
|
||||||
m_qmlSnapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot();
|
m_qmlSnapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot();
|
||||||
|
QWriteLocker lock(&m_parseLock); // should not be necessary
|
||||||
if (!fullParse) {
|
if (!fullParse) {
|
||||||
// in a full parse we get the correct entry points by the respective main
|
// in a full parse we get the correct entry points by the respective main
|
||||||
m_proFilesForQmlFiles = QuickTestUtils::proFilesForQmlFiles(framework(), filesToParse);
|
m_proFilesForQmlFiles = QuickTestUtils::proFilesForQmlFiles(framework(), filesToParse);
|
||||||
// get rid of cached main cpp files that are going to get processed anyhow
|
// get rid of cached main cpp files that are going to get processed anyhow
|
||||||
for (const FilePath &file : filesToParse) {
|
for (const FilePath &file : filesToParse) {
|
||||||
if (m_mainCppFiles.contains(file)) {
|
if (m_mainCppFiles.remove(file) == 1) {
|
||||||
m_mainCppFiles.remove(file);
|
|
||||||
if (m_mainCppFiles.isEmpty())
|
if (m_mainCppFiles.isEmpty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -355,6 +358,7 @@ void QuickTestParser::init(const QSet<FilePath> &filesToParse, bool fullParse)
|
|||||||
// get rid of all cached main cpp files
|
// get rid of all cached main cpp files
|
||||||
m_mainCppFiles.clear();
|
m_mainCppFiles.clear();
|
||||||
}
|
}
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
m_checkForDerivedTests = theQtTestFramework().quickCheckForDerivedTests();
|
m_checkForDerivedTests = theQtTestFramework().quickCheckForDerivedTests();
|
||||||
|
|
||||||
@@ -399,9 +403,10 @@ bool QuickTestParser::processDocument(QPromise<TestParseResultPtr> &promise,
|
|||||||
return handleQtQuickTest(promise, cppdoc, framework());
|
return handleQtQuickTest(promise, cppdoc, framework());
|
||||||
}
|
}
|
||||||
|
|
||||||
FilePath QuickTestParser::projectFileForMainCppFile(const FilePath &fileName) const
|
FilePath QuickTestParser::projectFileForMainCppFile(const FilePath &fileName)
|
||||||
{
|
{
|
||||||
return m_mainCppFiles.contains(fileName) ? m_mainCppFiles.value(fileName) : FilePath();
|
QReadLocker lock(&m_parseLock);
|
||||||
|
return m_mainCppFiles.value(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Autotest::Internal
|
} // namespace Autotest::Internal
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <qmljs/qmljsdocument.h>
|
#include <qmljs/qmljsdocument.h>
|
||||||
|
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
namespace Autotest {
|
namespace Autotest {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -28,7 +29,7 @@ public:
|
|||||||
void release() override;
|
void release() override;
|
||||||
bool processDocument(QPromise<TestParseResultPtr> &promise,
|
bool processDocument(QPromise<TestParseResultPtr> &promise,
|
||||||
const Utils::FilePath &fileName) override;
|
const Utils::FilePath &fileName) override;
|
||||||
Utils::FilePath projectFileForMainCppFile(const Utils::FilePath &fileName) const;
|
Utils::FilePath projectFileForMainCppFile(const Utils::FilePath &fileName);
|
||||||
QStringList supportedExtensions() const override { return {"qml"}; };
|
QStringList supportedExtensions() const override { return {"qml"}; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -45,6 +46,7 @@ private:
|
|||||||
QMap<QString, QMap<QString, QDateTime> > m_watchedFiles;
|
QMap<QString, QMap<QString, QDateTime> > m_watchedFiles;
|
||||||
QMap<Utils::FilePath, Utils::FilePath> m_mainCppFiles;
|
QMap<Utils::FilePath, Utils::FilePath> m_mainCppFiles;
|
||||||
QSet<Utils::FilePath> m_prefilteredFiles;
|
QSet<Utils::FilePath> m_prefilteredFiles;
|
||||||
|
QReadWriteLock m_parseLock; // guard for m_mainCppFiles
|
||||||
bool m_checkForDerivedTests = false;
|
bool m_checkForDerivedTests = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user