diff --git a/bin/qtcreator.sh b/bin/qtcreator.sh index aca30f5b9ec..454224c26ee 100755 --- a/bin/qtcreator.sh +++ b/bin/qtcreator.sh @@ -1,5 +1,9 @@ #! /bin/sh +# Use this script if you add paths to LD_LIBRARY_PATH +# that contain libraries that conflict with the +# libraries that Qt Creator depends on. + makeAbsolute() { case $1 in /*) @@ -30,6 +34,12 @@ fi bindir=`dirname "$me"` libdir=`cd "$bindir/../lib" ; pwd` -LD_LIBRARY_PATH=$libdir:$libdir/qtcreator${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} +# Add path to deployed Qt libraries in package +qtlibdir=$libdir/Qt/lib +if test -d "$qtlibdir"; then + qtlibpath=:$qtlibdir +fi +# Add Qt Creator library path +LD_LIBRARY_PATH=$libdir:$libdir/qtcreator$qtlibpath${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} export LD_LIBRARY_PATH exec "$bindir/qtcreator" ${1+"$@"} diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index 7f085417616..5820647dca8 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -648,14 +648,16 @@ const QtInfo &QtInfo::get(const SymbolGroupValueContext &ctx) std::string moduleName; std::string::size_type exclPos = std::string::npos; std::string::size_type libPos = std::string::npos; + std::string::size_type qtPos = std::string::npos; const StringList &modules = SymbolGroupValue::getAllModuleNames(ctx); for (StringListConstIt module = modules.begin(), total = modules.end(); module != total; ++module) { moduleName = *module; - if (moduleName.find("Qt") != std::string::npos) { + qtPos = moduleName.find("Qt"); + if (qtPos != std::string::npos) { libPos = moduleName.find("Core"); - if (libPos != std::string::npos) + if (libPos != std::string::npos && (libPos - qtPos) < 4) break; } } diff --git a/src/libs/utils/process_stub_win.c b/src/libs/utils/process_stub_win.c index ca359e88f10..5e634ad9c41 100644 --- a/src/libs/utils/process_stub_win.c +++ b/src/libs/utils/process_stub_win.c @@ -214,9 +214,11 @@ int main() if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) systemError("Wait for debugee failed, error %d\n"); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - free(env); + + /* Don't close the process/thread handles, so that the kernel doesn't free + the resources before ConsoleProcess is able to obtain handles to them + - this would be a problem if the child process exits very quickly. */ doExit(0); + return 0; } diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 4517bd8e9f5..cdf5922e424 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -326,8 +326,6 @@ CppModelManager::CppModelManager(QObject *parent) this, SLOT(onAboutToRemoveProject(ProjectExplorer::Project*))); connect(sessionManager, SIGNAL(aboutToLoadSession(QString)), this, SLOT(onAboutToLoadSession())); - connect(sessionManager, SIGNAL(aboutToUnloadSession(QString)), - this, SLOT(onAboutToUnloadSession())); connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, this, &CppModelManager::onCurrentEditorChanged); @@ -1021,17 +1019,6 @@ void CppModelManager::onAboutToLoadSession() GC(); } -void CppModelManager::onAboutToUnloadSession() -{ - Core::ProgressManager::cancelTasks(CppTools::Constants::TASK_INDEX); - do { - QMutexLocker locker(&d->m_projectMutex); - d->m_projectToProjectsInfo.clear(); - recalculateProjectPartMappings(); - d->m_dirty = true; - } while (0); -} - void CppModelManager::renameIncludes(const QString &oldFileName, const QString &newFileName) { if (oldFileName.isEmpty() || newFileName.isEmpty()) @@ -1063,6 +1050,7 @@ void CppModelManager::renameIncludes(const QString &oldFileName, const QString & void CppModelManager::onCoreAboutToClose() { + Core::ProgressManager::cancelTasks(CppTools::Constants::TASK_INDEX); d->m_enableGC = false; } diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 27486045f68..41ec74ee670 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -195,7 +195,6 @@ private slots: // This should be executed in the GUI thread. friend class Tests::ModelManagerTestHelper; void onAboutToLoadSession(); - void onAboutToUnloadSession(); void renameIncludes(const QString &oldFileName, const QString &newFileName); void onProjectAdded(ProjectExplorer::Project *project); void onAboutToRemoveProject(ProjectExplorer::Project *project); diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index fcaaeebf579..0eeb8ee032d 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -327,7 +327,7 @@ void SessionManager::setActiveBuildConfiguration(Target *target, BuildConfigurat if (otherProject == target->project()) continue; Target *otherTarget = otherProject->activeTarget(); - if (otherTarget->kit()->id() != kitId) + if (!otherTarget || otherTarget->kit()->id() != kitId) continue; foreach (BuildConfiguration *otherBc, otherTarget->buildConfigurations()) { @@ -355,7 +355,7 @@ void SessionManager::setActiveDeployConfiguration(Target *target, DeployConfigur if (otherProject == target->project()) continue; Target *otherTarget = otherProject->activeTarget(); - if (otherTarget->kit()->id() != kitId) + if (!otherTarget || otherTarget->kit()->id() != kitId) continue; foreach (DeployConfiguration *otherDc, otherTarget->deployConfigurations()) { diff --git a/tests/system/objects.map b/tests/system/objects.map index 49b2b820535..a10ac7417b8 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -146,6 +146,7 @@ :Qt Creator.scrollArea_QScrollArea {type='ProjectExplorer::PanelsWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator.splitter_QSplitter {name='splitter' type='QSplitter' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton {occurrence='3' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} +:Qt Creator_BinEditor::BinEditorWidget {type='BinEditor::BinEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Bookmarks_TreeView {type='TreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_CloseButton {type='CloseButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_CompileOutput_Core::Internal::OutputPaneToggleButton {occurrence='4' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} diff --git a/tests/system/shared/clang.py b/tests/system/shared/clang.py index 42f1a08e722..3ae8854d0b6 100644 --- a/tests/system/shared/clang.py +++ b/tests/system/shared/clang.py @@ -37,6 +37,7 @@ def startCreatorTryingClang(): except: # ClangCodeModel plugin has not been built - start without it test.warning("ClangCodeModel plugin not available - performing test without.") + overrideStartApplication() startApplication("qtcreator" + SettingsPath) return False diff --git a/tests/system/shared/editor_utils.py b/tests/system/shared/editor_utils.py index 42b1aae3f0d..d9d2ac4fb38 100644 --- a/tests/system/shared/editor_utils.py +++ b/tests/system/shared/editor_utils.py @@ -261,6 +261,7 @@ def getEditorForFileSuffix(curFile, treeViewSyntax=False): proEditorSuffixes = ["pro", "pri", "prf"] glslEditorSuffixes= ["frag", "vert", "fsh", "vsh", "glsl", "shader", "gsh"] pytEditorSuffixes = ["py", "pyw", "wsgi"] + binEditorSuffixes = ["bin"] suffix = __getFileSuffix__(curFile) expected = os.path.basename(curFile) if treeViewSyntax: @@ -276,6 +277,8 @@ def getEditorForFileSuffix(curFile, treeViewSyntax=False): editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") elif suffix in proEditorSuffixes or suffix in glslEditorSuffixes or suffix in pytEditorSuffixes: editor = waitForObject(":Qt Creator_TextEditor::TextEditorWidget") + elif suffix in binEditorSuffixes: + editor = waitForObject(":Qt Creator_BinEditor::BinEditorWidget") else: test.log("Trying TextEditorWidget (file suffix: %s)" % suffix) try: diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py index 91b57c3dfb3..22170969197 100644 --- a/tests/system/shared/project.py +++ b/tests/system/shared/project.py @@ -794,10 +794,15 @@ def addCPlusPlusFileToCurrentProject(name, template, forceOverwrite=False, addTo test.compare(str(waitForObject("{name='HdrFileName' type='QLineEdit' visible='1'}").text), expectedHeaderName) clickButton(waitForObject(":Next_QPushButton")) - fileExistedBefore = os.path.exists(os.path.join(basePath, name)) + fileExistedBefore = False + if template == "C++ Class": + fileExistedBefore = (os.path.exists(os.path.join(basePath, name.lower() + ".cpp")) + or os.path.exists(os.path.join(basePath, name.lower() + ".h"))) + else: + fileExistedBefore = os.path.exists(os.path.join(basePath, name)) __createProjectHandleLastPage__(expectedFiles, addToVersionControl=addToVCS) if (fileExistedBefore): - overwriteDialog = "{type='Core::Internal::PromptOverwriteDialog' unnamed='1' visible='1'}" + overwriteDialog = "{type='Core::PromptOverwriteDialog' unnamed='1' visible='1'}" waitForObject(overwriteDialog) if forceOverwrite: buttonToClick = 'OK' diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py index 9c757d99adb..016891a7320 100644 --- a/tests/system/shared/utils.py +++ b/tests/system/shared/utils.py @@ -133,37 +133,16 @@ def textUnderCursor(window, fromPos, toPos): return returnValue def which(program): - def is_exe(fpath): - return os.path.exists(fpath) and os.access(fpath, os.X_OK) - - def callableFile(path): - if is_exe(path): - return path - if platform.system() in ('Windows', 'Microsoft'): - for suffix in suffixes.split(os.pathsep): - if is_exe(path + suffix): - return path + suffix - return None - + # Don't use spawn.find_executable because it can't find .bat or + # .cmd files and doesn't check whether a file is executable (!) if platform.system() in ('Windows', 'Microsoft'): - suffixes = os.getenv("PATHEXT") - if not suffixes: - test.fatal("Can't read environment variable PATHEXT. Please check your installation.") - suffixes = "" - - fpath, fname = os.path.split(program) - if fpath: - return callableFile(program) + command = "where" + else: + command = "which" + foundPath = getOutputFromCmdline(command + " " + program) + if foundPath: + return foundPath.splitlines()[0] else: - if platform.system() in ('Windows', 'Microsoft'): - cf = callableFile(os.getcwd() + os.sep + program) - if cf: - return cf - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - cf = callableFile(exe_file) - if cf: - return cf return None # this function removes the user files of given pro file(s) diff --git a/tests/system/suite_CSUP/tst_CSUP06/test.py b/tests/system/suite_CSUP/tst_CSUP06/test.py index 82ff5429a3c..57701d468c9 100644 --- a/tests/system/suite_CSUP/tst_CSUP06/test.py +++ b/tests/system/suite_CSUP/tst_CSUP06/test.py @@ -123,7 +123,10 @@ def checkSymbolCompletion(editor, isClangCodeModel): def testSymb(currentLine, *args): missing, expectedSug, expectedRes = args symbol = currentLine.lstrip("/").strip() - propShown = waitFor("object.exists(':popupFrame_TextEditor::GenericProposalWidget')", 2500) + timeout = 2500 + if isClangCodeModel and JIRA.isBugStillOpen(15639): + timeout = 5000 + propShown = waitFor("object.exists(':popupFrame_TextEditor::GenericProposalWidget')", timeout) test.compare(not propShown, symbol in missing, "Proposal widget is (not) shown as expected (%s)" % symbol) found = [] @@ -144,8 +147,11 @@ def checkSymbolCompletion(editor, isClangCodeModel): else: exp = (symbol[:max(symbol.rfind(":"), symbol.rfind(".")) + 1] + expectedSug.get(symbol, found)[0]) - if not (isClangCodeModel and platform.system() in ('Microsoft', 'Windows') - and JIRA.isBugStillOpen(15483)): + if isClangCodeModel and changedLine != exp and JIRA.isBugStillOpen(15483): + test.xcompare(changedLine, exp, "Verify completion matches (QTCREATORBUG-15483).") + test.verify(changedLine.startswith(exp.replace("(", "").replace(")", "")), + "Verify completion starts with expected string.") + else: test.compare(changedLine, exp, "Verify completion matches.") performAutoCompletionTest(editor, ".*Complete symbols.*", "//", diff --git a/tests/system/suite_debugger/tst_qml_js_console/test.py b/tests/system/suite_debugger/tst_qml_js_console/test.py index 3b2a6b759a9..a6adab106d2 100644 --- a/tests/system/suite_debugger/tst_qml_js_console/test.py +++ b/tests/system/suite_debugger/tst_qml_js_console/test.py @@ -71,6 +71,8 @@ def getQmlJSConsoleOutput(): result = [] consoleView = waitForObject(":DebugModeWidget_Debugger::Internal::ConsoleView") model = consoleView.model() + # old input, output, new input > 2 + waitFor("model.rowCount() > 2", 2000) return dumpItems(model)[:-1] except: return [""] diff --git a/tests/system/suite_editors/shared/testdata/files.tsv b/tests/system/suite_editors/shared/testdata/files.tsv index 8be0cd420b8..1563394a6d2 100644 --- a/tests/system/suite_editors/shared/testdata/files.tsv +++ b/tests/system/suite_editors/shared/testdata/files.tsv @@ -7,3 +7,4 @@ "creator/src/plugins/coreplugin/basefilewizard.cpp" "creator/src/plugins/coreplugin/basefilewizard.h" "creator/tests/system/suite_debugger/tst_simple_debug/test.py" +"creator/tests/system/suite_editors/shared/testdata/binary.bin" diff --git a/tests/system/suite_editors/tst_delete_externally/test.py b/tests/system/suite_editors/tst_delete_externally/test.py index e8c4aa69a2a..fa85df88ae5 100644 --- a/tests/system/suite_editors/tst_delete_externally/test.py +++ b/tests/system/suite_editors/tst_delete_externally/test.py @@ -43,22 +43,25 @@ def main(): continue contentBefore = readFile(currentFile) - popupText = "The file %s was removed. Do you want to save it under a different name, or close the editor?" os.remove(currentFile) - test.compare(waitForObject(":File has been removed_QMessageBox").text, - popupText % currentFile) - clickButton(waitForObject(":File has been removed.Save_QPushButton")) - waitFor("os.path.exists(currentFile)", 5000) - # avoids a lock-up on some Linux machines, purely empiric, might have different cause - waitFor("checkIfObjectExists(':File has been removed_QMessageBox', False, 0)", 5000) + if not currentFile.endswith(".bin"): + popupText = "The file %s was removed. Do you want to save it under a different name, or close the editor?" + test.compare(waitForObject(":File has been removed_QMessageBox").text, + popupText % currentFile) + clickButton(waitForObject(":File has been removed.Save_QPushButton")) + waitFor("os.path.exists(currentFile)", 5000) + # avoids a lock-up on some Linux machines, purely empiric, might have different cause + waitFor("checkIfObjectExists(':File has been removed_QMessageBox', False, 0)", 5000) - test.compare(readFile(currentFile), contentBefore, - "Verifying that file '%s' was restored correctly" % currentFile) + test.compare(readFile(currentFile), contentBefore, + "Verifying that file '%s' was restored correctly" % currentFile) - # Different warning because of QTCREATORBUG-8130 - popupText2 = "The file %s has been removed outside Qt Creator. Do you want to save it under a different name, or close the editor?" - os.remove(currentFile) - test.compare(waitForObject(":File has been removed_QMessageBox").text, - popupText2 % currentFile) - clickButton(waitForObject(":File has been removed.Close_QPushButton")) + # Different warning because of QTCREATORBUG-8130 + popupText2 = "The file %s has been removed outside Qt Creator. Do you want to save it under a different name, or close the editor?" + os.remove(currentFile) + test.compare(waitForObject(":File has been removed_QMessageBox").text, + popupText2 % currentFile) + clickButton(waitForObject(":File has been removed.Close_QPushButton")) + test.verify(checkIfObjectExists(objectMap.realName(editor), False), + "Was the editor closed after deleting the file?") invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_editors/tst_edit_externally/test.py b/tests/system/suite_editors/tst_edit_externally/test.py index 32ee3efe6f1..e48232e9a4d 100644 --- a/tests/system/suite_editors/tst_edit_externally/test.py +++ b/tests/system/suite_editors/tst_edit_externally/test.py @@ -96,7 +96,8 @@ def main(): test.fatal("Failed to get editor - continuing...") continue # verify currentFile - waitFor("'addedLine' in str(editor.plainText)", 2500) - test.compare(editor.plainText, contentBefore + "addedLine\n", - "Verifying: file '%s' was reloaded modified." % currentFile) + if not currentFile.endswith(".bin"): + waitFor("'addedLine' in str(editor.plainText)", 2500) + test.compare(editor.plainText, contentBefore + "addedLine\n", + "Verifying: file '%s' was reloaded modified." % currentFile) invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_editors/tst_select_all/test.py b/tests/system/suite_editors/tst_select_all/test.py index c98c387e69b..1c0a4b309a3 100644 --- a/tests/system/suite_editors/tst_select_all/test.py +++ b/tests/system/suite_editors/tst_select_all/test.py @@ -30,6 +30,7 @@ source("../../shared/qtcreator.py") def main(): files = map(lambda record: os.path.join(srcPath, testData.field(record, "filename")), testData.dataset("files.tsv")) + files = filter(lambda x: not x.endswith(".bin"), files) for currentFile in files: if not neededFilePresent(currentFile): return diff --git a/tests/system/suite_general/tst_new_class/test.py b/tests/system/suite_general/tst_new_class/test.py index 2db90d7b533..c0ab7bbe86c 100644 --- a/tests/system/suite_general/tst_new_class/test.py +++ b/tests/system/suite_general/tst_new_class/test.py @@ -29,10 +29,12 @@ def main(): newClassName = "MyNewClass" headerFileName = newClassName.lower() + ".h" sourceFileName = newClassName.lower() + ".cpp" + basePath = tempDir() + notOverwrittenComment = "// If you can read this, the file was not overwritten." startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): return - addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", newBasePath=tempDir(), + addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", newBasePath=basePath, expectedSourceName=sourceFileName, expectedHeaderName=headerFileName) @@ -46,6 +48,9 @@ def main(): "Header included in source file?") test.verify(newClassName + "::" + newClassName + "()" in editorText, "Ctor implementation in source file?") + type(editor, notOverwrittenComment) + type(editor, "") + invokeMenuItem("File", "Save All") clickButton(waitForObject(":Qt Creator.CloseDoc_QToolButton")) if test.verify(waitFor("headerFileName in str(mainWindow.windowTitle)", 1000), "Header file was shown after closing source?"): @@ -64,5 +69,29 @@ def main(): "No signals in non-Qt header file?") test.verify("slots" not in editorText, # QTCREATORBUG-14949 "No slots in non-Qt header file?") + type(editor, notOverwrittenComment) + type(editor, "") + invokeMenuItem("File", "Save All") + invokeMenuItem("File", "Close All") + + def overwritten(filename): + return notOverwrittenComment not in readFile(os.path.join(basePath, filename)) + + addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", False, newBasePath=basePath, + expectedSourceName=sourceFileName, + expectedHeaderName=headerFileName) + test.verify(not waitFor("overwritten(sourceFileName)", 500), + "Source file should not be overwritten.") + test.verify(not waitFor("overwritten(headerFileName)", 500), + "Header file should not be overwritten.") + + addCPlusPlusFileToCurrentProject(newClassName, "C++ Class", True, newBasePath=basePath, + expectedSourceName=sourceFileName, + expectedHeaderName=headerFileName) + test.verify(waitFor("overwritten(sourceFileName)", 500), + "Source file should be overwritten.") + test.verify(waitFor("overwritten(headerFileName)", 500), + "Header file should be overwritten.") + invokeMenuItem("File", "Exit") return