diff options
author | Christian Stenger <christian.stenger@digia.com> | 2012-10-19 17:36:14 +0200 |
---|---|---|
committer | Christian Stenger <christian.stenger@digia.com> | 2012-11-01 17:09:40 +0100 |
commit | 47289addff4e23f049d38ad368defe77d403a56a (patch) | |
tree | 3800ac2a461d23e498c5609fb9245991c13a95eb /tests | |
parent | 270207f77e60bcb60bcd9d134f4b17ad79f4cdfd (diff) | |
download | qt-creator-47289addff4e23f049d38ad368defe77d403a56a.tar.gz |
Squish: Test handling of read only files
Change-Id: I459fdaed7338f5343b760da47e9652baf78986f0
Reviewed-by: Robert Loehning <robert.loehning@digia.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/system/objects.map | 3 | ||||
-rw-r--r-- | tests/system/shared/editor_utils.py | 6 | ||||
-rw-r--r-- | tests/system/shared/fs_utils.py | 33 | ||||
-rw-r--r-- | tests/system/shared/qtcreator.py | 1 | ||||
-rw-r--r-- | tests/system/suite_debugger/tst_cli_output_console/test.py | 3 | ||||
-rw-r--r-- | tests/system/suite_editors/suite.conf | 2 | ||||
-rw-r--r-- | tests/system/suite_editors/tst_modify_readonly/test.py | 136 |
7 files changed, 177 insertions, 7 deletions
diff --git a/tests/system/objects.map b/tests/system/objects.map index 98896e6c4f..a8f6172529 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -54,6 +54,7 @@ :Next_QPushButton {text~='(Next.*|Continue)' type='QPushButton' visible='1'} :Open File.File name:_QLabel {name='fileNameLabel' text='File name:' type='QLabel' visible='1' window=':Open File_QFileDialog'} :Open File_QFileDialog {name='QFileDialog' type='QFileDialog' visible='1' windowTitle='Open File'} +:OpenDocuments_QTreeView {name='editorList' type='QTreeView' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :OpenProject_QStyleItem {clip='false' container=':Qt Creator_QDeclarativeView' enabled='true' text='Open Project' type='LinkedText' unnamed='1' visible='true'} :Options.Cancel_QPushButton {text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':Options_Core::Internal::SettingsDialog'} :Options.OK_QPushButton {text='OK' type='QPushButton' unnamed='1' visible='1' window=':Options_Core::Internal::SettingsDialog'} @@ -87,10 +88,12 @@ :Qt Creator_Core::Internal::CommandComboBox {type='Core::Internal::CommandComboBox' 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_FilenameQComboBox {type='QComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Find::Internal::SearchResultTreeView {type='Find::Internal::SearchResultTreeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Help::Internal::HelpViewer {type='Help::Internal::HelpViewer' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_HelpSelector_QComboBox {occurrence='3' type='QComboBox' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_Issues_Core::Internal::OutputPaneToggleButton {occurrence='1' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} +:Qt Creator_ProFileEditorWidget {type='Qt4ProjectManager::Internal::ProFileEditorWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_QDeclarativeView {type='QDeclarativeView' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'} :Qt Creator_QHelpContentWidget {type='QHelpContentWidget' 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'} diff --git a/tests/system/shared/editor_utils.py b/tests/system/shared/editor_utils.py index 7f96fc189b..7200725346 100644 --- a/tests/system/shared/editor_utils.py +++ b/tests/system/shared/editor_utils.py @@ -218,13 +218,11 @@ def getEditorForFileSuffix(curFile): glslEditorSuffixes= ["frag", "vert", "fsh", "vsh", "glsl", "shader", "gsh"] suffix = __getFileSuffix__(curFile) if suffix in cppEditorSuffixes: - editor = waitForObject("{type='CppEditor::Internal::CPPEditorWidget' unnamed='1' " - "visible='1' window=':Qt Creator_Core::Internal::MainWindow'}") + editor = waitForObject(":Qt Creator_CppEditor::Internal::CPPEditorWidget") elif suffix in qmlEditorSuffixes: editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget") elif suffix in proEditorSuffixes: - editor = waitForObject("{type='Qt4ProjectManager::Internal::ProFileEditorWidget' unnamed='1' " - "visible='1' window=':Qt Creator_Core::Internal::MainWindow'}") + editor = waitForObject(":Qt Creator_ProFileEditorWidget") elif suffix in glslEditorSuffixes: editor = waitForObject("{type='GLSLEditor::GLSLTextEditorWidget' unnamed='1' " "visible='1' window=':Qt Creator_Core::Internal::MainWindow'}") diff --git a/tests/system/shared/fs_utils.py b/tests/system/shared/fs_utils.py new file mode 100644 index 0000000000..b261860a01 --- /dev/null +++ b/tests/system/shared/fs_utils.py @@ -0,0 +1,33 @@ +import stat + +# this function modifies all (regular) files inside the given dirPath to have specified permissions +# ATTENTION: it won't process the directory recursively +def changeFilePermissions(dirPath, readPerm, writePerm, excludeFileNames=None): + permission = 0 + if readPerm: + permission |= stat.S_IREAD + if writePerm: + permission |= stat.S_IWRITE + if excludeFileNames == None: + excludeFileNames = [] + elif isinstance(excludeFileNames, (str, unicode)): + excludeFileNames = [excludeFileNames] + if not isinstance(excludeFileNames, (tuple, list)): + test.warning("File names to exclude must be of type str, unicode, list, tuple or None - " + "ignoring parameter this time.") + excludeFileNames = [] + if not os.path.isdir(dirPath): + test.warning("Could not find directory '%s'." % dirPath) + return False + filePaths = [os.path.join(dirPath, fileName) for fileName in os.listdir(dirPath) + if fileName not in excludeFileNames] + for filePath in filter(os.path.isfile, filePaths): + os.chmod(filePath, permission) + return True + +def isWritable(pathToFile): + if os.path.exists(pathToFile): + return os.access(pathToFile, os.W_OK) + else: + test.warning("Path to check for writability does not exist.") + return False diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py index e48fe4ad37..66324cc7af 100644 --- a/tests/system/shared/qtcreator.py +++ b/tests/system/shared/qtcreator.py @@ -17,6 +17,7 @@ testSettings.logScreenshotOnError = True source("../../shared/classes.py") source("../../shared/utils.py") +source("../../shared/fs_utils.py") source("../../shared/build_utils.py") source("../../shared/project.py") source("../../shared/editor_utils.py") diff --git a/tests/system/suite_debugger/tst_cli_output_console/test.py b/tests/system/suite_debugger/tst_cli_output_console/test.py index f04e0e4959..6900aef542 100644 --- a/tests/system/suite_debugger/tst_cli_output_console/test.py +++ b/tests/system/suite_debugger/tst_cli_output_console/test.py @@ -31,8 +31,7 @@ def main(): # 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) + proEditor = waitForObject(":Qt Creator_ProFileEditorWidget", 20000) test.verify("CONFIG += console" in str(proEditor.plainText), "Verifying that program is configured with console") setRunInTerminal(1, 0, False) diff --git a/tests/system/suite_editors/suite.conf b/tests/system/suite_editors/suite.conf index 46c8bb025c..5a93d56846 100644 --- a/tests/system/suite_editors/suite.conf +++ b/tests/system/suite_editors/suite.conf @@ -7,6 +7,6 @@ HOOK_SUB_PROCESSES=false IMPLICITAUTSTART=0 LANGUAGE=Python OBJECTMAP=../objects.map -TEST_CASES=tst_memberoperator tst_rename_macros tst_basic_cpp_support tst_select_all tst_qml_indent tst_qml_editor +TEST_CASES=tst_basic_cpp_support tst_memberoperator tst_modify_readonly tst_qml_editor tst_qml_indent tst_rename_macros tst_select_all VERSION=2 WRAPPERS=Qt diff --git a/tests/system/suite_editors/tst_modify_readonly/test.py b/tests/system/suite_editors/tst_modify_readonly/test.py new file mode 100644 index 0000000000..c5de75a853 --- /dev/null +++ b/tests/system/suite_editors/tst_modify_readonly/test.py @@ -0,0 +1,136 @@ +source("../../shared/qtcreator.py") + +def main(): + global testFolder + cppEditorStr = ":Qt Creator_CppEditor::Internal::CPPEditorWidget" + proEditorStr = ":Qt Creator_ProFileEditorWidget" + testFolder = prepareTemplate(os.path.abspath(os.path.join(os.getcwd(), "..", "shared", + "simplePlainCPP"))) + if testFolder == None: + test.fatal("Could not prepare test files - leaving test") + return + if not changeFilePermissions(testFolder, True, False, "testfiles.pro"): + test.fatal("Could not set permissions for files to read-only - test will likely fail.") + startApplication("qtcreator" + SettingsPath) + openQmakeProject(os.path.join(testFolder, "testfiles.pro")) + modifiedUnsaved = [] + readOnlyFiles = [] + currentFile = testModifyFile("testfiles.Sources.main\\.cpp", cppEditorStr, "{", True) + modifiedUnsaved.append(currentFile) + readOnlyFiles.append(currentFile) + currentFile = testModifyFile("testfiles.testfiles\\.pro", proEditorStr, "CONFIG -= qt", False) + modifiedUnsaved.append(currentFile) + currentFile = testModifyFile("testfiles.Headers.testfile\\.h", cppEditorStr, "{", True) + modifiedUnsaved.append(currentFile) + readOnlyFiles.append(currentFile) + invokeMenuItem("File", "Exit") + testSaveChangesAndMakeWritable(modifiedUnsaved, readOnlyFiles) + +def testModifyFile(fileName, editor, line, expectWarning): + readOnlyWarningStr = ("{text='<b>Warning:</b> You are changing a read-only file.' type='QLabel'" + " unnamed='1' window=':Qt Creator_Core::Internal::MainWindow'}") + simpleFName = simpleFileName(fileName) + test.log("Opening file '%s'" % simpleFName) + openDocument(fileName) + fileNameCombo = waitForObject(":Qt Creator_FilenameQComboBox") + test.compare(str(fileNameCombo.currentText), simpleFName, + "Verifying content of file name combo box.") + checkOpenDocumentsContains(simpleFName) + if not placeCursorToLine(editor, line): + return + type(editor, "<Return>") + try: + waitForObject(readOnlyWarningStr, 3000) + if expectWarning: + test.passes("Warning about changing a read-only file appeared.") + else: + test.fail("Warning about changing a read-only file appeared, although changing " + "a writable file. (%s)" % simpleFName) + except: + if expectWarning: + test.fail("Warning about changing a read-only file missing. (%s)" % simpleFName) + else: + test.passes("Warning about changing a read-only file does not come up " + "(changing a writable file).") + test.compare(str(fileNameCombo.currentText), "%s*" % simpleFName, + "Verifying content of file name combo box.") + return checkOpenDocumentsContains("%s*" % simpleFName) + +def testSaveChangesAndMakeWritable(modifiedFiles, readOnlyFiles): + saveDlgStr = ("{name='Core__Internal__SaveItemsDialog' type='Core::Internal::SaveItemsDialog' " + "visible='1' windowTitle='Save Changes'}") + readOnlyMBoxStr = ("{type='QMessageBox' unnamed='1' visible='1' text~='The file <i>.+</i> " + "is read only\.'}") + cannotResetStr = ("{text='Cannot set permissions to writable.' type='QMessageBox' " + "unnamed='1' visible='1'}") + filePattern = re.compile('The file <i>(.+)</i> is read only\.') + try: + waitForObject(saveDlgStr) + except: + test.fail("Save Changes dialog did not come up, but was expected to appear.") + return + treeWidget = waitForObject("{name='treeWidget' type='QTreeWidget' visible='1' window=%s}" + % saveDlgStr) + checkUnsavedChangesContains(treeWidget.model(), modifiedFiles) + clickButton(waitForObject("{text='Save All' type='QPushButton' unnamed='1' visible='1' " + "window=%s}" % saveDlgStr)) + # iterating over the readOnlyFiles (order is unpredictable) + for i in range(len(readOnlyFiles)): + try: + currentText = str(waitForObject(readOnlyMBoxStr, 3000).text) + currentFile = filePattern.match(currentText).group(1) + clickButton(waitForObject("{text='Make Writable' type='QPushButton' unnamed='1' " + "visible='1' window=%s}" % readOnlyMBoxStr)) + try: + waitForObject(cannotResetStr, 3000) + # should not be possible + test.fail("Could not reset file '%s' to writable state." % currentFile) + clickButton("{text='OK' type='QPushButton' window=%s}" % cannotResetStr) + except: + if isWritable(currentFile): + test.passes("File '%s' resetted to writable state and saved." % currentFile) + if currentFile in readOnlyFiles: + readOnlyFiles.remove(currentFile) + else: + test.fatal("Creator states file '%s' is read-only - but supposed to be " + "writable." % currentFile) + else: + test.fail("Creator states file '%s' had been made writable - " + "but it's still read only." % currentFile) + except: + test.fail("Missing QMessageBox about a read only file.") + if not test.verify(len(readOnlyFiles) == 0, + "Checking whether all files have been handled correctly."): + try: + invokeMenuItem("File", "Exit") + waitForObject(saveDlgStr) + clickButton(waitForObject("{text='Do not Save' type='QPushButton' unnamed='1' " + "visible='1' window=%s}" % saveDlgStr)) + except: + pass + +def checkOpenDocumentsContains(itemName): + openDocsTreeViewModel = waitForObject(":OpenDocuments_QTreeView").model() + result = None + found = False + for index in dumpIndices(openDocsTreeViewModel): + if str(index.data()) == itemName: + found = True + result = index.toolTip + break + test.verify(found, "Check whether 'Open Documents' contains '%s'" % itemName) + return result + +def checkUnsavedChangesContains(model, filePaths): + foundItems = map(lambda x: os.path.join(x[0], x[1]), zip(dumpItems(model,column=1), + dumpItems(model, column=0))) + test.compare(set(foundItems), set(filePaths), + "Verifying whether modified (unsaved) files do match expected.") + +def simpleFileName(navigatorFileName): + return ".".join(navigatorFileName.split(".")[-2:]).replace("\\","") + +def cleanup(): + global testFolder + if testFolder: + changeFilePermissions(testFolder, True, True, "testfiles.pro") |