def run(self, deviceTab): ''' Runs the keyboard event dialog. ''' log.debug("Running keyboard event dialog") self._deviceTab = deviceTab self.dialog.show()
def systemExec(processor, command, wait=True): ''' Executes the given system command. :param processor: A processor object calling the function :type processor: Processor :param command: A cammand to execute :type command: string :param wait: If True wait for termination of a command process :type wait: boolean :return: The command execution status, output and error :rtype: tuple ''' log.debug(str(locals())) # Reset the processor cache processor.cache = None stdout, stderr = '', '' try: cmd = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) status = True if wait: code = cmd.wait() log.info("System command '%s' returned with code: %d" % (command, code)) status = (code == 0) stdout, stderr = cmd.communicate() stdout = stdout or '' stderr = stderr or '' except: log.exception("Execute system command failure: %s" % command) return False, stdout, stderr return status, stdout, stderr
def run(self, deviceTab): ''' Runs the mouse event dialog. ''' log.debug("Running mouse event dialog") self._deviceTab = deviceTab self.dialog.show()
def systemPut(processor, path, data): ''' Puts the given data in a system file of the specified path. :param processor: A processor object calling the function :type processor: Processor :param path: A path to the system file :type path: string :return: True if success, False otherwise :rtype: boolean ''' log.debug(str(locals())) # Reset the processor cache processor.cache = None fd = None try: dir = os.path.dirname(path) if not os.path.exists(dir): log.info("Create intermediate directories of file path: %s" % path) os.makedirs(dir) fd = open(path, 'w') fd.write(data) except: log.exception("Get system file failure: %s" % path) return False finally: if fd: fd.close() return True
def _addDeviceTab(self, device): ''' Adds the device tab for given device. ''' log.debug("Adding device tab: %s" % device) tab = DeviceTab(device, self) self._tabs[device] = tab index = self._tabWidget.addTab(tab.tab, device.name) address, port = device.address if port: tooltip = "%s:%d" % (address, port) else: tooltip = address self._tabWidget.setTabToolTip(index, tooltip) self._tabWidget.setCurrentIndex(index) self._actionRefresh.triggered.connect(tab.refresh) self._actionRefreshAll.triggered.connect(tab.refreshAll) self._actionExpand.triggered.connect(tab.expand) self._actionExpandAll.triggered.connect(tab.expandAll) self._actionCollapse.triggered.connect(tab.collapse) self._actionCollapseAll.triggered.connect(tab.collapseAll) if not tab.isOffline(): self._actionSave.triggered.connect(tab.save) self._actionSaveAll.triggered.connect(tab.saveAll) self._actionButtons.buttonClicked.connect(tab.doAction) self._mouse.clicked.connect(self._callMouseDialog) self._keyboard.clicked.connect(self._callKeyboardDialog)
def accessibilityPutValue(processor, path, value): ''' Sets the given value in an accessible of the given path. :param processor: A processor object calling the function :type processor: Processor :param path: A path of the accessible :type path: tadek.core.accessible.Path :param value: New value of the accessible :type value: float :return: True if success, False otherwise :rtype: boolean ''' log.debug(str(locals())) try: # Get object from the processor cache or from the accessible provider if processor.cache and processor.cache[-1] == path: a11y, obj, path = processor.cache else: a11y, obj = providers.accessible(path) # Reset the processor cache processor.cache = None if obj is None: log.warning("Attempt of setting value for non-accessible") return False status = a11y.setValue(obj, value) except: log.exception("Set accessible value error: %s" % path) # Reset the processor cache before leaving processor.cache = None return False if not status: log.info("Set accessible value failure: %s" % path) return status
def _responseExpandAll(self, response): ''' Expands an accessible tree item from the response recursively. ''' path = response.accessible.path log.debug("Expanding accessible tree item recursively: %s" % path) if not response.status: return False accessible = response.accessible item = None if path.tuple: item = self._pathItem(path) if not item: log.warning("Invalid accessible tree path: %s" % path) return False # Update the item self._setAccessibleItem(accessible, item) item.setDisabled(False) else: self._treeWidget.clear() self._manualExpand = True if item: item.setExpanded(True) for child in accessible.children(): self._accessibleItem(child, item or self._treeWidget, recursive=True) for i in xrange(self._COLUMN_COUNT): self._treeWidget.resizeColumnToContents(i) self._manualExpand = False return True
def _openRecent(self): ''' Opens a recent dump file in a new tab. ''' path = self.sender().data() log.debug("Opening recent dump: '%s'" % path) self._open(path)
def getDevices(deviceArgs): ''' Converts command-line arguments representing devices. :param deviceArgs: Devices identifiers :type deviceArgs: list [string] :return: List of devices :rtype: list [tadek.connection.device.Device] ''' log.debug("Get devices from command-line arguments: %s" % deviceArgs) deviceList = [] if deviceArgs is None or deviceArgs == [None]: log.info("Using default device %s:%d" % (devices.DEFAULT_IP, devices.DEFAULT_PORT) ) deviceList.append(Device('localhost', devices.DEFAULT_IP, devices.DEFAULT_PORT)) else: for arg in deviceArgs: device = devices.get(arg) if device is None: address = arg.split(':') if len(address) == 2: address, port = address port = int(port) elif len(address) == 1: address, port = address[0], devices.DEFAULT_PORT else: exitWithError("Invalid format of a device: %s" % arg) device = Device(address + ':' + str(port), address, port) log.info("Adding a device: %s=%s:%d" % (device.name, device.address[0], device.address[1])) deviceList.append(device) return deviceList
def addTab(self, result, title, tooltip=None, select=False, closable=True): ''' Creates and returns a tab containing a tree of test result items based on given result and title. Optional parameters are: - tooptip: a tooltip message of the tab, if not provided the title is used instead - select: a boolean that determines whether tree items should be selected while adding - closable: a boolean that determines if the tab can be closed manually ''' log.debug("Adding tab: %s" % title) tab = ResultTab(self, result, select, closable) self._actionExpand.triggered.connect(tab.expand) self._actionExpandAll.triggered.connect(tab.expandAll) self._actionCollapse.triggered.connect(tab.collapse) self._actionCollapseAll.triggered.connect(tab.collapseAll) if title in self._tabs: remTab = self._tabs.pop(title) self._actionExpand.triggered.disconnect(remTab.expand) self._actionExpandAll.triggered.disconnect(remTab.expandAll) self._actionCollapse.triggered.disconnect(remTab.collapse) self._actionCollapseAll.triggered.disconnect(remTab.collapseAll) self._tabWidget.removeTab(self._tabWidget.indexOf(remTab.tab)) index = self._tabWidget.addTab(tab.tab, title) self._tabWidget.setTabToolTip(index, tooltip or title) self._tabWidget.setCurrentWidget(tab.tab) self._tabs[title] = tab return tab
def _openDialog(self): ''' Opens selected files containing test results in tabs. ''' log.debug("Opening result file") readableChannels = {} for c in [c for c in channels.get() if isinstance(c, channels.TestResultFileChannel)]: desc = "%s (*.%s)" % (c.name, c.fileExt().strip(".")) readableChannels[desc] = c if not readableChannels: dialogs.runWarning("There are no readable channels available") return dialog = QtGui.QFileDialog(self.view) dialog.setFileMode(QtGui.QFileDialog.ExistingFiles) dialog.setFilter(";;".join(readableChannels)) if not dialog.exec_(): log.debug("Opening result file was cancelled") return channel = readableChannels[dialog.selectedFilter()] for path in dialog.selectedFiles(): try: self.addTab(channel.read(path), os.path.split(path)[1], tooltip=path) self._updateRecentFiles(path) except Exception, ex: dialogs.runError("Error occurred while loading result file " "'%s':\n%s" % (path, ex))
def _startTests(self): ''' Starts execution of tests. ''' log.debug("Starting tests") self._actionStart.setVisible(False) devices = self._devices.getChecked() if not devices: runWarning("Select some devices first") self._actionStart.setVisible(True) return tests = self._tests.getCheckedTests() if not tests: self._actionStart.setVisible(True) return if sum([test.count() for test in tests]) == 0: runWarning("Selected test suites do not contain any test cases") self._actionStart.setVisible(True) return self._suiteRuns = 0 self._todoSuites = len(tests) self._testResult = testresult.TestResult() self._testRunner = TestRunner(devices, tests, self._testResult) self._devices.deviceChecked.connect(self._testRunner.addDevice) self._devices.deviceUnchecked.connect(self._testRunner.removeDevice) self._devices.setWarning(True) self._testRunner.start() self._actionStop.setVisible(True) self._actionPause.setVisible(True)
def collapse(self): ''' Collapses currently selected tree item. ''' if self._view.isTabCurrent(self): log.debug("Collapsing selected tree item") self._treeWidget.collapseItem(self._treeWidget.currentItem())
def _onStopped(self): ''' Shows summary dialog after finishing test executions. ''' log.debug("All tests finished") self._actionStart.setVisible(True) self._actionStop.setVisible(False) self._actionPause.setVisible(False) self._actionResume.setVisible(False) self._devices.deviceChecked.disconnect(self._testRunner.addDevice) self._devices.deviceUnchecked.disconnect(self._testRunner.removeDevice) self._devices.setWarning(False) files = [] for c in self._testRunner.result.get(): if isinstance(c, channels.TestResultFileChannel) and c.isActive(): files.append((c.name, c.filePath())) dialog = ReportDialog( self._testResult.get(name='_ui_summary')[0].getSummary(), files, len(self._devices.getChecked()) > 0) dialog.closed.connect(self._progress.reset, type=QtCore.Qt.DirectConnection) dialog.runAgainClicked.connect(self._startTests, type=QtCore.Qt.QueuedConnection) dialog.showDetailsClicked.connect(self._showDetails) dialog.run()
def systemGet(processor, path): ''' Gets content data of a system file of the given path. :param processor: A processor object calling the function :type processor: Processor :param path: A path to the system file :type path: string :return: The file content data or None :rtype: string ''' log.debug(str(locals())) # Reset the processor cache processor.cache = None if not os.path.exists(path): log.warning("Attempt of getting not existing system file: %s" % path) return False, '' fd = None try: fd = open(path, 'r') data = fd.read() except: log.exception("Get system file failure: %s" % path) return False, '' finally: if fd: fd.close() return True, data
def _loadState(self): """ Loads window's settings from configuration. """ log.debug("Loading main window's settings") if self._views: index = config.getInt(self._NAME, "views", "last", 0) view = self._views[0] try: view = self._views[index] except IndexError: log.error("Failed to load view #%d" % index) view.activate() section = "geometry" self.window.setGeometry( config.getInt(self._NAME, section, "window_x", 50), config.getInt(self._NAME, section, "window_y", 50), config.getInt(self._NAME, section, "window_w", 800), config.getInt(self._NAME, section, "window_h", 600), ) state = config.get(self._NAME, section, "window_state") if state: byteData = QtCore.QByteArray.fromBase64(state) self.window.restoreState(byteData)
def _disconnectAll(self): ''' Disconnects all devices. ''' log.debug("Disconnecting all devices") for dev in devices.all(): self._updateConnectionState(False, dev)
def _accept(self): ''' Accepts provided device data. ''' log.debug("Accepting device data") # Test provided name name = self._name.text() if not name: dialogs.runError("'name' field is required") return # Test provided address address = self._address.currentText() if not address: dialogs.runError("'address' field is required") return if ((not self._device or self._device.name != name) and devices.get(name) is not None): dialogs.runError("'%s' name already in use" % name) return self.params = { "name": name, "description": self._desc.text() or '', "address": address, "port": self._port.value(), "connect": self._connect.isChecked(), "autoconnect": self._autoconnect.isChecked() } self._lastAddresses.add(address) self.dialog.accept()
def getDevices(deviceArgs): ''' Converts command-line arguments representing devices. :param deviceArgs: Devices identifiers :type deviceArgs: list [string] :return: List of devices :rtype: list [tadek.connection.device.Device] ''' log.debug("Get devices from command-line arguments: %s" % deviceArgs) deviceList = [] if deviceArgs is None or deviceArgs == [None]: log.info("Using default device %s:%d" % (devices.DEFAULT_IP, devices.DEFAULT_PORT)) deviceList.append( Device('localhost', devices.DEFAULT_IP, devices.DEFAULT_PORT)) else: for arg in deviceArgs: device = devices.get(arg) if device is None: address = arg.split(':') if len(address) == 2: address, port = address port = int(port) elif len(address) == 1: address, port = address[0], devices.DEFAULT_PORT else: exitWithError("Invalid format of a device: %s" % arg) device = Device(address + ':' + str(port), address, port) log.info("Adding a device: %s=%s:%d" % (device.name, device.address[0], device.address[1])) deviceList.append(device) return deviceList
def _editDevice(self): ''' Runs the 'Edit device' dialog for currently selected device. ''' items = self._deviceList.selectedItems() if not items: return dev = devices.get(items[0].text(0)) log.debug("Editing device: %s" % dev) dialog = DeviceConfigDialog(dev) if not dialog.run(): return connect = dialog.params.pop("connect", False) if dev.name != dialog.params["name"]: self._updateConnectionState(False, dev) devices.remove(dev.name) index = self._deviceList.indexOfTopLevelItem(items[0]) self._deviceList.takeTopLevelItem(index) dev = devices.add(type=Device, **dialog.params) self._addDeviceItem(dev) else: address = dialog.params["address"] port = dialog.params["port"] if dev.address != (address, port): self._updateConnectionState(False, dev) devices.update(**dialog.params) self._deviceItems[dev].updateDevice() log.info("Device edited: %s" % dev) if connect: self._updateConnectionState(True, dev)
def run(self): ''' Runs the manage devices dialog. ''' log.debug("Running manage devices dialog") self._refresh() self.dialog.show()
def printResult(result): ''' Prints the given test result. ''' log.debug("Print test result: %s" % result) summary = result.get(name=SUMMARY_CHANNEL)[0].getSummary() log.info("Print summary of test execution results: %s" % summary) report = "Ran %d of %d test cases in %s" % (summary[COUNTER_TESTS_RUN], summary[COUNTER_N_TESTS], summary[COUNTER_RUN_TIME]) print '\n', report printSeparator(len(report)) if summary[STATUS_PASSED]: print "Tests passed:\t\t%d" % summary[STATUS_PASSED] if summary[STATUS_FAILED]: print "Tests failed:\t\t%d" % summary[STATUS_FAILED] if summary[STATUS_NOT_COMPLETED]: print "Tests not completed:\t%d" % summary[STATUS_NOT_COMPLETED] if summary[COUNTER_CORE_DUMPS]: print "Core dumps:\t\t%d" % summary[COUNTER_CORE_DUMPS] if summary[STATUS_ERROR]: print "Tests error:\t\t%d" % summary[STATUS_ERROR] filechls = [chl for chl in result.get(cls=channels.TestResultFileChannel) if chl.isActive()] if filechls: print "Result file:" if len(filechls) == 1 else "Result files:" for channel in filechls: print "\t%s" % channel.filePath() printSeparator() status = (1 if (summary[STATUS_FAILED] + summary[STATUS_ERROR] + summary[STATUS_NOT_COMPLETED]) else 0) exitWithStatus("FAILURE" if status else "SUCCESS", status)
def _connectAll(self): ''' Connects all devices. ''' log.debug("Connecting all devices") for dev in devices.all(): self._updateConnectionState(True, dev)
def _openRecent(self): ''' Opens a recent file containing test results in tabs. ''' log.debug("Opening recent result file") path = self.sender().data() ext = os.path.splitext(path)[1] channel = None for c in channels.get(): if (isinstance(c, channels.TestResultFileChannel) and c.fileExt() == ext): channel = c break if not channel: dialogs.runWarning("There are no readable channels accepting " "'%s' files" % ext) return try: self.addTab(channel.read(path), os.path.split(path)[1], tooltip=path) except Exception, ex: dialogs.runError("Error occurred while loading result file:\n%s" % str(ex))
def _openDialog(self): ''' Opens selected files containing test results in tabs. ''' log.debug("Opening result file") readableChannels = {} for c in [ c for c in channels.get() if isinstance(c, channels.TestResultFileChannel) ]: desc = "%s (*.%s)" % (c.name, c.fileExt().strip(".")) readableChannels[desc] = c if not readableChannels: dialogs.runWarning("There are no readable channels available") return dialog = QtGui.QFileDialog(self.view) dialog.setFileMode(QtGui.QFileDialog.ExistingFiles) dialog.setFilter(";;".join(readableChannels)) if not dialog.exec_(): log.debug("Opening result file was cancelled") return channel = readableChannels[dialog.selectedFilter()] for path in dialog.selectedFiles(): try: self.addTab(channel.read(path), os.path.split(path)[1], tooltip=path) self._updateRecentFiles(path) except Exception, ex: dialogs.runError("Error occurred while loading result file " "'%s':\n%s" % (path, ex))
def unload(self): ''' Disconnect and unload all current devices from the dialog. ''' log.debug("Unloading device list") for dev in devices.all(): self._updateConnectionState(False, dev)
def updateDevice(self): ''' Updates the displayed name and address of the device. ''' log.debug("Updating dev item: %s" % self._device) self.setText(0, self._device.name) self.setText(1, "%s:%d" % self._device.address) self._updateButton()
def update(self, result): ''' Selects and updates status of a tree item corresponding to given result. ''' log.debug("Selecting tree item for result '%s'" % result.id) item = self._getItem(result.id) self._setItemStatus(item) self._treeWidget.setCurrentItem(item)
def saveState(self): ''' Saves the view's settings to configuration. ''' log.debug("Saving settings of view: %s" % self.NAME) for name in filter(lambda name: "splitter" in name, self._elements): config.set(self.NAME, self._CONFIG_SECTION_GEOMETRY, name.lower(), str(self._elements[name].saveState().toBase64()))
def accessibilityGet(processor, path, depth, name=False, description=False, role=False, count=False, position=False, size=False, text=False, value=False, actions=False, states=False, attributes=False, relations=False): ''' Gets an accessible of the given path and depth including specified accessible parameters. :param processor: A processor object calling the function :type processor: Processor :param path: A path of a demanded accessible :type path: tadek.core.accessible.Path :param depth: A depth of a demanded accessible tree :type depth: integer :param name: True if a demanded accessible should include name :type name: boolean :param description: True if a demanded accessible should include description :type description: boolean :param role: True if a demanded accessible should include role :type role: boolean :param count: True if a demanded accessible should include child count :type count: boolean :param position: True if a demanded accessible should include position :type position: boolean :param size: True if a demanded accessible should include size :type size: boolean :param text: True if a demanded accessible should include text :type text: boolean :param value: True if a demanded accessible should include value :type value: boolean :param actions: True if a demanded accessible should include actions :type actions: boolean :param states: True if a demanded accessible should include states :type states: boolean :param attributes: True if a demanded accessible should include attributes :type attributes: boolean :param relations: True if a demanded accessible should include relations :type relations: bool :return: A getting accessible status and an accessible of the given path :rtype: tuple ''' log.debug(str(locals())) # Reset the processor cache processor.cache = None try: a11y, obj = providers.accessible(path) if a11y is None and path.tuple: log.info("Get accessible of requested path failure: %s" % path) return False, Accessible(path) processor.cache = (a11y, obj, path) return True, dumpAccessible(a11y, obj, path, depth=depth, name=name, description=description, role=role, count=count, position=position, size=size, text=text, value=value, actions=actions, states=states, attributes=attributes, relations=relations) except: log.exception("Get accessible of requested path error: %s" % path) return False, Accessible(path)
def collapseAll(self): ''' Collapses all items of tree. ''' if self._view.isTabCurrent(self): log.debug("Collapsing all tree items") self._treeWidget.collapseAll() for i in xrange(self._COLUMN_COUNT): self._treeWidget.resizeColumnToContents(i)
def expandAll(self): ''' Expands all items in the tree. ''' if self._view.isTabCurrent(self): log.debug("Expanding all tree items") self._treeWidget.expandAll() for i in xrange(self._COLUMN_COUNT): self._treeWidget.resizeColumnToContents(i)
def refresh(self): ''' Refreshes details of a test result that corresponds to the currently selected item. ''' log.debug("Refreshing currently selected result item") item = self._treeWidget.currentItem() self._treeWidget.setCurrentItem(None) self._treeWidget.setCurrentItem(item)
def _showDetails(self): ''' Shows execution result in Result view. ''' resultView = self._parent.getView("result") if resultView is not None: log.debug("Showing details in Result view") resultView.activate() resultView.showLastResult()
def _hideConsole(self): ''' Hides the console widget. ''' if self._widgetConsole.isVisible(): log.debug("Hiding console output") self._widgetConsole.setVisible(False) self._buttonShowConsole.setVisible(True) self._buttonHideConsole.setVisible(False)