From 7dbc6014e346efea9705f1a69771d009569f93c7 Mon Sep 17 00:00:00 2001
From: Robert Loehning 
Date: Tue, 31 Jan 2012 15:49:59 +0100
Subject: [PATCH] Squish: Added test for command line output
Change-Id: I4a25f971d41acd5e349e753602d4ae3aaafb4e32
Reviewed-by: Christian Stenger 
---
 tests/system/objects.map                      |  4 +
 tests/system/shared/debugger.py               | 33 +++++++
 tests/system/shared/project.py                |  8 +-
 tests/system/shared/qtcreator.py              |  1 +
 tests/system/shared/utils.py                  |  7 ++
 tests/system/suite_debugger/suite.conf        |  2 +-
 .../tst_cli_output_console/test.py            | 89 +++++++++++++++++++
 7 files changed, 142 insertions(+), 2 deletions(-)
 create mode 100644 tests/system/shared/debugger.py
 create mode 100644 tests/system/suite_debugger/tst_cli_output_console/test.py
diff --git a/tests/system/objects.map b/tests/system/objects.map
index 563969df75d..54a66f749ab 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -11,6 +11,7 @@
 :CMake Wizard.Next_QPushButton	{name='__qt__passive_wizardbutton1' text~='(Next.*|Continue)' type='QPushButton' visible='1' window=':CMake Wizard_CMakeProjectManager::Internal::CMakeOpenProjectWizard'}
 :CMake Wizard.Run CMake_QPushButton	{text='Run CMake' type='QPushButton' unnamed='1' visible='1' window=':CMake Wizard_CMakeProjectManager::Internal::CMakeOpenProjectWizard'}
 :CMake Wizard_CMakeProjectManager::Internal::CMakeOpenProjectWizard	{type='CMakeProjectManager::Internal::CMakeOpenProjectWizard' unnamed='1' visible='1' windowTitle='CMake Wizard'}
+:DebugModeWidget.Debugger Log_QDockWidget	{container=':Qt Creator.DebugModeWidget_QSplitter' name='Debugger.Docks.Output' type='QDockWidget' visible='1' windowTitle='Debugger Log'}
 :Generator:_QComboBox	{buddy=':CMake Wizard.Generator:_QLabel' type='QComboBox' unnamed='1' visible='1'}
 :New.templateCategoryView_QTreeView	{name='templateCategoryView' type='QTreeView' visible='1' window=':New_Core::Internal::NewDialog'}
 :New.templatesView_QListView	{name='templatesView' type='QListView' visible='1' window=':New_Core::Internal::NewDialog'}
@@ -22,11 +23,13 @@
 :Options_QListView	{type='QListView' unnamed='1' visible='1' window=':Options_Core::Internal::SettingsDialog'}
 :Project Setup.scrollArea_QScrollArea	{name='scrollArea' type='QScrollArea' visible='1' window=':Project Setup_Qt4ProjectManager::Internal::ProjectLoadWizard'}
 :Project Setup_Qt4ProjectManager::Internal::ProjectLoadWizard	{type='Qt4ProjectManager::Internal::ProjectLoadWizard' unnamed='1' visible='1' windowTitle='Project Setup'}
