| 
									
										
										
										
											2013-05-15 13:17:33 +02:00
										 |  |  | ############################################################################# | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | 
					
						
							|  |  |  | ## Contact: http://www.qt-project.org/legal | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## This file is part of Qt Creator. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## Commercial License Usage | 
					
						
							|  |  |  | ## Licensees holding valid commercial Qt licenses may use this file in | 
					
						
							|  |  |  | ## accordance with the commercial license agreement provided with the | 
					
						
							|  |  |  | ## Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ## a written agreement between you and Digia.  For licensing terms and | 
					
						
							|  |  |  | ## conditions see http://qt.digia.com/licensing.  For further information | 
					
						
							|  |  |  | ## use the contact form at http://qt.digia.com/contact-us. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## GNU Lesser General Public License Usage | 
					
						
							|  |  |  | ## Alternatively, this file may be used under the terms of the GNU Lesser | 
					
						
							|  |  |  | ## General Public License version 2.1 as published by the Free Software | 
					
						
							|  |  |  | ## Foundation and appearing in the file LICENSE.LGPL included in the | 
					
						
							|  |  |  | ## packaging of this file.  Please review the following information to | 
					
						
							|  |  |  | ## ensure the GNU Lesser General Public License version 2.1 requirements | 
					
						
							|  |  |  | ## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ## In addition, as a special exception, Digia gives you certain additional | 
					
						
							|  |  |  | ## rights.  These rights are described in the Digia Qt LGPL Exception | 
					
						
							|  |  |  | ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ## | 
					
						
							|  |  |  | ############################################################################# | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 13:47:47 +01:00
										 |  |  | import re; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  | # dictionary to hold a list of all installed handler functions for all object-signalSignature pairs | 
					
						
							|  |  |  | installedSignalHandlers = {} | 
					
						
							|  |  |  | # flag to indicate whether overrideInstallLazySignalHandler() has been called already | 
					
						
							|  |  |  | overridenInstallLazySignalHandlers = False | 
					
						
							|  |  |  | # flag to indicate whether a tasks file should be created when building ends with errors | 
					
						
							|  |  |  | createTasksFileOnError = True | 
					
						
							|  |  |  | # currently used directory for tasks files | 
					
						
							|  |  |  | tasksFileDir = None | 
					
						
							|  |  |  | # counter for written tasks files | 
					
						
							|  |  |  | tasksFileCount = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # call this function to override installLazySignalHandler() | 
					
						
							|  |  |  | def overrideInstallLazySignalHandler(): | 
					
						
							|  |  |  |     global overridenInstallLazySignalHandlers | 
					
						
							|  |  |  |     if overridenInstallLazySignalHandlers: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     overridenInstallLazySignalHandlers = True | 
					
						
							|  |  |  |     global installLazySignalHandler | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  |     installLazySignalHandler = __addSignalHandlerDict__(installLazySignalHandler) | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | # avoids adding a handler to a signal twice or more often | 
					
						
							|  |  |  | # do not call this function directly - use overrideInstallLazySignalHandler() instead | 
					
						
							| 
									
										
										
										
											2011-09-21 17:29:18 +02:00
										 |  |  | def __addSignalHandlerDict__(lazySignalHandlerFunction): | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |     global installedSignalHandlers | 
					
						
							|  |  |  |     def wrappedFunction(name, signalSignature, handlerFunctionName): | 
					
						
							|  |  |  |         handlers = installedSignalHandlers.get("%s____%s" % (name,signalSignature)) | 
					
						
							|  |  |  |         if handlers == None: | 
					
						
							|  |  |  |             lazySignalHandlerFunction(name, signalSignature, handlerFunctionName) | 
					
						
							|  |  |  |             installedSignalHandlers.setdefault("%s____%s" % (name,signalSignature), [handlerFunctionName]) | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2012-02-22 15:43:05 +01:00
										 |  |  |             if not handlerFunctionName in handlers: | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |                 lazySignalHandlerFunction(name, signalSignature, handlerFunctionName) | 
					
						
							|  |  |  |                 handlers.append(handlerFunctionName) | 
					
						
							|  |  |  |                 installedSignalHandlers.setdefault("%s____%s" % (name,signalSignature), handlers) | 
					
						
							|  |  |  |     return wrappedFunction | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # returns the currently assigned handler functions for a given object and signal | 
					
						
							|  |  |  | def getInstalledSignalHandlers(name, signalSignature): | 
					
						
							|  |  |  |     return installedSignalHandlers.get("%s____%s" % (name,signalSignature)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # this method checks the last build (if there's one) and logs the number of errors, warnings and | 
					
						
							| 
									
										
										
										
											2011-10-06 13:55:05 +02:00
										 |  |  | # lines within the Issues output | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  | # optional parameter can be used to tell this function if the build was expected to fail or not | 
					
						
							|  |  |  | def checkLastBuild(expectedToFail=False): | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         # can't use waitForObject() 'cause visible is always 0 | 
					
						
							|  |  |  |         buildProg = findObject("{type='ProjectExplorer::Internal::BuildProgress' unnamed='1' }") | 
					
						
							|  |  |  |     except LookupError: | 
					
						
							|  |  |  |         test.log("checkLastBuild called without a build") | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2013-04-17 10:54:14 +02:00
										 |  |  |     ensureChecked(":Qt Creator_Issues_Core::Internal::OutputPaneToggleButton") | 
					
						
							|  |  |  |     model = waitForObject(":Qt Creator.Issues_QListView").model() | 
					
						
							|  |  |  |     buildIssues = dumpBuildIssues(model) | 
					
						
							|  |  |  |     errors = len(filter(lambda i: i[5] == "1", buildIssues)) | 
					
						
							|  |  |  |     warnings = len(filter(lambda i: i[5] == "2", buildIssues)) | 
					
						
							|  |  |  |     gotErrors = errors != 0 | 
					
						
							| 
									
										
										
										
											2011-09-26 15:24:49 +02:00
										 |  |  |     if not (gotErrors ^ expectedToFail): | 
					
						
							|  |  |  |         test.passes("Errors: %s | Warnings: %s" % (errors, warnings)) | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2011-09-26 15:24:49 +02:00
										 |  |  |         test.fail("Errors: %s | Warnings: %s" % (errors, warnings)) | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |     # additional stuff - could be removed... or improved :) | 
					
						
							| 
									
										
										
										
											2011-10-06 13:55:05 +02:00
										 |  |  |     test.log("Rows inside issues: %d" % model.rowCount()) | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |     if gotErrors and createTasksFileOnError: | 
					
						
							| 
									
										
										
										
											2013-04-17 10:54:14 +02:00
										 |  |  |         createTasksFile(buildIssues) | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |     return not gotErrors | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-05 11:00:32 +02:00
										 |  |  | # helper function to check the compilation when build wasn't successful | 
					
						
							|  |  |  | def checkCompile(): | 
					
						
							| 
									
										
										
										
											2012-09-05 16:49:35 +02:00
										 |  |  |     ensureChecked(":Qt Creator_CompileOutput_Core::Internal::OutputPaneToggleButton") | 
					
						
							| 
									
										
										
										
											2012-11-02 19:34:38 +01:00
										 |  |  |     output = waitForObject(":Qt Creator.Compile Output_Core::OutputWindow") | 
					
						
							| 
									
										
										
										
											2011-09-05 11:00:32 +02:00
										 |  |  |     waitFor("len(str(output.plainText))>0",5000) | 
					
						
							| 
									
										
										
										
											2013-02-04 11:08:38 +01:00
										 |  |  |     if compileSucceeded(output.plainText): | 
					
						
							| 
									
										
										
										
											2012-01-10 16:55:57 +01:00
										 |  |  |         if os.getenv("SYSTEST_DEBUG") == "1": | 
					
						
							|  |  |  |             test.log("Compile Output:\n%s" % output.plainText) | 
					
						
							| 
									
										
										
										
											2013-02-04 11:08:38 +01:00
										 |  |  |         test.passes("Compile successful") | 
					
						
							|  |  |  |         return True | 
					
						
							| 
									
										
										
										
											2011-09-05 11:00:32 +02:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2011-10-06 16:46:03 +02:00
										 |  |  |         test.fail("Compile Output:\n%s" % output.plainText) | 
					
						
							| 
									
										
										
										
											2013-02-04 11:08:38 +01:00
										 |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def compileSucceeded(compileOutput): | 
					
						
							|  |  |  |     return None != re.match(".*exited normally\.\n\d\d:\d\d:\d\d: Elapsed time: " | 
					
						
							|  |  |  |                             "(\d:)?\d{2}:\d\d\.$", str(compileOutput), re.S) | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-17 10:54:14 +02:00
										 |  |  | def dumpBuildIssues(listModel): | 
					
						
							|  |  |  |     issueDump = [] | 
					
						
							|  |  |  |     for row in range(listModel.rowCount()): | 
					
						
							|  |  |  |         index = listModel.index(row, 0) | 
					
						
							|  |  |  |         issueDump.extend([map(lambda role: index.data(role).toString(), | 
					
						
							|  |  |  |                               range(Qt.UserRole, Qt.UserRole + 6))]) | 
					
						
							|  |  |  |     return issueDump | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # helper method that writes a tasks file | 
					
						
							|  |  |  | def createTasksFile(buildIssues): | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |     global tasksFileDir, tasksFileCount | 
					
						
							|  |  |  |     if tasksFileDir == None: | 
					
						
							| 
									
										
										
										
											2011-09-05 15:00:01 +02:00
										 |  |  |             tasksFileDir = os.getcwd() + "/tasks" | 
					
						
							|  |  |  |             tasksFileDir = os.path.abspath(tasksFileDir) | 
					
						
							|  |  |  |     if not os.path.exists(tasksFileDir): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             os.makedirs(tasksFileDir) | 
					
						
							|  |  |  |         except OSError: | 
					
						
							|  |  |  |             test.log("Could not create %s - falling back to a temporary directory" % tasksFileDir) | 
					
						
							|  |  |  |             tasksFileDir = tempDir() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |     tasksFileCount += 1 | 
					
						
							|  |  |  |     outfile = os.path.join(tasksFileDir, os.path.basename(squishinfo.testCase)+"_%d.tasks" % tasksFileCount) | 
					
						
							|  |  |  |     file = codecs.open(outfile, "w", "utf-8") | 
					
						
							|  |  |  |     test.log("Writing tasks file - can take some time (according to number of issues)") | 
					
						
							| 
									
										
										
										
											2013-04-17 10:54:14 +02:00
										 |  |  |     rows = len(buildIssues) | 
					
						
							| 
									
										
										
										
											2012-02-03 14:19:01 +01:00
										 |  |  |     if os.environ.get("SYSTEST_DEBUG") == "1": | 
					
						
							|  |  |  |         firstrow = 0 | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         firstrow = max(0, rows - 100) | 
					
						
							| 
									
										
										
										
											2013-04-17 10:54:14 +02:00
										 |  |  |     for issue in buildIssues[firstrow:rows]: | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |         # the following is currently a bad work-around | 
					
						
							| 
									
										
										
										
											2013-04-17 10:54:14 +02:00
										 |  |  |         fData = issue[0] # file | 
					
						
							|  |  |  |         lData = issue[1] # line -> linenumber or empty | 
					
						
							|  |  |  |         tData = issue[5] # type -> 1==error 2==warning | 
					
						
							|  |  |  |         dData = issue[3] # description | 
					
						
							| 
									
										
										
										
											2011-09-01 14:09:25 +02:00
										 |  |  |         if lData == "": | 
					
						
							|  |  |  |             lData = "-1" | 
					
						
							|  |  |  |         if tData == "1": | 
					
						
							|  |  |  |             tData = "error" | 
					
						
							|  |  |  |         elif tData == "2": | 
					
						
							|  |  |  |             tData = "warning" | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             tData = "unknown" | 
					
						
							|  |  |  |         file.write("%s\t%s\t%s\t%s\n" % (fData, lData, tData, dData)) | 
					
						
							|  |  |  |     file.close() | 
					
						
							|  |  |  |     test.log("Written tasks file %s" % outfile) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-29 19:22:43 +01:00
										 |  |  | # returns a list of pairs each containing the zero based number of a kit | 
					
						
							|  |  |  | # and the name of the matching build configuration | 
					
						
							|  |  |  | # param kitCount specifies the number of kits currently defined (must be correct!) | 
					
						
							| 
									
										
										
										
											2012-01-17 13:47:47 +01:00
										 |  |  | # param filter is a regular expression to filter the configuration by their name | 
					
						
							| 
									
										
										
										
											2012-10-29 19:22:43 +01:00
										 |  |  | def iterateBuildConfigs(kitCount, filter = ""): | 
					
						
							| 
									
										
										
										
											2012-01-17 13:47:47 +01:00
										 |  |  |     switchViewTo(ViewConstants.PROJECTS) | 
					
						
							| 
									
										
										
										
											2012-10-29 19:22:43 +01:00
										 |  |  |     configs = [] | 
					
						
							|  |  |  |     for currentKit in range(kitCount): | 
					
						
							|  |  |  |         switchToBuildOrRunSettingsFor(kitCount, currentKit, ProjectSettings.BUILD) | 
					
						
							| 
									
										
										
										
											2012-11-02 19:34:38 +01:00
										 |  |  |         model = waitForObject(":scrollArea.Edit build configuration:_QComboBox").model() | 
					
						
							| 
									
										
										
										
											2012-10-29 19:22:43 +01:00
										 |  |  |         prog = re.compile(filter) | 
					
						
							|  |  |  |         # for each row in the model, write its data to a list | 
					
						
							|  |  |  |         configNames = dumpItems(model) | 
					
						
							|  |  |  |         # pick only those configuration names which pass the filter | 
					
						
							|  |  |  |         configs += zip([currentKit] * len(configNames), | 
					
						
							|  |  |  |                        [config for config in configNames if prog.match(config)]) | 
					
						
							| 
									
										
										
										
											2012-01-17 13:47:47 +01:00
										 |  |  |     switchViewTo(ViewConstants.EDIT) | 
					
						
							|  |  |  |     return configs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # selects a build configuration for building the current project | 
					
						
							|  |  |  | # param targetCount specifies the number of targets currently defined (must be correct!) | 
					
						
							|  |  |  | # param currentTarget specifies the target for which to switch into the specified settings (zero based index) | 
					
						
							|  |  |  | # param configName is the name of the configuration that should be selected | 
					
						
							| 
									
										
										
										
											2013-04-03 13:57:02 +02:00
										 |  |  | # returns information about the selected kit, see getQtInformationForBuildSettings | 
					
						
							| 
									
										
										
										
											2012-01-17 13:47:47 +01:00
										 |  |  | def selectBuildConfig(targetCount, currentTarget, configName): | 
					
						
							|  |  |  |     switchViewTo(ViewConstants.PROJECTS) | 
					
						
							|  |  |  |     switchToBuildOrRunSettingsFor(targetCount, currentTarget, ProjectSettings.BUILD) | 
					
						
							|  |  |  |     if selectFromCombo(":scrollArea.Edit build configuration:_QComboBox", configName): | 
					
						
							| 
									
										
										
										
											2013-04-25 19:08:55 +02:00
										 |  |  |         progressBarWait(30000) | 
					
						
							| 
									
										
										
										
											2013-04-03 13:57:02 +02:00
										 |  |  |     return getQtInformationForBuildSettings(targetCount, True, ViewConstants.EDIT) | 
					
						
							| 
									
										
										
										
											2012-03-26 14:13:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-11 17:38:58 +02:00
										 |  |  | # This will not trigger a rebuild. If needed, caller has to do this. | 
					
						
							|  |  |  | def verifyBuildConfig(targetCount, currentTarget, shouldBeDebug=False, enableShadowBuild=False, enableQmlDebug=False): | 
					
						
							| 
									
										
										
										
											2012-03-26 14:13:39 +02:00
										 |  |  |     switchViewTo(ViewConstants.PROJECTS) | 
					
						
							|  |  |  |     switchToBuildOrRunSettingsFor(targetCount, currentTarget, ProjectSettings.BUILD) | 
					
						
							| 
									
										
										
										
											2012-08-01 11:30:31 +02:00
										 |  |  |     ensureChecked(waitForObject(":scrollArea.Details_Utils::DetailsButton")) | 
					
						
							| 
									
										
										
										
											2012-03-26 14:13:39 +02:00
										 |  |  |     ensureChecked("{name='shadowBuildCheckBox' type='QCheckBox' visible='1'}", enableShadowBuild) | 
					
						
							|  |  |  |     buildCfCombo = waitForObject("{type='QComboBox' name='buildConfigurationComboBox' visible='1' " | 
					
						
							| 
									
										
										
										
											2012-08-01 11:30:31 +02:00
										 |  |  |                                  "window=':Qt Creator_Core::Internal::MainWindow'}") | 
					
						
							| 
									
										
										
										
											2012-03-26 14:13:39 +02:00
										 |  |  |     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") | 
					
						
							| 
									
										
										
										
											2012-05-11 17:38:58 +02:00
										 |  |  |     try: | 
					
						
							|  |  |  |         libLabel = waitForObject(":scrollArea.Library not available_QLabel", 2000) | 
					
						
							| 
									
										
										
										
											2012-08-01 11:30:31 +02:00
										 |  |  |         mouseClick(libLabel, libLabel.width - 10, libLabel.height / 2, 0, Qt.LeftButton) | 
					
						
							| 
									
										
										
										
											2012-05-11 17:38:58 +02:00
										 |  |  |     except: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  |     # Since waitForObject waits for the object to be enabled, | 
					
						
							|  |  |  |     # it will wait here until compilation of the debug libraries has finished. | 
					
						
							|  |  |  |     qmlDebugCheckbox = waitForObject(":scrollArea.qmlDebuggingLibraryCheckBox_QCheckBox", 150000) | 
					
						
							|  |  |  |     if qmlDebugCheckbox.checked != enableQmlDebug: | 
					
						
							|  |  |  |         clickButton(qmlDebugCheckbox) | 
					
						
							|  |  |  |         # Don't rebuild now | 
					
						
							|  |  |  |         clickButton(waitForObject(":QML Debugging.No_QPushButton", 5000)) | 
					
						
							| 
									
										
										
										
											2012-03-26 14:13:39 +02:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2012-08-01 11:30:31 +02:00
										 |  |  |         problemFound = waitForObject("{window=':Qt Creator_Core::Internal::MainWindow' " | 
					
						
							|  |  |  |                                      "type='QLabel' name='problemLabel' visible='1'}", 1000) | 
					
						
							| 
									
										
										
										
											2012-03-26 14:13:39 +02:00
										 |  |  |         if problemFound: | 
					
						
							|  |  |  |             test.warning('%s' % problemFound.text) | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2012-08-01 11:30:31 +02:00
										 |  |  |     clickButton(waitForObject(":scrollArea.Details_Utils::DetailsButton")) | 
					
						
							| 
									
										
										
										
											2012-03-26 14:13:39 +02:00
										 |  |  |     switchViewTo(ViewConstants.EDIT) |