From d766c2e77342ea3a3f6cb8f999d66569bf299d4e Mon Sep 17 00:00:00 2001 From: Christian Stenger <christian.stenger@nokia.com> Date: Fri, 10 Feb 2012 16:25:08 +0100 Subject: [PATCH] Squish: Use single file for workarounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This would help to keep the normal tests clean and mess up only a single file that contains all workarounds. Change-Id: Ic26e57bcd13663efe9c882c003909eb0caa6fe9e Reviewed-by: Robert Löhning <robert.loehning@nokia.com> Reviewed-by: Bill King <bill.king@nokia.com> --- tests/system/shared/qtcreator.py | 1 + tests/system/shared/workarounds.py | 182 ++++++++++++++++++ .../tst_basic_cpp_support/test.py | 3 +- .../suite_general/tst_select_all/test.py | 3 +- 4 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 tests/system/shared/workarounds.py diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py index 7e7841afafd..29cbd7e305a 100644 --- a/tests/system/shared/qtcreator.py +++ b/tests/system/shared/qtcreator.py @@ -22,6 +22,7 @@ source("../../shared/editor_utils.py") source("../../shared/project_explorer.py") source("../../shared/hook_utils.py") source("../../shared/debugger.py") +source("../../shared/workarounds.py") def waitForCleanShutdown(timeOut=10): appCtxt = currentApplicationContext() diff --git a/tests/system/shared/workarounds.py b/tests/system/shared/workarounds.py new file mode 100644 index 00000000000..c665a7540de --- /dev/null +++ b/tests/system/shared/workarounds.py @@ -0,0 +1,182 @@ +import urllib2 +import re + +JIRA_URL='https://bugreports.qt-project.org/browse' + +class JIRA: + __instance__ = None + + # Helper class + class Bug: + CREATOR = 'QTCREATORBUG' + SIMULATOR = 'QTSIM' + SDK = 'QTSDK' + QT = 'QTBUG' + QT_QUICKCOMPONENTS = 'QTCOMPONENTS' + + # constructor of JIRA + def __init__(self, number, bugType=Bug.CREATOR): + if JIRA.__instance__ == None: + JIRA.__instance__ = JIRA.__impl(number, bugType) + JIRA.__dict__['_JIRA__instance__'] = JIRA.__instance__ + else: + JIRA.__instance__._bugType = bugType + JIRA.__instance__._number = number + JIRA.__instance__.__fetchStatusAndResolutionFromJira__() + + # overriden to make it possible to use JIRA just like the + # underlying implementation (__impl) + def __getattr__(self, attr): + return getattr(self.__instance__, attr) + + # overriden to make it possible to use JIRA just like the + # underlying implementation (__impl) + def __setattr__(self, attr, value): + return setattr(self.__instance__, attr, value) + + # function to get an instance of the singleton + @staticmethod + def getInstance(): + if '_JIRA__instance__' in JIRA.__dict__: + return JIRA.__instance__ + else: + return JIRA.__impl(0, Bug.CREATOR) + + # function to check if the given bug is open or not + @staticmethod + def isBugStillOpen(number, bugType=Bug.CREATOR): + tmpJIRA = JIRA(number, bugType) + return tmpJIRA.isOpen() + + # function similar to performWorkaroundForBug - but it will execute the + # workaround (function) only if the bug is still open + # returns True if the workaround function has been executed, False otherwise + @staticmethod + def performWorkaroundIfStillOpen(number, bugType=Bug.CREATOR, *args): + if JIRA.isBugStillOpen(number, bugType): + return JIRA.performWorkaroundForBug(number, bugType, *args) + else: + test.warning("Bug is closed... skipping workaround!", + "You should remove potential code inside performWorkaroundForBug()") + return False + + # function that performs the workaround (function) for the given bug + # if the function needs additional arguments pass them as 3rd parameter + @staticmethod + def performWorkaroundForBug(number, bugType=Bug.CREATOR, *args): + functionToCall = JIRA.getInstance().__bugs__.get("%s-%d" % (bugType, number), None) + if functionToCall: + test.warning("Using workaround for %s-%d" % (bugType, number)) + functionToCall(*args) + return True + else: + JIRA.getInstance()._exitFatal_(bugType, number) + return False + + # implementation of JIRA singleton + class __impl: + # constructor of __impl + def __init__(self, number, bugType): + self._number = number + self._bugType = bugType + self._localOnly = os.getenv("SYSTEST_JIRA_NO_LOOKUP")=="1" + self.__initBugDict__() + self.__fetchStatusAndResolutionFromJira__() + + # function to retrieve the status of the current bug + def getStatus(self): + return self._status + + # function to retrieve the resolution of the current bug + def getResolution(self): + return self._resolution + + # this function checks the resolution of the given bug + # and returns True if the bug can still be assumed as 'Open' and False otherwise + def isOpen(self): + # handle special cases + if self._resolution == None: + return True + if self._resolution in ('Duplicate', 'Moved', 'Incomplete', 'Cannot Reproduce', 'Invalid'): + test.warning("Resolution of bug is '%s' - assuming 'Open' for now." % self._resolution, + "Please check the bugreport manually and update this test.") + return True + return self._resolution != 'Done' + + # this function tries to fetch the status and resolution from JIRA for the given bug + # if this isn't possible or the lookup is disabled it does only check the internal + # dict whether a function for the given bug is deposited or not + def __fetchStatusAndResolutionFromJira__(self): + global JIRA_URL + data = None + if not self._localOnly: + try: + bugReport = urllib2.urlopen('%s/%s-%d' % (JIRA_URL, self._bugType, self._number)) + data = bugReport.read() + except: + data = self.__tryExternalTools__() + if data == None: + test.warning("Sorry, ssl module missing - cannot fetch data via HTTPS", + "Try to install the ssl module by yourself, or set the python " + "path inside SQUISHDIR/etc/paths.ini to use a python version with " + "ssl support OR install wget or curl to get rid of this warning!") + self._localOnly = True + if data == None: + if '%s-%d' % (self._bugType, self._number) in self.__bugs__: + test.warning("Using internal dict - bug status could have changed already", + "Please check manually!") + self._status = None + self._resolution = None + return + else: + test.fatal("No workaround function deposited for %s-%d" % (self._bugType, self._number)) + self._resolution = 'Done' + return + else: + data = data.replace("\r", "").replace("\n", "") + resPattern = re.compile('<span\s+id="resolution-val".*?>(?P<resolution>.*?)</span>') + statPattern = re.compile('<span\s+id="status-val".*?>(.*?<img.*?>)?(?P<status>.*?)</span>') + status = statPattern.search(data) + resolution = resPattern.search(data) + if status: + self._status = status.group("status").strip() + else: + test.fatal("FATAL: Cannot get status of bugreport %s-%d" % (self._bugType, self._number), + "Looks like JIRA has changed.... Please verify!") + self._status = None + if resolution: + self._resolution = resolution.group("resolution").strip() + else: + test.fatal("FATAL: Cannot get resolution of bugreport %s-%d" % (self._bugType, self._number), + "Looks like JIRA has changed.... Please verify!") + self._resolution = None + + # simple helper function - used as fallback if python has no ssl support + # tries to find curl or wget in PATH and fetches data with it instead of + # using urllib2 + def __tryExternalTools__(self): + global JIRA_URL + cmdAndArgs = { 'curl':'-k', 'wget':'-qO-' } + for call in cmdAndArgs: + prog = which(call) + if prog: + return getOutputFromCmdline("%s %s %s/%s-%d" % (prog, cmdAndArgs[call], JIRA_URL, self._bugType, self._number)) + return None + + # this function initializes the bug dict for localOnly usage and + # for later lookup which function to call for which bug + # ALWAYS update this dict when adding a new function for a workaround! + def __initBugDict__(self): + self.__bugs__= { + 'QTCREATORBUG-6918':self._workaroundCreator_MacEditorFocus_, + 'QTCREATORBUG-6953':self._workaroundCreator_MacEditorFocus_ + } + # helper function - will be called if no workaround for the requested bug is deposited + def _exitFatal_(self, bugType, number): + test.fatal("No workaround found for bug %s-%d" % (bugType, number)) + +############### functions that hold workarounds ################################# + + def _workaroundCreator_MacEditorFocus_(self, *args): + editor = args[0] + nativeMouseClick(editor.mapToGlobal(QPoint(50, 50)).x, editor.mapToGlobal(QPoint(50, 50)).y, Qt.LeftButton) diff --git a/tests/system/suite_general/tst_basic_cpp_support/test.py b/tests/system/suite_general/tst_basic_cpp_support/test.py index 65bcf69c996..76adf075793 100644 --- a/tests/system/suite_general/tst_basic_cpp_support/test.py +++ b/tests/system/suite_general/tst_basic_cpp_support/test.py @@ -25,8 +25,7 @@ def main(): # - Press F2 or select from the menu: Tools / C++ / Follow Symbol under Cursor # Creator will show you the declaration of the variable. - # workaround because of QTCREATORBUG-6953 - nativeMouseClick(cppwindow.mapToGlobal(QPoint(50, 50)).x, cppwindow.mapToGlobal(QPoint(50, 50)).y, Qt.LeftButton) + JIRA.performWorkaroundIfStillOpen(6953, JIRA.Bug.CREATOR, cppwindow) type(cppwindow, "<Ctrl+F>") type(waitForObject(":*Qt Creator.findEdit_Utils::FilterLineEdit"), " xi") type(waitForObject(":*Qt Creator.findEdit_Utils::FilterLineEdit"), "<Return>") diff --git a/tests/system/suite_general/tst_select_all/test.py b/tests/system/suite_general/tst_select_all/test.py index fa9d9c25092..690bebdfe21 100644 --- a/tests/system/suite_general/tst_select_all/test.py +++ b/tests/system/suite_general/tst_select_all/test.py @@ -25,8 +25,7 @@ def main(): selectFromFileDialog(currentFile) editor = waitForObject("{type='%s' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}" % filesAndEditors[currentFile], 20000) - # needed on Mac because of QTCREATORBUG-6918 - nativeMouseClick(editor.mapToGlobal(QPoint(50, 50)).x, editor.mapToGlobal(QPoint(50, 50)).y, Qt.LeftButton) + JIRA.performWorkaroundIfStillOpen(6918, JIRA.Bug.CREATOR, editor) for key in ["<Up>", "<Down>", "<Left>", "<Right>"]: test.log("Selecting everything") invokeMenuItem("Edit", "Select All") -- GitLab