aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorChristian Stenger <christian.stenger@nokia.com>2012-03-26 14:13:39 +0200
committerChristian Stenger <christian.stenger@nokia.com>2012-04-27 17:52:25 +0200
commitaa3a2dc9267519e4bdfd93b3a79386fad68665ee (patch)
tree4a9cf5a03f835213cbca06a026384a98c8d59bfe /tests
parent29062c64f7d880f15a95dbcec8d0ca6804550a54 (diff)
Squish: Added debug test case
This is intended to be a starting point. Change-Id: I0941ed16876810832aa6088287f8062bba6a273e Reviewed-by: Robert Löhning <robert.loehning@nokia.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/system/objects.map10
-rw-r--r--tests/system/shared/build_utils.py22
-rw-r--r--tests/system/shared/debugger.py186
-rw-r--r--tests/system/suite_debugger/tst_simple_debug/test.py62
4 files changed, 280 insertions, 0 deletions
diff --git a/tests/system/objects.map b/tests/system/objects.map
index 7345a42fb2..2f228d6fd4 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -1,5 +1,8 @@
:*Qt Creator.Build Project_Core::Internal::FancyToolButton {text='Build Project' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:*Qt Creator.Continue_Core::Internal::FancyToolButton {text='Continue' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:*Qt Creator.Interrupt_Core::Internal::FancyToolButton {text='Interrupt' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.Run_Core::Internal::FancyToolButton {text='Run' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:*Qt Creator.Start Debugging_Core::Internal::FancyToolButton {text='Start Debugging' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.findEdit_Utils::FilterLineEdit {name='findEdit' type='Utils::FilterLineEdit' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator.qt_tabwidget_stackedwidget_QStackedWidget {name='qt_tabwidget_stackedwidget' type='QStackedWidget' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:*Qt Creator_Core::Internal::FancyToolButton {occurrence='3' type='Core::Internal::FancyToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
@@ -12,6 +15,12 @@
: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'}
+:DebugModeWidget.Debugger Toolbar_QDockWidget {container=':Qt Creator.DebugModeWidget_QSplitter' name='Debugger Toolbar' type='QDockWidget' visible='1' windowTitle='Debugger Toolbar'}
+:DebugModeWidget.OK_QPushButton {container=':Qt Creator.DebugModeWidget_QSplitter' text='OK' type='QPushButton' unnamed='1' visible='1'}
+:Debugger Toolbar.Continue_QToolButton {container=':DebugModeWidget.Debugger Toolbar_QDockWidget' text='Continue' type='QToolButton' unnamed='1' visible='1'}
+:Debugger Toolbar.Exit Debugger_QToolButton {container=':DebugModeWidget.Debugger Toolbar_QDockWidget' text='Exit Debugger' type='QToolButton' unnamed='1' visible='1'}
+:Debugger Toolbar.StatusText_Utils::StatusLabel {container=':DebugModeWidget.Debugger Toolbar_QDockWidget' type='Utils::StatusLabel' unnamed='1'}
+:Failed to start application_QMessageBox {type='QMessageBox' unnamed='1' visible='1' windowTitle='Failed to start application'}
:Generator:_QComboBox {buddy=':CMake Wizard.Generator:_QLabel' type='QComboBox' unnamed='1' visible='1'}
:New.frame_QFrame {name='frame' type='QFrame' visible='1' window=':New_Core::Internal::NewDialog'}
:New.templateCategoryView_QTreeView {name='templateCategoryView' type='QTreeView' visible='1' window=':New_Core::Internal::NewDialog'}
@@ -57,6 +66,7 @@
:qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget {container=':Options.qt_tabwidget_stackedwidget_QStackedWidget' name='QtSupport__Internal__QtVersionManager' type='QtSupport::Internal::QtOptionsPageWidget' visible='1'}
:scrollArea.Create Build Configurations:_QComboBox_2 {container=':Qt Gui Application.scrollArea_QScrollArea' leftWidget=':scrollArea.Create Build Configurations:_QLabel_2' type='QComboBox' unnamed='1' visible='1'}
:scrollArea.Create Build Configurations:_QLabel_2 {container=':Qt Gui Application.scrollArea_QScrollArea' text='Create build configurations:' type='QLabel' unnamed='1' visible='1'}
+:scrollArea.Details_Utils::DetailsButton {container=':Qt Creator.scrollArea_QScrollArea' text='Details' type='Utils::DetailsButton' unnamed='1' visible='1'}
:scrollArea.Edit build configuration:_QComboBox {container=':Qt Creator.scrollArea_QScrollArea' leftWidget=':scrollArea.Edit build configuration:_QLabel' type='QComboBox' unnamed='1' visible='1'}
:scrollArea.Edit build configuration:_QLabel {container=':Qt Creator.scrollArea_QScrollArea' text='Edit build configuration:' type='QLabel' unnamed='1' visible='1'}
:scrollArea.Qt 4 for Desktop - (Qt SDK) debug_QCheckBox {container=':Qt Gui Application.scrollArea_QScrollArea' text?='*Qt 4.* for *(Qt SDK) debug' type='QCheckBox' unnamed='1' visible='1'}
diff --git a/tests/system/shared/build_utils.py b/tests/system/shared/build_utils.py
index ed39e06069..156cdad1a7 100644
--- a/tests/system/shared/build_utils.py
+++ b/tests/system/shared/build_utils.py
@@ -163,3 +163,25 @@ def selectBuildConfig(targetCount, currentTarget, configName):
waitForSignal("{type='CppTools::Internal::CppModelManager' unnamed='1'}",
"sourceFilesRefreshed(QStringList)")
switchViewTo(ViewConstants.EDIT)
+
+def verifyBuildConfig(targetCount, currentTarget, shouldBeDebug=False, enableShadowBuild=False):
+ switchViewTo(ViewConstants.PROJECTS)
+ switchToBuildOrRunSettingsFor(targetCount, currentTarget, ProjectSettings.BUILD)
+ detailsButton = waitForObject(":scrollArea.Details_Utils::DetailsButton")
+ ensureChecked(detailsButton)
+ ensureChecked("{name='shadowBuildCheckBox' type='QCheckBox' visible='1'}", enableShadowBuild)
+ buildCfCombo = waitForObject("{type='QComboBox' name='buildConfigurationComboBox' visible='1' "
+ "container=':Qt Creator.scrollArea_QScrollArea'}")
+ if shouldBeDebug:
+ test.compare(buildCfCombo.currentText, 'Debug', "Verifying whether it's a debug build")
+ else:
+ test.compare(buildCfCombo.currentText, 'Release', "Verifying whether it's a release build")
+ try:
+ problemFound = waitForObject("{container=':Qt Creator.scrollArea_QScrollArea' type='QLabel' "
+ "name='problemLabel' visible='1'}", 1000)
+ if problemFound:
+ test.warning('%s' % problemFound.text)
+ except:
+ pass
+ clickButton(detailsButton)
+ switchViewTo(ViewConstants.EDIT)
diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py
index 6ddb2a68ee..42957d8d24 100644
--- a/tests/system/shared/debugger.py
+++ b/tests/system/shared/debugger.py
@@ -1,3 +1,5 @@
+import re
+
def handleDebuggerWarnings(config):
if "MSVC" in config:
try:
@@ -31,3 +33,187 @@ def takeDebuggerLog():
waitFor("str(debuggerLogWindow.plainText)==''", 5000)
invokeMenuItem("Window", "Views", "Debugger Log")
return debuggerLog
+
+# function to set breakpoints for the current project
+# on the given file,line pairs inside the given dict
+# the lines are treated as regular expression
+def setBreakpointsForCurrentProject(filesAndLines):
+ # internal helper for setBreakpointsForCurrentProject
+ # double clicks the treeElement inside the given navTree
+ # TODO: merge with doubleClickFile() from tst_qml_editor & move to utils(?)
+ def __doubleClickFile__(navTree, treeElement):
+ waitForObjectItem(navTree, treeElement)
+ fileNamePattern = re.compile(".*\.(?P<file>(.*\\\..*)?)$")
+ fileName = fileNamePattern.search(treeElement).group("file").replace("\\.", ".")
+ doubleClickItem(navTree, treeElement, 5, 5, 0, Qt.LeftButton)
+ mainWindow = waitForObject(":Qt Creator_Core::Internal::MainWindow")
+ waitFor('fileName in str(mainWindow.windowTitle)', 5000)
+ return fileName
+
+ switchViewTo(ViewConstants.DEBUG)
+ removeOldBreakpoints()
+ if not filesAndLines or not isinstance(filesAndLines, dict):
+ test.fatal("This function only takes a non-empty dict.")
+ return False
+ navTree = waitForObject("{type='Utils::NavigationTreeView' unnamed='1' visible='1' "
+ "window=':Qt Creator_Core::Internal::MainWindow'}", 20000)
+ for curFile,curLine in filesAndLines.iteritems():
+ fName = __doubleClickFile__(navTree, curFile)
+ editor = getEditorForFileSuffix(curFile)
+ if not placeCursorToLine(editor, curLine, True):
+ return False
+ invokeMenuItem("Debug", "Toggle Breakpoint")
+ test.log('Set breakpoint in %s' % fName, curLine)
+ breakPointTreeView = waitForObject("{type='Debugger::Internal::BreakWindow' visible='1' "
+ "windowTitle='Breakpoints' name='Debugger.Docks.Break'}")
+ waitFor("breakPointTreeView.model().rowCount() == len(filesAndLines)", 2000)
+ test.compare(breakPointTreeView.model().rowCount(), len(filesAndLines),
+ 'Expected %d set break points, found %d listed' %
+ (len(filesAndLines), breakPointTreeView.model().rowCount()))
+ return True
+
+# helper that removes all breakpoints - assumes that it's getting called
+# being already on Debug view and Breakpoints widget is not disabled
+def removeOldBreakpoints():
+ test.log("Removing old breakpoints if there are any")
+ try:
+ breakPointTreeView = waitForObject("{type='Debugger::Internal::BreakWindow' visible='1' "
+ "windowTitle='Breakpoints' name='Debugger.Docks.Break'}")
+ model = breakPointTreeView.model()
+ if model.rowCount()==0:
+ test.log("No breakpoints found...")
+ else:
+ test.log("Found %d breakpoints - removing them" % model.rowCount())
+ for row in range(model.rowCount()):
+ currentIndex = model.index(row,0)
+ rect = breakPointTreeView.visualRect(currentIndex)
+ mouseClick(breakPointTreeView, rect.x+5, rect.y+5, 0, Qt.LeftButton)
+ type(breakPointTreeView, "<Delete>")
+ except LookupError:
+ pass
+ return test.compare(model.rowCount(), 0, "Check if all breakpoints have been removed.")
+
+# function to do simple debugging of the current (configured) project
+# param pressContinueCount defines how often it is expected to press
+# the 'Continue' button while debugging
+# param expectedBPOrder holds a list of dicts where the dicts contain always
+# only 1 key:value pair - the key is the name of the file, the value is
+# line number where the debugger should stop
+def doSimpleDebugging(currentConfigName, pressContinueCount=1, expectedBPOrder=[]):
+ expectedLabelTexts = ['Stopped\.', 'Stopped at breakpoint \d+ \(\d+\) in thread \d+\.']
+ if len(expectedBPOrder) == 0:
+ expectedLabelTexts.append("Running\.")
+ if not __startDebugger__(currentConfigName):
+ return False
+ statusLabel = findObject(":Debugger Toolbar.StatusText_Utils::StatusLabel")
+ test.log("Continuing debugging %d times..." % pressContinueCount)
+ for i in range(pressContinueCount):
+ if waitFor("regexVerify(str(statusLabel.text), expectedLabelTexts)", 20000):
+ verifyBreakPoint(expectedBPOrder[i])
+ else:
+ test.fail('%s' % str(statusLabel.text))
+ contDbg = waitForObject(":*Qt Creator.Continue_Core::Internal::FancyToolButton", 3000)
+ test.log("Continuing...")
+ clickButton(contDbg)
+ waitFor("str(statusLabel.text) == 'Running.'", 5000)
+ timedOut = not waitFor("str(statusLabel.text) in ['Running.', 'Debugger finished.']", 30000)
+ if timedOut:
+ test.log("Waiting for 'Running.' / 'Debugger finished.' timed out.",
+ "Debugger is in state: '%s'..." % statusLabel.text)
+ if str(statusLabel.text) == 'Running.':
+ test.log("Debugger is still running... Will be stopped.")
+ return __stopDebugger__()
+ elif str(statusLabel.text) == 'Debugger finished.':
+ test.log("Debugger has finished.")
+ return __logDebugResult__()
+ else:
+ test.log("Trying to stop debugger...")
+ try:
+ return __stopDebugger__()
+ except:
+ # if stopping failed - debugger had already stopped
+ return True
+
+def __startDebugger__(config):
+ clickButton(waitForObject(":*Qt Creator.Start Debugging_Core::Internal::FancyToolButton"))
+ handleDebuggerWarnings(config)
+ hasNotTimedOut = waitFor("object.exists(':Debugger Toolbar.Continue_QToolButton')", 20000)
+ try:
+ mBox = findObject(":Failed to start application_QMessageBox")
+ mBoxText = mBox.text
+ mBoxIText = mBox.informativeText
+ clickButton(":DebugModeWidget.OK_QPushButton")
+ test.fail("Debugger hasn't started... QMessageBox appeared!")
+ test.log("QMessageBox content: '%s'" % mBoxText,
+ "'%s'" % mBoxIText)
+ return False
+ except:
+ pass
+ if hasNotTimedOut:
+ test.passes("Debugger started...")
+ else:
+ test.fail("Debugger seems to have not started...")
+ if "MSVC" in config:
+ 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.")
+ logApplicationOutput()
+ return False
+ try:
+ waitForObject(":*Qt Creator.Interrupt_Core::Internal::FancyToolButton", 3000)
+ test.passes("'Interrupt' (debugger) button visible.")
+ except:
+ try:
+ waitForObject(":*Qt Creator.Continue_Core::Internal::FancyToolButton", 3000)
+ test.passes("'Continue' (debugger) button visible.")
+ except:
+ test.fatal("Neither 'Interrupt' nor 'Continue' button visible (Debugger).")
+ return True
+
+def __stopDebugger__():
+ clickButton(waitForObject(":Debugger Toolbar.Exit Debugger_QToolButton"))
+ ensureChecked("{type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' "
+ "window=':Qt Creator_Core::Internal::MainWindow' occurrence='3'}")
+ output = waitForObject("{type='Core::OutputWindow' visible='1' windowTitle='Application Output Window'}", 20000)
+ waitFor("'Debugging has finished' in str(output.plainText)", 20000)
+ return __logDebugResult__()
+
+def __logDebugResult__():
+ try:
+ result = waitForObject(":*Qt Creator.Start Debugging_Core::Internal::FancyToolButton")
+ test.passes("'Start Debugging' button visible.")
+ except:
+ test.fail("'Start Debugging' button is not visible.")
+ result = None
+ if result:
+ test.passes("Debugger stopped.. Qt Creator is back at normal state.")
+ else:
+ test.fail("Debugger seems to have not stopped...")
+ logApplicationOutput()
+ return result
+
+def verifyBreakPoint(bpToVerify):
+ if isinstance(bpToVerify, dict):
+ fileName = bpToVerify.keys()[0]
+ editor = getEditorForFileSuffix(fileName)
+ if editor == None:
+ return False
+ textPos = editor.textCursor().position()
+ line = str(editor.plainText)[:textPos].count("\n") + 1
+ windowTitle = str(waitForObject(":Qt Creator_Core::Internal::MainWindow").windowTitle)
+ if fileName in windowTitle:
+ test.passes("Creator's window title changed according to current file")
+ else:
+ test.fail("Creator's window title did not change according to current file")
+ if line == bpToVerify.values()[0]:
+ test.passes("Breakpoint at expected line (%d) inside expected file (%s)"
+ % (line, fileName))
+ return True
+ else:
+ test.fail("Breakpoint did not match expected line/file",
+ "Found: %d in %s" % (line, fileName))
+ else:
+ test.fatal("Expected a dict for bpToVerify - got '%s'" % className(bpToVerify))
+ return False
diff --git a/tests/system/suite_debugger/tst_simple_debug/test.py b/tests/system/suite_debugger/tst_simple_debug/test.py
new file mode 100644
index 0000000000..4dce12bab1
--- /dev/null
+++ b/tests/system/suite_debugger/tst_simple_debug/test.py
@@ -0,0 +1,62 @@
+source("../../shared/qtcreator.py")
+
+workingDir = None
+
+def main():
+ global workingDir
+ startApplication("qtcreator" + SettingsPath)
+ if not checkDebuggingLibrary("4.8.0", [QtQuickConstants.Targets.DESKTOP]):
+ test.fatal("Error while checking debugging libraries - leaving this test.")
+ invokeMenuItem("File", "Exit")
+ return
+ # using a temporary directory won't mess up a potentially existing
+ workingDir = tempDir()
+ projectName = createNewQtQuickApplication(workingDir, targets = QtQuickConstants.Targets.DESKTOP)
+ # wait for parsing to complete
+ waitForSignal("{type='CppTools::Internal::CppModelManager' unnamed='1'}",
+ "sourceFilesRefreshed(QStringList)")
+ editor = waitForObject("{type='QmlJSEditor::QmlJSTextEditorWidget' unnamed='1' "
+ "visible='1' window=':Qt Creator_Core::Internal::MainWindow'}")
+ if placeCursorToLine(editor, "MouseArea.*", True):
+ type(editor, '<Up>')
+ type(editor, '<Return>')
+ type(editor, 'Component.onCompleted: console.log("Break here")')
+ invokeMenuItem("File", "Save All")
+ filesAndLines = {
+ "%s.QML.qml/%s.main\\.qml" % (projectName,projectName) : 'Component.onCompleted.*',
+ "%s.Sources.main\\.cpp" % projectName : "viewer.setOrientation\\(.+\\);"
+ }
+ test.log("Setting breakpoints")
+ result = setBreakpointsForCurrentProject(filesAndLines)
+ if result:
+ expectedBreakpointsOrder = [{"main.cpp":9}, {"main.qml":11}]
+ availableConfigs = iterateBuildConfigs(1, 0, ".*4\.8(\.\d+)?.*$(?<![Rr]elease)")
+ if not availableConfigs:
+ test.fatal("Haven't found a suitable Qt version (need Qt >= 4.8) - leaving without debugging.")
+ for config in availableConfigs:
+ test.log("Selecting '%s' as build config" % config)
+ selectBuildConfig(1, 0, config)
+ verifyBuildConfig(1, 0, True)
+ # explicitly build before start debugging for adding the executable as allowed program to WinFW
+ invokeMenuItem("Build", "Rebuild All")
+ waitForSignal("{type='ProjectExplorer::BuildManager' unnamed='1'}",
+ "buildQueueFinished(bool)", 300000)
+ if not checkCompile():
+ test.fatal("Compile had errors... Skipping current build config")
+ continue
+ allowAppThroughWinFW(workingDir, projectName, False)
+ if not doSimpleDebugging(config, 2, expectedBreakpointsOrder):
+ try:
+ stopB = findObject(':Qt Creator.Stop_QToolButton')
+ if stopB.enabled:
+ clickButton(stopB)
+ except:
+ pass
+ deleteAppFromWinFW(workingDir, projectName, False)
+ # close application output window of current run to avoid mixing older output on the next run
+ ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton")
+ clickButton(waitForObject("{type='CloseButton' unnamed='1' visible='1' "
+ "window=':Qt Creator_Core::Internal::MainWindow'}"))
+ else:
+ test.fatal("Setting breakpoints failed - leaving without testing.")
+ invokeMenuItem("File", "Exit")