forked from qt-creator/qt-creator
Squish: Test handling of read only files
Change-Id: I459fdaed7338f5343b760da47e9652baf78986f0 Reviewed-by: Robert Loehning <robert.loehning@digia.com>
This commit is contained in:
@@ -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'}
|
||||
|
@@ -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'}")
|
||||
|
33
tests/system/shared/fs_utils.py
Normal file
33
tests/system/shared/fs_utils.py
Normal file
@@ -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
|
@@ -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")
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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
|
||||
|
136
tests/system/suite_editors/tst_modify_readonly/test.py
Normal file
136
tests/system/suite_editors/tst_modify_readonly/test.py
Normal file
@@ -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")
|
Reference in New Issue
Block a user