+:Qt Creator.DebugModeWidget_QSplitter	{name='DebugModeWidget' type='QSplitter' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
 :Qt Creator.QtCreator.MenuBar_QMenuBar	{name='QtCreator.MenuBar' type='QMenuBar' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
 :Qt Creator.ReRun_QToolButton	{toolTip='Re-run this run-configuration' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
 :Qt Creator.Stop_QToolButton	{text='Stop' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
 :Qt Creator.scrollArea_QScrollArea	{name='scrollArea' type='QScrollArea' 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_CloseButton	{type='CloseButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
 :Qt Creator_Core::Internal::MainWindow	{type='Core::Internal::MainWindow' visible='1' windowTitle?='*Qt Creator'}
 :Qt Creator_CppEditor::Internal::CPPEditorWidget	{type='CppEditor::Internal::CPPEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
 :Qt Creator_QTableView	{type='QTableView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
@@ -40,6 +43,7 @@
 :Qt Gui Application.scrollArea_QScrollArea	{name='scrollArea' type='QScrollArea' visible='1'}
 :Qt Gui Application_Qt4ProjectManager::Internal::GuiAppWizardDialog	{type='Qt4ProjectManager::Internal::GuiAppWizardDialog' unnamed='1' visible='1' windowTitle='Qt Gui Application'}
 :QtCreator.MenuBar_ProjectExplorer::Internal::MiniProjectTargetSelector	{type='ProjectExplorer::Internal::MiniProjectTargetSelector'}
+:Symbol Server_Utils::CheckableMessageBox	{type='Utils::CheckableMessageBox' unnamed='1' visible='1' windowTitle='Symbol Server'}
 :addToVersionControlComboBox_QComboBox	{name='addToVersionControlComboBox' type='QComboBox' visible='1'}
 :formFileLineEdit_Utils::FileNameValidatingLineEdit	{buddy=':Qt Gui Application.Form file:_QLabel' name='formFileLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1'}
 :headerFileLineEdit_Utils::FileNameValidatingLineEdit	{buddy=':Qt Gui Application.Header file:_QLabel' name='headerFileLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1'}
diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py
new file mode 100644
index 00000000000..6ddb2a68eeb
--- /dev/null
+++ b/tests/system/shared/debugger.py
@@ -0,0 +1,33 @@
+def handleDebuggerWarnings(config):
+    if "MSVC" in config:
+        try:
+            popup = waitForObject("{text?='*' type='QLabel' unnamed='1' visible='1' window=':Symbol Server_Utils::CheckableMessageBox'}", 10000)
+            symServerNotConfiged = ("
The debugger is not configured to use the public "
+                                    "Microsoft Symbol Server. "
+                                    "This is recommended for retrieval of the symbols of the operating system libraries.
"
+                                    "Note: A fast internet connection is required for this to work smoothly. "
+                                    "Also, a delay might occur when connecting for the first time.
"
+                                    "Would you like to set it up?
")
+            if popup.text == symServerNotConfiged:
+                test.log("Creator warned about the debugger not being configured to use the public Microsoft Symbol Server.")
+            else:
+                test.warning("Creator showed an unexpected warning: " + str(popup.text))
+            clickButton(waitForObject("{text='No' type='QPushButton' unnamed='1' visible='1' window=':Symbol Server_Utils::CheckableMessageBox'}", 10000))
+        except LookupError:
+            pass # No warning. Fine.
+    else:
+        if "Release" in config and platform.system() != "Darwin":
+            message = waitForObject("{container=':Qt Creator.DebugModeWidget_QSplitter' name='qt_msgbox_label' type='QLabel' visible='1'}", 20000)
+            test.compare(message.text, "This does not seem to be a \"Debug\" build.\nSetting breakpoints by file name and line number may fail.")
+            clickButton("{container=':Qt Creator.DebugModeWidget_QSplitter' text='OK' type='QPushButton' unnamed='1' visible='1'}")
+
+def takeDebuggerLog():
+    invokeMenuItem("Window", "Views", "Debugger Log")
+    debuggerLogWindow = waitForObject("{container=':DebugModeWidget.Debugger Log_QDockWidget' type='Debugger::Internal::CombinedPane' unnamed='1' visible='1'}", 20000)
+    debuggerLog = str(debuggerLogWindow.plainText)
+    mouseClick(debuggerLogWindow, 5, 5, 0, Qt.LeftButton)
+    activateItem(waitForObjectItem(openContextMenuOnTextCursorPosition(debuggerLogWindow),
+                                   "Clear Contents"))
+    waitFor("str(debuggerLogWindow.plainText)==''", 5000)
+    invokeMenuItem("Window", "Views", "Debugger Log")
+    return debuggerLog
diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py
index d855ff33e3d..7818cf8af4f 100644
--- a/tests/system/shared/project.py
+++ b/tests/system/shared/project.py
@@ -164,7 +164,13 @@ def createProject_Qt_GUI(path, projectName, qtVersion = None, checks = True):
     waitForSignal("{type='CppTools::Internal::CppModelManager' unnamed='1'}", "sourceFilesRefreshed(QStringList)", 20000)
     __verifyFileCreation__(path, expectedFiles)
 
-def createProject_Qt_Console(path, projectName, qtVersion, checks):
+# Creates a Qt Console project
+# param path specifies where to create the project
+# param projectName is the name for the new project
+# param qtVersion is the name of a Qt version. In the project, build configurations will be
+#                 created for this version. If it is None, all Qt versions will be used
+# param checks turns tests in the function on if set to True
+def createProject_Qt_Console(path, projectName, qtVersion = None, checks = True):
     __createProjectSelectType__("Other Qt Project", "Qt Console Application")
     __createProjectSetNameAndPath__(path, projectName, checks)
     __selectQtVersionDesktop__(qtVersion, checks)
diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py
index 564e0331249..7e7841afafd 100644
--- a/tests/system/shared/qtcreator.py
+++ b/tests/system/shared/qtcreator.py
@@ -21,6 +21,7 @@ source("../../shared/project.py")
 source("../../shared/editor_utils.py")
 source("../../shared/project_explorer.py")
 source("../../shared/hook_utils.py")
+source("../../shared/debugger.py")
 
 def waitForCleanShutdown(timeOut=10):
     appCtxt = currentApplicationContext()
diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py
index 34c8a443138..e5b12f6a524 100644
--- a/tests/system/shared/utils.py
+++ b/tests/system/shared/utils.py
@@ -221,3 +221,10 @@ def addHelpDocumentationFromSDK():
     clickButton(waitForObject("{type='QPushButton' name='addButton' visible='1' text='Add...'}"))
     selectFromFileDialog("%s/Documentation/qt.qch" % sdkPath)
     clickButton(waitForObject(":Options.OK_QPushButton"))
+
+def verifyOutput(string, substring, outputFrom, outputIn):
+    index = string.find(substring)
+    if (index == -1):
+        test.fail("Output from " + outputFrom + " could not be found in " + outputIn)
+    else:
+        test.passes("Output from " + outputFrom + " found at position " + str(index) + " of " + outputIn)
diff --git a/tests/system/suite_debugger/suite.conf b/tests/system/suite_debugger/suite.conf
index 441033d6127..d776d72c7a0 100644
--- a/tests/system/suite_debugger/suite.conf
+++ b/tests/system/suite_debugger/suite.conf
@@ -7,6 +7,6 @@ HOOK_SUB_PROCESSES=false
 IMPLICITAUTSTART=0
 LANGUAGE=Python
 OBJECTMAP=../objects.map
-TEST_CASES=tst_build_new_project
+TEST_CASES=tst_build_new_project tst_cli_output_console
 VERSION=2
 WRAPPERS=Qt
diff --git a/tests/system/suite_debugger/tst_cli_output_console/test.py b/tests/system/suite_debugger/tst_cli_output_console/test.py
new file mode 100644
index 00000000000..7ae75ddc5e5
--- /dev/null
+++ b/tests/system/suite_debugger/tst_cli_output_console/test.py
@@ -0,0 +1,89 @@
+source("../../shared/qtcreator.py")
+
+projectsPath = tempDir()
+project = "untitled"
+
+def __handlerunControlFinished__(object, runControlP):
+    global runControlFinished
+    runControlFinished = True
+
+def main():
+    global runControlFinished
+    outputQDebug = "Output from qDebug()."
+    outputStdOut = "Output from std::cout."
+    outputStdErr = "Output from std::cerr."
+    startApplication("qtcreator" + SettingsPath)
+    installLazySignalHandler("{type='ProjectExplorer::Internal::ProjectExplorerPlugin' unnamed='1'}",
+                             "runControlFinished(ProjectExplorer::RunControl*)", "__handlerunControlFinished__")
+    createProject_Qt_Console(projectsPath, project)
+
+    mainEditor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget")
+    replaceEditorContent(mainEditor, "")
+    typeLines(mainEditor, ["#include ",
+                           "#include ",
+                           "int main(int, char *argv[])",
+                           "{",
+                           '    std::cout << \"' + outputStdOut + '\" << std::endl;',
+                           '    std::cerr << \"' + outputStdErr + '\" << std::endl;',
+                           '    qDebug() << \"' + outputQDebug + '\";'])
+    # Rely on code completion for closing bracket
+    invokeMenuItem("File", "Save All")
+    selectFromLocator(project + ".pro")
+    proEditor = waitForObject("{type='Qt4ProjectManager::Internal::ProFileEditorWidget' unnamed='1' visible='1'"
+                              "window=':Qt Creator_Core::Internal::MainWindow'}", 20000)
+    test.verify("CONFIG   += console" in str(proEditor.plainText), "Verifying that program is configured with console")
+    setRunInTerminal(1, 0, False)
+
+    for config in iterateBuildConfigs(1, 0):
+        selectBuildConfig(1, 0, config)
+        test.log("Testing build configuration: " + config)
+
+        test.log("Running application")
+        runControlFinished = False
+        clickButton(waitForObject("{type='Core::Internal::FancyToolButton' text='Run' visible='1'}", 20000))
+        waitFor("runControlFinished==True")
+        appOutput = str(waitForObject("{type='Core::OutputWindow' unnamed='1' visible='1'}", 20000).plainText)
+        verifyOutput(appOutput, outputStdOut, "std::cout", "Application Output")
+        verifyOutput(appOutput, outputStdErr, "std::cerr", "Application Output")
+        verifyOutput(appOutput, outputQDebug, "qDebug()", "Application Output")
+        clickButton(waitForObject(":Qt Creator_CloseButton"))
+
+        test.log("Debugging application")
+        runControlFinished = False
+        invokeMenuItem("Debug", "Start Debugging", "Start Debugging")
+        if "Release" in config and platform.system() == "Linux":
+            snooze(1) # work around QTCREATORBUG-6853
+        handleDebuggerWarnings(config)
+        waitFor("runControlFinished==True")
+        try:
+            debuggerLog = takeDebuggerLog()
+            if not "MSVC" in config:
+                # cout works with MSVC, too, but we don't check it since it's not supported
+                verifyOutput(debuggerLog, outputStdOut, "std::cout", "Debugger Log")
+                verifyOutput(debuggerLog, outputStdErr, "std::cerr", "Debugger Log")
+                verifyOutput(debuggerLog, outputQDebug, "qDebug()", "Debugger Log")
+        except LookupError:
+            # takeDebuggerLog() expects the debugger log to not be visible.
+            # If debugger log showed up automatically, previous call to takeDebuggerLog() has closed it.
+            debuggerLog = takeDebuggerLog()
+            if "lib\qtcreatorcdbext64\qtcreatorcdbext.dll cannot be found." in debuggerLog:
+                test.fatal("qtcreatorcdbext.dll is missing in lib\qtcreatorcdbext64")
+            else:
+                test.fatal("Debugger log did not behave as expected. Please check manually.")
+        switchViewTo(ViewConstants.EDIT)
+        appOutput = str(waitForObject("{type='Core::OutputWindow' unnamed='1' visible='1'}", 20000).plainText)
+        if not "MSVC" in config:
+            verifyOutput(appOutput, outputStdOut, "std::cout", "Application Output")
+            verifyOutput(appOutput, outputStdErr, "std::cerr", "Application Output")
+            verifyOutput(appOutput, outputQDebug, "qDebug()", "Application Output")
+        clickButton(waitForObject(":Qt Creator_CloseButton"))
+
+    invokeMenuItem("File", "Exit")
+    waitForCleanShutdown()
+
+def init():
+    cleanup()
+
+def cleanup():
+    deleteDirIfExists(projectsPath + os.sep + project)
+    deleteDirIfExists(shadowBuildDir(projectsPath, project, defaultQtVersion, 1))